infinity-context 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1053) hide show
  1. infinity_context-0.1.0.dist-info/METADATA +239 -0
  2. infinity_context-0.1.0.dist-info/RECORD +1053 -0
  3. infinity_context-0.1.0.dist-info/WHEEL +5 -0
  4. infinity_context-0.1.0.dist-info/entry_points.txt +9 -0
  5. infinity_context-0.1.0.dist-info/licenses/LICENSE +201 -0
  6. infinity_context-0.1.0.dist-info/top_level.txt +8 -0
  7. infinity_context_adapters/__init__.py +1 -0
  8. infinity_context_adapters/cognee/__init__.py +5 -0
  9. infinity_context_adapters/cognee/adapter.py +364 -0
  10. infinity_context_adapters/embeddings/__init__.py +6 -0
  11. infinity_context_adapters/embeddings/noop_adapter.py +5 -0
  12. infinity_context_adapters/embeddings/openai_adapter.py +104 -0
  13. infinity_context_adapters/extraction/__init__.py +41 -0
  14. infinity_context_adapters/extraction/content.py +828 -0
  15. infinity_context_adapters/extraction/docling_engine.py +255 -0
  16. infinity_context_adapters/extraction/document_normalization.py +434 -0
  17. infinity_context_adapters/extraction/factory.py +69 -0
  18. infinity_context_adapters/extraction/fallback_context.py +137 -0
  19. infinity_context_adapters/extraction/file_detection.py +378 -0
  20. infinity_context_adapters/extraction/image_evidence.py +319 -0
  21. infinity_context_adapters/extraction/media_tools.py +579 -0
  22. infinity_context_adapters/extraction/openai_json.py +356 -0
  23. infinity_context_adapters/extraction/openai_vision.py +722 -0
  24. infinity_context_adapters/extraction/prompts/__init__.py +1 -0
  25. infinity_context_adapters/extraction/prompts/semantic_memory_v1.md +20 -0
  26. infinity_context_adapters/extraction/schemas/__init__.py +1 -0
  27. infinity_context_adapters/extraction/schemas/semantic_memory_v1.json +62 -0
  28. infinity_context_adapters/extraction/transcription/__init__.py +11 -0
  29. infinity_context_adapters/extraction/transcription/openai_adapter.py +400 -0
  30. infinity_context_adapters/extraction/transcription_engine.py +544 -0
  31. infinity_context_adapters/extraction/video_evidence.py +129 -0
  32. infinity_context_adapters/extraction/whisper_engine.py +386 -0
  33. infinity_context_adapters/features/__init__.py +7 -0
  34. infinity_context_adapters/features/context_building/__init__.py +53 -0
  35. infinity_context_adapters/features/context_building/candidate_provider_chain.py +68 -0
  36. infinity_context_adapters/features/context_building/graphiti_candidate_provider.py +44 -0
  37. infinity_context_adapters/features/context_building/in_memory_candidate_provider.py +62 -0
  38. infinity_context_adapters/features/context_building/postgres_candidate_provider.py +44 -0
  39. infinity_context_adapters/features/context_building/qdrant_candidate_provider.py +44 -0
  40. infinity_context_adapters/features/context_building/query_request.py +99 -0
  41. infinity_context_adapters/features/context_building/records.py +113 -0
  42. infinity_context_adapters/features/document_ingestion/__init__.py +74 -0
  43. infinity_context_adapters/features/document_ingestion/composition.py +69 -0
  44. infinity_context_adapters/features/document_ingestion/extraction_adapter.py +114 -0
  45. infinity_context_adapters/features/document_ingestion/in_memory_chunk_index.py +67 -0
  46. infinity_context_adapters/features/document_ingestion/in_memory_document_store.py +176 -0
  47. infinity_context_adapters/features/document_ingestion/postgres_document_store.py +110 -0
  48. infinity_context_adapters/features/document_ingestion/qdrant_chunk_index.py +49 -0
  49. infinity_context_adapters/features/document_ingestion/records.py +88 -0
  50. infinity_context_adapters/features/memory_facts/__init__.py +53 -0
  51. infinity_context_adapters/features/memory_facts/graphiti_fact_projection.py +111 -0
  52. infinity_context_adapters/features/memory_facts/in_memory_fact_store.py +200 -0
  53. infinity_context_adapters/features/memory_facts/postgres_fact_store.py +126 -0
  54. infinity_context_adapters/features/memory_facts/qdrant_fact_projection.py +100 -0
  55. infinity_context_adapters/features/memory_scopes/__init__.py +44 -0
  56. infinity_context_adapters/features/memory_scopes/in_memory_scope_store.py +189 -0
  57. infinity_context_adapters/features/memory_scopes/postgres_scope_store.py +121 -0
  58. infinity_context_adapters/features/memory_scopes/records.py +86 -0
  59. infinity_context_adapters/graphiti/__init__.py +5 -0
  60. infinity_context_adapters/graphiti/adapter.py +613 -0
  61. infinity_context_adapters/graphiti/identity_evidence.py +711 -0
  62. infinity_context_adapters/graphiti/scope_identity.py +31 -0
  63. infinity_context_adapters/local_blob.py +101 -0
  64. infinity_context_adapters/noop/__init__.py +16 -0
  65. infinity_context_adapters/noop/adapters.py +156 -0
  66. infinity_context_adapters/noop/runtime.py +21 -0
  67. infinity_context_adapters/postgres/__init__.py +19 -0
  68. infinity_context_adapters/postgres/asset_mappers.py +348 -0
  69. infinity_context_adapters/postgres/asset_repositories.py +865 -0
  70. infinity_context_adapters/postgres/benchmark_projection_schema.py +241 -0
  71. infinity_context_adapters/postgres/benchmark_run_completion.py +645 -0
  72. infinity_context_adapters/postgres/benchmark_run_repositories.py +908 -0
  73. infinity_context_adapters/postgres/benchmark_writer_fence.py +139 -0
  74. infinity_context_adapters/postgres/canonical_keyword_trigram.py +31 -0
  75. infinity_context_adapters/postgres/canonical_retrieval_batching.py +388 -0
  76. infinity_context_adapters/postgres/fact_repositories.py +766 -0
  77. infinity_context_adapters/postgres/mappers.py +745 -0
  78. infinity_context_adapters/postgres/migrations/0001_core_facts.sql +95 -0
  79. infinity_context_adapters/postgres/migrations/0002_threads_documents_chunks.sql +97 -0
  80. infinity_context_adapters/postgres/migrations/0003_suggestions.sql +24 -0
  81. infinity_context_adapters/postgres/migrations/0004_service_tokens.sql +16 -0
  82. infinity_context_adapters/postgres/migrations/0005_data_classification_lite.sql +8 -0
  83. infinity_context_adapters/postgres/migrations/0006_service_token_usage_metadata.sql +5 -0
  84. infinity_context_adapters/postgres/migrations/0007_service_token_permissions.sql +2 -0
  85. infinity_context_adapters/postgres/migrations/0008_service_token_memory_scope.sql +2 -0
  86. infinity_context_adapters/postgres/migrations/0009_outbox_lifecycle_hardening.sql +15 -0
  87. infinity_context_adapters/postgres/migrations/0010_fact_taxonomy.sql +14 -0
  88. infinity_context_adapters/postgres/migrations/0011_asset_extractions.sql +66 -0
  89. infinity_context_adapters/postgres/migrations/0012_asset_extraction_execution_hardening.sql +20 -0
  90. infinity_context_adapters/postgres/migrations/0012_usage_governance.sql +33 -0
  91. infinity_context_adapters/postgres/migrations/0013_context_link_suggestions.sql +44 -0
  92. infinity_context_adapters/postgres/migrations/0014_memory_anchors.sql +26 -0
  93. infinity_context_adapters/postgres/migrations/0015_users_acl.sql +36 -0
  94. infinity_context_adapters/postgres/migrations/0016_managed_benchmark_runs.sql +27 -0
  95. infinity_context_adapters/postgres/migrations/0017_managed_benchmark_writer_fence.sql +104 -0
  96. infinity_context_adapters/postgres/migrations/0018_benchmark_projection_manifest.sql +51 -0
  97. infinity_context_adapters/postgres/migrations/0019_managed_benchmark_sealed_fence.sql +131 -0
  98. infinity_context_adapters/postgres/migrations/0020_benchmark_cleanup_completion.sql +219 -0
  99. infinity_context_adapters/postgres/migrations/0021_benchmark_unsealed_abort.sql +64 -0
  100. infinity_context_adapters/postgres/migrations/0022_canonical_keyword_trigram.sql +5 -0
  101. infinity_context_adapters/postgres/models.py +878 -0
  102. infinity_context_adapters/postgres/projection_fence.py +80 -0
  103. infinity_context_adapters/postgres/repositories.py +906 -0
  104. infinity_context_adapters/postgres/repository_helpers.py +115 -0
  105. infinity_context_adapters/postgres/scope_repositories.py +540 -0
  106. infinity_context_adapters/postgres/unit_of_work.py +785 -0
  107. infinity_context_adapters/postgres/usage_repositories.py +128 -0
  108. infinity_context_adapters/postgres/user_repositories.py +164 -0
  109. infinity_context_adapters/provider_errors.py +73 -0
  110. infinity_context_adapters/qdrant/__init__.py +5 -0
  111. infinity_context_adapters/qdrant/identity_evidence.py +504 -0
  112. infinity_context_adapters/qdrant/vector_adapter.py +718 -0
  113. infinity_context_adapters/s3_blob.py +242 -0
  114. infinity_context_cli/__init__.py +5 -0
  115. infinity_context_cli/__main__.py +6 -0
  116. infinity_context_cli/cli.py +964 -0
  117. infinity_context_cli/config.py +184 -0
  118. infinity_context_cli/doctor.py +397 -0
  119. infinity_context_cli/local_experience.py +250 -0
  120. infinity_context_cli/mcp_config.py +124 -0
  121. infinity_context_cli/onboarding.py +542 -0
  122. infinity_context_cli/runtime.py +179 -0
  123. infinity_context_contracts/__init__.py +16 -0
  124. infinity_context_contracts/_json.py +32 -0
  125. infinity_context_contracts/capabilities.py +67 -0
  126. infinity_context_contracts/common.py +54 -0
  127. infinity_context_contracts/features/__init__.py +12 -0
  128. infinity_context_contracts/features/context_building.py +248 -0
  129. infinity_context_contracts/features/document_ingestion.py +277 -0
  130. infinity_context_contracts/features/memory_facts.py +236 -0
  131. infinity_context_contracts/features/memory_scopes.py +329 -0
  132. infinity_context_contracts/health.py +23 -0
  133. infinity_context_core/__init__.py +76 -0
  134. infinity_context_core/agent_behavior_contract.py +72 -0
  135. infinity_context_core/application/__init__.py +580 -0
  136. infinity_context_core/application/anchor_creative_work_filters.py +148 -0
  137. infinity_context_core/application/anchor_event_extraction.py +1571 -0
  138. infinity_context_core/application/anchor_extraction.py +1144 -0
  139. infinity_context_core/application/anchor_identity_normalization.py +90 -0
  140. infinity_context_core/application/anchor_relation_projection.py +203 -0
  141. infinity_context_core/application/anchor_temporal_window.py +172 -0
  142. infinity_context_core/application/asset_extraction_mapping.py +236 -0
  143. infinity_context_core/application/asset_upload_policy.py +952 -0
  144. infinity_context_core/application/auto_apply.py +72 -0
  145. infinity_context_core/application/auto_memory.py +527 -0
  146. infinity_context_core/application/capture_policy.py +61 -0
  147. infinity_context_core/application/chunker.py +93 -0
  148. infinity_context_core/application/context_action_role_evidence.py +890 -0
  149. infinity_context_core/application/context_action_role_labels.py +176 -0
  150. infinity_context_core/application/context_action_roles.py +2365 -0
  151. infinity_context_core/application/context_action_subject_policy.py +71 -0
  152. infinity_context_core/application/context_activity_companion.py +120 -0
  153. infinity_context_core/application/context_activity_duration_rerank.py +118 -0
  154. infinity_context_core/application/context_activity_participant_grounding.py +87 -0
  155. infinity_context_core/application/context_aggregation_answer_slots.py +586 -0
  156. infinity_context_core/application/context_aggregation_evidence_text.py +409 -0
  157. infinity_context_core/application/context_aggregation_rerank.py +145 -0
  158. infinity_context_core/application/context_aggregation_subject.py +137 -0
  159. infinity_context_core/application/context_allergy_condition_inference.py +146 -0
  160. infinity_context_core/application/context_anchor_identity.py +157 -0
  161. infinity_context_core/application/context_anchor_intent_ranking.py +84 -0
  162. infinity_context_core/application/context_anchor_relations.py +67 -0
  163. infinity_context_core/application/context_anchors.py +393 -0
  164. infinity_context_core/application/context_answer_evidence_types.py +14 -0
  165. infinity_context_core/application/context_answer_unit_shapes.py +207 -0
  166. infinity_context_core/application/context_artifact_evidence.py +893 -0
  167. infinity_context_core/application/context_attribution_lexicon.py +254 -0
  168. infinity_context_core/application/context_awareness_cause_rerank.py +109 -0
  169. infinity_context_core/application/context_baby_birth_evidence.py +91 -0
  170. infinity_context_core/application/context_birdwatching_schedule_rerank.py +130 -0
  171. infinity_context_core/application/context_bm25_ranking.py +450 -0
  172. infinity_context_core/application/context_book_author_preference_exact_turns.py +110 -0
  173. infinity_context_core/application/context_building_legacy_candidate_adapter.py +530 -0
  174. infinity_context_core/application/context_canonical_fact_retrieval.py +409 -0
  175. infinity_context_core/application/context_causal_reason_rerank.py +145 -0
  176. infinity_context_core/application/context_choice_reason_rerank.py +109 -0
  177. infinity_context_core/application/context_collectors.py +931 -0
  178. infinity_context_core/application/context_commonality_rerank.py +428 -0
  179. infinity_context_core/application/context_community_membership_inference.py +139 -0
  180. infinity_context_core/application/context_competition_count_exact_turns.py +383 -0
  181. infinity_context_core/application/context_conflicting_evidence_rerank.py +282 -0
  182. infinity_context_core/application/context_conversation_counterparty.py +260 -0
  183. infinity_context_core/application/context_count_cardinality.py +164 -0
  184. infinity_context_core/application/context_creative_work_count_exact_turns.py +517 -0
  185. infinity_context_core/application/context_diagnostics.py +55 -0
  186. infinity_context_core/application/context_diagnostics_bundle_keys.py +433 -0
  187. infinity_context_core/application/context_diagnostics_bundle_projection.py +711 -0
  188. infinity_context_core/application/context_diagnostics_item_projection.py +410 -0
  189. infinity_context_core/application/context_diagnostics_primitives.py +131 -0
  190. infinity_context_core/application/context_diagnostics_ranking.py +143 -0
  191. infinity_context_core/application/context_diagnostics_signals.py +209 -0
  192. infinity_context_core/application/context_diagnostics_sources.py +82 -0
  193. infinity_context_core/application/context_dialogue_authority.py +382 -0
  194. infinity_context_core/application/context_distinct_set_evidence.py +994 -0
  195. infinity_context_core/application/context_distinct_set_selection.py +335 -0
  196. infinity_context_core/application/context_domain_rerank_apply.py +310 -0
  197. infinity_context_core/application/context_domain_rerank_signals.py +2391 -0
  198. infinity_context_core/application/context_domain_rerank_types.py +14 -0
  199. infinity_context_core/application/context_english_activity_displacement_answer_support.py +128 -0
  200. infinity_context_core/application/context_english_lifestyle_inference.py +122 -0
  201. infinity_context_core/application/context_english_lifestyle_inference_answer_support.py +291 -0
  202. infinity_context_core/application/context_english_temporal_dates.py +53 -0
  203. infinity_context_core/application/context_evidence_priority.py +262 -0
  204. infinity_context_core/application/context_evidence_reservation_safety.py +208 -0
  205. infinity_context_core/application/context_exercise_performance_rerank.py +71 -0
  206. infinity_context_core/application/context_food_inventory_exact_turns.py +583 -0
  207. infinity_context_core/application/context_frequency_rerank.py +109 -0
  208. infinity_context_core/application/context_future_plan_timing_rerank.py +110 -0
  209. infinity_context_core/application/context_generic_behavior_inference.py +348 -0
  210. infinity_context_core/application/context_geo_residence_aliases.py +149 -0
  211. infinity_context_core/application/context_hydration.py +329 -0
  212. infinity_context_core/application/context_identity_fact_rerank.py +362 -0
  213. infinity_context_core/application/context_identity_rerank.py +76 -0
  214. infinity_context_core/application/context_identity_terms.py +15 -0
  215. infinity_context_core/application/context_inference_evidence.py +484 -0
  216. infinity_context_core/application/context_inference_evidence_terms.py +744 -0
  217. infinity_context_core/application/context_internal_diagnostics.py +61 -0
  218. infinity_context_core/application/context_item_evidence.py +108 -0
  219. infinity_context_core/application/context_item_purchase_evidence.py +49 -0
  220. infinity_context_core/application/context_keyword_aggregation_prefilter.py +63 -0
  221. infinity_context_core/application/context_keyword_ranking.py +178 -0
  222. infinity_context_core/application/context_lexical.py +750 -0
  223. infinity_context_core/application/context_lifecycle_rerank.py +502 -0
  224. infinity_context_core/application/context_link_candidate_policy.py +864 -0
  225. infinity_context_core/application/context_link_expansion.py +727 -0
  226. infinity_context_core/application/context_link_expansion_items.py +441 -0
  227. infinity_context_core/application/context_link_policy.py +451 -0
  228. infinity_context_core/application/context_link_source_enrichment.py +120 -0
  229. infinity_context_core/application/context_media_time.py +368 -0
  230. infinity_context_core/application/context_museum_visit_policy.py +66 -0
  231. infinity_context_core/application/context_named_person_preference.py +313 -0
  232. infinity_context_core/application/context_national_park_inference.py +93 -0
  233. infinity_context_core/application/context_object_attribute_rerank.py +416 -0
  234. infinity_context_core/application/context_object_mismatch.py +63 -0
  235. infinity_context_core/application/context_occupational_role_identity.py +961 -0
  236. infinity_context_core/application/context_ordinal_sequence.py +134 -0
  237. infinity_context_core/application/context_owner_grounding.py +408 -0
  238. infinity_context_core/application/context_packer.py +858 -0
  239. infinity_context_core/application/context_packer_answer_slots.py +733 -0
  240. infinity_context_core/application/context_packer_answer_support.py +3101 -0
  241. infinity_context_core/application/context_packer_answer_support_patterns.py +1267 -0
  242. infinity_context_core/application/context_packer_answer_support_slots.py +1209 -0
  243. infinity_context_core/application/context_packer_answer_support_utils.py +473 -0
  244. infinity_context_core/application/context_packer_diagnostics.py +48 -0
  245. infinity_context_core/application/context_packer_exact_literal_turns.py +697 -0
  246. infinity_context_core/application/context_packer_exact_prepasses.py +758 -0
  247. infinity_context_core/application/context_packer_exact_turn_utils.py +133 -0
  248. infinity_context_core/application/context_packer_identity_policy.py +155 -0
  249. infinity_context_core/application/context_packer_inference_reservation.py +113 -0
  250. infinity_context_core/application/context_packer_inventory_prepasses.py +359 -0
  251. infinity_context_core/application/context_packer_inventory_slots.py +771 -0
  252. infinity_context_core/application/context_packer_marker_coverage.py +409 -0
  253. infinity_context_core/application/context_packer_rendering.py +338 -0
  254. infinity_context_core/application/context_packer_selection.py +487 -0
  255. infinity_context_core/application/context_packer_source_policy.py +123 -0
  256. infinity_context_core/application/context_paired_evidence_requirements.py +78 -0
  257. infinity_context_core/application/context_paired_evidence_roles.py +64 -0
  258. infinity_context_core/application/context_person_activity_exact_turns.py +375 -0
  259. infinity_context_core/application/context_person_aliases.py +49 -0
  260. infinity_context_core/application/context_person_kinship.py +296 -0
  261. infinity_context_core/application/context_person_occupation.py +240 -0
  262. infinity_context_core/application/context_person_relation_inventory.py +755 -0
  263. infinity_context_core/application/context_person_residence.py +398 -0
  264. infinity_context_core/application/context_person_team_membership.py +305 -0
  265. infinity_context_core/application/context_pet_ownership.py +223 -0
  266. infinity_context_core/application/context_polarity_rerank.py +338 -0
  267. infinity_context_core/application/context_policy.py +107 -0
  268. infinity_context_core/application/context_political_inference.py +128 -0
  269. infinity_context_core/application/context_possession_source.py +161 -0
  270. infinity_context_core/application/context_precise_temporal_evidence.py +156 -0
  271. infinity_context_core/application/context_preference_goal_rerank.py +428 -0
  272. infinity_context_core/application/context_preference_inference.py +335 -0
  273. infinity_context_core/application/context_property_interaction_evidence.py +659 -0
  274. infinity_context_core/application/context_provider_retrieval_terms.py +95 -0
  275. infinity_context_core/application/context_quality.py +488 -0
  276. infinity_context_core/application/context_quantity_evidence_patterns.py +254 -0
  277. infinity_context_core/application/context_quantity_evidence_slots.py +750 -0
  278. infinity_context_core/application/context_quantity_pending_clothing.py +200 -0
  279. infinity_context_core/application/context_query_artifact_inventory_expansions.py +76 -0
  280. infinity_context_core/application/context_query_decomposition.py +879 -0
  281. infinity_context_core/application/context_query_decomposition_answer_policy.py +707 -0
  282. infinity_context_core/application/context_query_decomposition_contracts.py +28 -0
  283. infinity_context_core/application/context_query_decomposition_event_policy.py +535 -0
  284. infinity_context_core/application/context_query_decomposition_inventory_policy.py +767 -0
  285. infinity_context_core/application/context_query_decomposition_shared.py +300 -0
  286. infinity_context_core/application/context_query_duration.py +171 -0
  287. infinity_context_core/application/context_query_entity_relation_expansions.py +212 -0
  288. infinity_context_core/application/context_query_event_summary_expansions.py +80 -0
  289. infinity_context_core/application/context_query_expansion.py +200 -0
  290. infinity_context_core/application/context_query_expansion_rule_catalog_part1.py +1279 -0
  291. infinity_context_core/application/context_query_expansion_rule_catalog_part2.py +770 -0
  292. infinity_context_core/application/context_query_expansion_rule_catalog_part3.py +982 -0
  293. infinity_context_core/application/context_query_expansion_rule_catalog_part4.py +1334 -0
  294. infinity_context_core/application/context_query_expansion_rule_catalog_part5.py +517 -0
  295. infinity_context_core/application/context_query_expansion_rule_terms.py +269 -0
  296. infinity_context_core/application/context_query_expansion_rules.py +66 -0
  297. infinity_context_core/application/context_query_expansion_selection.py +892 -0
  298. infinity_context_core/application/context_query_financial_resources_inference.py +92 -0
  299. infinity_context_core/application/context_query_food_expansions.py +89 -0
  300. infinity_context_core/application/context_query_frequency.py +194 -0
  301. infinity_context_core/application/context_query_game_expansions.py +141 -0
  302. infinity_context_core/application/context_query_health_lifestyle_expansions.py +178 -0
  303. infinity_context_core/application/context_query_identity_terms.py +81 -0
  304. infinity_context_core/application/context_query_intent.py +33 -0
  305. infinity_context_core/application/context_query_intent_common.py +29 -0
  306. infinity_context_core/application/context_query_intent_contracts.py +92 -0
  307. infinity_context_core/application/context_query_intent_extraction.py +614 -0
  308. infinity_context_core/application/context_query_intent_keys.py +499 -0
  309. infinity_context_core/application/context_query_intent_matching.py +407 -0
  310. infinity_context_core/application/context_query_organization_summary_expansions.py +75 -0
  311. infinity_context_core/application/context_query_personal_fact_expansions.py +314 -0
  312. infinity_context_core/application/context_query_pet_activity_expansions.py +329 -0
  313. infinity_context_core/application/context_query_preference_expansions.py +97 -0
  314. infinity_context_core/application/context_query_project_summary_expansions.py +60 -0
  315. infinity_context_core/application/context_query_relevance_ranking.py +76 -0
  316. infinity_context_core/application/context_query_sports_expansions.py +48 -0
  317. infinity_context_core/application/context_query_state_transition.py +53 -0
  318. infinity_context_core/application/context_query_support_role.py +165 -0
  319. infinity_context_core/application/context_query_temporal_expansions.py +18 -0
  320. infinity_context_core/application/context_query_travel_expansions.py +134 -0
  321. infinity_context_core/application/context_query_vehicle_expansions.py +79 -0
  322. infinity_context_core/application/context_query_workflow_expansions.py +233 -0
  323. infinity_context_core/application/context_query_workflow_intent.py +65 -0
  324. infinity_context_core/application/context_quote_scanner.py +342 -0
  325. infinity_context_core/application/context_rank_dedupe.py +171 -0
  326. infinity_context_core/application/context_rank_fusion.py +191 -0
  327. infinity_context_core/application/context_ranked_activity_reservation.py +586 -0
  328. infinity_context_core/application/context_ranked_evidence_coverage_reservation.py +427 -0
  329. infinity_context_core/application/context_ranked_evidence_priority_reservation.py +37 -0
  330. infinity_context_core/application/context_ranked_evidence_selection.py +260 -0
  331. infinity_context_core/application/context_ranking.py +3681 -0
  332. infinity_context_core/application/context_ranking_reason_policy.py +31 -0
  333. infinity_context_core/application/context_ranking_reason_priorities.py +859 -0
  334. infinity_context_core/application/context_ranking_reason_scores.py +519 -0
  335. infinity_context_core/application/context_recommendation_answer_support.py +358 -0
  336. infinity_context_core/application/context_recommendation_exact_turns.py +360 -0
  337. infinity_context_core/application/context_relation_requirement.py +498 -0
  338. infinity_context_core/application/context_relationship_status_evidence.py +83 -0
  339. infinity_context_core/application/context_relative_duration_evidence.py +61 -0
  340. infinity_context_core/application/context_relevance.py +430 -0
  341. infinity_context_core/application/context_reported_obligation_attribution.py +416 -0
  342. infinity_context_core/application/context_reporting_frames.py +338 -0
  343. infinity_context_core/application/context_requirement_coverage.py +767 -0
  344. infinity_context_core/application/context_requirement_guard.py +503 -0
  345. infinity_context_core/application/context_requirement_patterns.py +943 -0
  346. infinity_context_core/application/context_requirement_ranking.py +181 -0
  347. infinity_context_core/application/context_requirement_signals.py +101 -0
  348. infinity_context_core/application/context_rerank_domain_heuristics.py +433 -0
  349. infinity_context_core/application/context_rerank_evidence_signals.py +400 -0
  350. infinity_context_core/application/context_rerank_relevance.py +131 -0
  351. infinity_context_core/application/context_retrieval_performance.py +153 -0
  352. infinity_context_core/application/context_review_items.py +338 -0
  353. infinity_context_core/application/context_score_signal_rerank.py +21 -0
  354. infinity_context_core/application/context_short_story_progress_evidence.py +119 -0
  355. infinity_context_core/application/context_snippets.py +545 -0
  356. infinity_context_core/application/context_social_education_inference.py +265 -0
  357. infinity_context_core/application/context_social_inventory_rerank.py +329 -0
  358. infinity_context_core/application/context_source_family.py +100 -0
  359. infinity_context_core/application/context_source_grounding.py +277 -0
  360. infinity_context_core/application/context_source_sibling_answer_evidence_repair.py +1983 -0
  361. infinity_context_core/application/context_source_sibling_contracts.py +35 -0
  362. infinity_context_core/application/context_source_sibling_evidence.py +405 -0
  363. infinity_context_core/application/context_source_sibling_evidence_rules.py +798 -0
  364. infinity_context_core/application/context_source_sibling_evidence_shared.py +449 -0
  365. infinity_context_core/application/context_source_sibling_identity.py +114 -0
  366. infinity_context_core/application/context_source_sibling_inventory_evidence.py +28 -0
  367. infinity_context_core/application/context_source_sibling_patterns.py +946 -0
  368. infinity_context_core/application/context_source_sibling_place_evidence.py +561 -0
  369. infinity_context_core/application/context_source_sibling_policy.py +988 -0
  370. infinity_context_core/application/context_source_sibling_scoring.py +721 -0
  371. infinity_context_core/application/context_source_siblings.py +363 -0
  372. infinity_context_core/application/context_speaker_attribution.py +574 -0
  373. infinity_context_core/application/context_speaker_disambiguation.py +108 -0
  374. infinity_context_core/application/context_stage_diagnostics.py +111 -0
  375. infinity_context_core/application/context_state_evidence.py +196 -0
  376. infinity_context_core/application/context_state_residence_inference.py +163 -0
  377. infinity_context_core/application/context_state_transition_pairing.py +401 -0
  378. infinity_context_core/application/context_temporal_answer_grounding.py +187 -0
  379. infinity_context_core/application/context_temporal_hints.py +485 -0
  380. infinity_context_core/application/context_temporal_intent_policy.py +146 -0
  381. infinity_context_core/application/context_temporal_interval_requirements.py +107 -0
  382. infinity_context_core/application/context_temporal_metadata.py +29 -0
  383. infinity_context_core/application/context_temporal_query.py +1358 -0
  384. infinity_context_core/application/context_temporal_ranges.py +471 -0
  385. infinity_context_core/application/context_temporal_session_order.py +439 -0
  386. infinity_context_core/application/context_temporal_source_identity.py +426 -0
  387. infinity_context_core/application/context_temporal_source_turn.py +1290 -0
  388. infinity_context_core/application/context_temporal_source_turn_labels.py +265 -0
  389. infinity_context_core/application/context_temporal_source_turn_patterns.py +186 -0
  390. infinity_context_core/application/context_temporal_source_turn_types.py +62 -0
  391. infinity_context_core/application/context_travel_hobby_writing_evidence.py +176 -0
  392. infinity_context_core/application/context_travel_place_evidence.py +23 -0
  393. infinity_context_core/application/document_fragments.py +206 -0
  394. infinity_context_core/application/document_text.py +203 -0
  395. infinity_context_core/application/dto.py +311 -0
  396. infinity_context_core/application/dto_anchors.py +143 -0
  397. infinity_context_core/application/dto_assets.py +234 -0
  398. infinity_context_core/application/dto_benchmark_runs.py +114 -0
  399. infinity_context_core/application/dto_context.py +176 -0
  400. infinity_context_core/application/dto_context_links.py +170 -0
  401. infinity_context_core/application/dto_facts.py +275 -0
  402. infinity_context_core/application/dto_suggestions_capture.py +199 -0
  403. infinity_context_core/application/dto_workspace.py +101 -0
  404. infinity_context_core/application/extraction_coordinates.py +56 -0
  405. infinity_context_core/application/extraction_resource_policy.py +796 -0
  406. infinity_context_core/application/extractor.py +147 -0
  407. infinity_context_core/application/memory_digest_renderer.py +215 -0
  408. infinity_context_core/application/multimodal_manifest.py +418 -0
  409. infinity_context_core/application/normalize.py +29 -0
  410. infinity_context_core/application/observed_anchor_resolution.py +243 -0
  411. infinity_context_core/application/related_facts.py +144 -0
  412. infinity_context_core/application/review_payloads.py +104 -0
  413. infinity_context_core/application/safe_payload.py +86 -0
  414. infinity_context_core/application/semantic_dedupe.py +943 -0
  415. infinity_context_core/application/sensitive_text.py +39 -0
  416. infinity_context_core/application/source_refs.py +263 -0
  417. infinity_context_core/application/storage_key_safety.py +13 -0
  418. infinity_context_core/application/temporal_validity.py +31 -0
  419. infinity_context_core/application/use_cases/__init__.py +1 -0
  420. infinity_context_core/application/use_cases/anchors.py +1165 -0
  421. infinity_context_core/application/use_cases/asset_extraction_support.py +273 -0
  422. infinity_context_core/application/use_cases/asset_extractions.py +1454 -0
  423. infinity_context_core/application/use_cases/assets.py +463 -0
  424. infinity_context_core/application/use_cases/benchmark_runs.py +877 -0
  425. infinity_context_core/application/use_cases/benchmark_unsealed_abort.py +147 -0
  426. infinity_context_core/application/use_cases/blob_storage_cleanup.py +289 -0
  427. infinity_context_core/application/use_cases/blob_storage_integrity.py +351 -0
  428. infinity_context_core/application/use_cases/build_context.py +995 -0
  429. infinity_context_core/application/use_cases/build_context_final_packing.py +59 -0
  430. infinity_context_core/application/use_cases/build_context_item_projection.py +839 -0
  431. infinity_context_core/application/use_cases/build_context_keyword_aggregation.py +908 -0
  432. infinity_context_core/application/use_cases/build_context_keyword_aggregation_seeds.py +132 -0
  433. infinity_context_core/application/use_cases/build_context_keyword_aggregation_selection.py +280 -0
  434. infinity_context_core/application/use_cases/build_context_keyword_aggregation_support.py +161 -0
  435. infinity_context_core/application/use_cases/build_context_requirement_guard.py +156 -0
  436. infinity_context_core/application/use_cases/build_context_source_selection.py +935 -0
  437. infinity_context_core/application/use_cases/build_memory_digest.py +203 -0
  438. infinity_context_core/application/use_cases/build_memory_insights.py +979 -0
  439. infinity_context_core/application/use_cases/consolidate_capture.py +806 -0
  440. infinity_context_core/application/use_cases/context_link_crud.py +196 -0
  441. infinity_context_core/application/use_cases/context_link_reviews.py +441 -0
  442. infinity_context_core/application/use_cases/context_link_suggestions.py +1060 -0
  443. infinity_context_core/application/use_cases/context_link_visibility.py +106 -0
  444. infinity_context_core/application/use_cases/context_links.py +33 -0
  445. infinity_context_core/application/use_cases/delete_document.py +71 -0
  446. infinity_context_core/application/use_cases/delete_thread_memory.py +55 -0
  447. infinity_context_core/application/use_cases/duplicate_merge_resolution.py +307 -0
  448. infinity_context_core/application/use_cases/ensure_scope.py +29 -0
  449. infinity_context_core/application/use_cases/expire_suggestions.py +36 -0
  450. infinity_context_core/application/use_cases/export_graph.py +684 -0
  451. infinity_context_core/application/use_cases/fact_relations.py +204 -0
  452. infinity_context_core/application/use_cases/forget_fact.py +43 -0
  453. infinity_context_core/application/use_cases/get_capabilities.py +213 -0
  454. infinity_context_core/application/use_cases/get_capture.py +16 -0
  455. infinity_context_core/application/use_cases/get_session_status.py +23 -0
  456. infinity_context_core/application/use_cases/ingest_document.py +376 -0
  457. infinity_context_core/application/use_cases/ingest_episode.py +263 -0
  458. infinity_context_core/application/use_cases/list_captures.py +25 -0
  459. infinity_context_core/application/use_cases/memory_browser.py +414 -0
  460. infinity_context_core/application/use_cases/operations_console.py +293 -0
  461. infinity_context_core/application/use_cases/process_document.py +83 -0
  462. infinity_context_core/application/use_cases/purge_capture.py +34 -0
  463. infinity_context_core/application/use_cases/query_documents.py +42 -0
  464. infinity_context_core/application/use_cases/query_facts.py +57 -0
  465. infinity_context_core/application/use_cases/receive_capture.py +238 -0
  466. infinity_context_core/application/use_cases/related_facts.py +47 -0
  467. infinity_context_core/application/use_cases/remember_fact.py +145 -0
  468. infinity_context_core/application/use_cases/spaces_memory_scopes.py +134 -0
  469. infinity_context_core/application/use_cases/suggestions.py +804 -0
  470. infinity_context_core/application/use_cases/update_fact.py +43 -0
  471. infinity_context_core/application/use_cases/usage.py +49 -0
  472. infinity_context_core/application/use_cases/users.py +138 -0
  473. infinity_context_core/domain/__init__.py +1 -0
  474. infinity_context_core/domain/aggregation_admission.py +200 -0
  475. infinity_context_core/domain/anchor_entities.py +316 -0
  476. infinity_context_core/domain/assets.py +654 -0
  477. infinity_context_core/domain/capture.py +321 -0
  478. infinity_context_core/domain/distinct_set_membership.py +69 -0
  479. infinity_context_core/domain/entities.py +103 -0
  480. infinity_context_core/domain/entity_policies.py +119 -0
  481. infinity_context_core/domain/entity_types.py +150 -0
  482. infinity_context_core/domain/errors.py +53 -0
  483. infinity_context_core/domain/events.py +14 -0
  484. infinity_context_core/domain/extraction.py +529 -0
  485. infinity_context_core/domain/idempotency.py +12 -0
  486. infinity_context_core/domain/memory_item_entities.py +426 -0
  487. infinity_context_core/domain/source_refs.py +91 -0
  488. infinity_context_core/domain/suggestion_entities.py +236 -0
  489. infinity_context_core/domain/taxonomy.py +121 -0
  490. infinity_context_core/domain/usage.py +221 -0
  491. infinity_context_core/domain/workspace_entities.py +269 -0
  492. infinity_context_core/features/__init__.py +7 -0
  493. infinity_context_core/features/context_building/__init__.py +3 -0
  494. infinity_context_core/features/context_building/application/__init__.py +92 -0
  495. infinity_context_core/features/context_building/application/candidate_fusion.py +136 -0
  496. infinity_context_core/features/context_building/application/coverage_reservation_selector.py +212 -0
  497. infinity_context_core/features/context_building/application/handlers.py +155 -0
  498. infinity_context_core/features/context_building/application/inference_evidence_reservation.py +592 -0
  499. infinity_context_core/features/context_building/application/provider_pipeline.py +61 -0
  500. infinity_context_core/features/context_building/application/queries.py +107 -0
  501. infinity_context_core/features/context_building/application/use_cases.py +78 -0
  502. infinity_context_core/features/context_building/domain/__init__.py +95 -0
  503. infinity_context_core/features/context_building/domain/budget.py +97 -0
  504. infinity_context_core/features/context_building/domain/context.py +157 -0
  505. infinity_context_core/features/context_building/domain/evidence_obligations.py +60 -0
  506. infinity_context_core/features/context_building/domain/feature.py +15 -0
  507. infinity_context_core/features/context_building/domain/prompt_sections.py +150 -0
  508. infinity_context_core/features/context_building/domain/query_pipeline.py +276 -0
  509. infinity_context_core/features/context_building/domain/rendering.py +102 -0
  510. infinity_context_core/features/context_building/ports/__init__.py +8 -0
  511. infinity_context_core/features/context_building/ports/candidates.py +36 -0
  512. infinity_context_core/features/context_building/public.py +165 -0
  513. infinity_context_core/features/context_building/tests/test_application_ports_public_skeleton.py +575 -0
  514. infinity_context_core/features/context_building/tests/test_domain_context_building_skeleton.py +402 -0
  515. infinity_context_core/features/document_ingestion/__init__.py +3 -0
  516. infinity_context_core/features/document_ingestion/application/__init__.py +31 -0
  517. infinity_context_core/features/document_ingestion/application/commands.py +62 -0
  518. infinity_context_core/features/document_ingestion/application/use_cases.py +273 -0
  519. infinity_context_core/features/document_ingestion/domain/__init__.py +61 -0
  520. infinity_context_core/features/document_ingestion/domain/chunking.py +297 -0
  521. infinity_context_core/features/document_ingestion/domain/errors.py +22 -0
  522. infinity_context_core/features/document_ingestion/domain/feature.py +18 -0
  523. infinity_context_core/features/document_ingestion/domain/source_document.py +228 -0
  524. infinity_context_core/features/document_ingestion/ports/__init__.py +21 -0
  525. infinity_context_core/features/document_ingestion/ports/indexing.py +51 -0
  526. infinity_context_core/features/document_ingestion/ports/repositories.py +56 -0
  527. infinity_context_core/features/document_ingestion/public.py +95 -0
  528. infinity_context_core/features/document_ingestion/tests/test_application_handlers.py +226 -0
  529. infinity_context_core/features/document_ingestion/tests/test_application_ports_public_skeleton.py +334 -0
  530. infinity_context_core/features/document_ingestion/tests/test_domain_chunking_skeleton.py +79 -0
  531. infinity_context_core/features/document_ingestion/tests/test_domain_source_document_skeleton.py +101 -0
  532. infinity_context_core/features/memory_facts/__init__.py +3 -0
  533. infinity_context_core/features/memory_facts/application/__init__.py +37 -0
  534. infinity_context_core/features/memory_facts/application/commands.py +89 -0
  535. infinity_context_core/features/memory_facts/application/handlers.py +241 -0
  536. infinity_context_core/features/memory_facts/application/use_cases.py +47 -0
  537. infinity_context_core/features/memory_facts/domain/__init__.py +35 -0
  538. infinity_context_core/features/memory_facts/domain/fact.py +98 -0
  539. infinity_context_core/features/memory_facts/domain/feature.py +15 -0
  540. infinity_context_core/features/memory_facts/ports/__init__.py +31 -0
  541. infinity_context_core/features/memory_facts/ports/clock.py +14 -0
  542. infinity_context_core/features/memory_facts/ports/ids.py +19 -0
  543. infinity_context_core/features/memory_facts/ports/outbox.py +26 -0
  544. infinity_context_core/features/memory_facts/ports/repositories.py +30 -0
  545. infinity_context_core/features/memory_facts/ports/unit_of_work.py +43 -0
  546. infinity_context_core/features/memory_facts/public.py +79 -0
  547. infinity_context_core/features/memory_facts/tests/test_application_handlers.py +332 -0
  548. infinity_context_core/features/memory_facts/tests/test_application_ports_public_skeleton.py +318 -0
  549. infinity_context_core/features/memory_facts/tests/test_domain_fact_skeleton.py +222 -0
  550. infinity_context_core/features/memory_scopes/__init__.py +3 -0
  551. infinity_context_core/features/memory_scopes/application/__init__.py +55 -0
  552. infinity_context_core/features/memory_scopes/application/commands.py +102 -0
  553. infinity_context_core/features/memory_scopes/application/errors.py +27 -0
  554. infinity_context_core/features/memory_scopes/application/handlers.py +226 -0
  555. infinity_context_core/features/memory_scopes/application/use_cases.py +68 -0
  556. infinity_context_core/features/memory_scopes/domain/__init__.py +59 -0
  557. infinity_context_core/features/memory_scopes/domain/errors.py +22 -0
  558. infinity_context_core/features/memory_scopes/domain/feature.py +18 -0
  559. infinity_context_core/features/memory_scopes/domain/policies.py +197 -0
  560. infinity_context_core/features/memory_scopes/domain/scope.py +178 -0
  561. infinity_context_core/features/memory_scopes/ports/__init__.py +25 -0
  562. infinity_context_core/features/memory_scopes/ports/clock.py +14 -0
  563. infinity_context_core/features/memory_scopes/ports/ids.py +13 -0
  564. infinity_context_core/features/memory_scopes/ports/repositories.py +40 -0
  565. infinity_context_core/features/memory_scopes/ports/unit_of_work.py +39 -0
  566. infinity_context_core/features/memory_scopes/public.py +111 -0
  567. infinity_context_core/features/memory_scopes/tests/test_application_ports_public_skeleton.py +824 -0
  568. infinity_context_core/features/memory_scopes/tests/test_domain_scope_skeleton.py +428 -0
  569. infinity_context_core/memory_scope_snapshot_preview.py +863 -0
  570. infinity_context_core/memory_scope_snapshots.py +206 -0
  571. infinity_context_core/ports/__init__.py +164 -0
  572. infinity_context_core/ports/adapters.py +217 -0
  573. infinity_context_core/ports/assets.py +270 -0
  574. infinity_context_core/ports/auth.py +68 -0
  575. infinity_context_core/ports/auto_memory.py +71 -0
  576. infinity_context_core/ports/benchmark_runs.py +205 -0
  577. infinity_context_core/ports/capabilities.py +324 -0
  578. infinity_context_core/ports/captures.py +53 -0
  579. infinity_context_core/ports/clock.py +11 -0
  580. infinity_context_core/ports/derived_projection_policy.py +72 -0
  581. infinity_context_core/ports/extraction.py +201 -0
  582. infinity_context_core/ports/graph_evidence.py +170 -0
  583. infinity_context_core/ports/ids.py +11 -0
  584. infinity_context_core/ports/projection_fence.py +27 -0
  585. infinity_context_core/ports/repositories.py +563 -0
  586. infinity_context_core/ports/transcription.py +63 -0
  587. infinity_context_core/ports/unit_of_work.py +77 -0
  588. infinity_context_core/ports/usage.py +36 -0
  589. infinity_context_core/ports/vector_projection_evidence.py +230 -0
  590. infinity_context_core/ports/vision.py +36 -0
  591. infinity_context_core/processes/__init__.py +3 -0
  592. infinity_context_core/processes/document_memory_pipeline/__init__.py +3 -0
  593. infinity_context_core/processes/document_memory_pipeline/contracts.py +44 -0
  594. infinity_context_core/processes/document_memory_pipeline/process.py +72 -0
  595. infinity_context_core/processes/document_memory_pipeline/public.py +21 -0
  596. infinity_context_core/reporting.py +105 -0
  597. infinity_context_mcp/__init__.py +5 -0
  598. infinity_context_mcp/__main__.py +6 -0
  599. infinity_context_mcp/adapters/__init__.py +1 -0
  600. infinity_context_mcp/adapters/http_gateway.py +940 -0
  601. infinity_context_mcp/agent_behavior_bench.py +1731 -0
  602. infinity_context_mcp/agent_behavior_bench_metrics.py +419 -0
  603. infinity_context_mcp/agent_behavior_bench_redaction.py +149 -0
  604. infinity_context_mcp/agent_behavior_bench_types.py +127 -0
  605. infinity_context_mcp/agent_behavior_scenarios.py +35 -0
  606. infinity_context_mcp/agent_behavior_scenarios_core.py +484 -0
  607. infinity_context_mcp/agent_behavior_scenarios_realistic.py +473 -0
  608. infinity_context_mcp/agent_behavior_scenarios_transcript.py +196 -0
  609. infinity_context_mcp/agent_behavior_transcripts.py +231 -0
  610. infinity_context_mcp/agent_behavior_types.py +66 -0
  611. infinity_context_mcp/agent_behavior_utils.py +29 -0
  612. infinity_context_mcp/application/__init__.py +1 -0
  613. infinity_context_mcp/application/context_link_review.py +109 -0
  614. infinity_context_mcp/application/local_runtime.py +473 -0
  615. infinity_context_mcp/application/normalization.py +36 -0
  616. infinity_context_mcp/application/obsidian.py +568 -0
  617. infinity_context_mcp/application/policy.py +160 -0
  618. infinity_context_mcp/application/ports.py +324 -0
  619. infinity_context_mcp/application/prepare.py +254 -0
  620. infinity_context_mcp/application/readiness.py +71 -0
  621. infinity_context_mcp/application/review_batch.py +62 -0
  622. infinity_context_mcp/application/service.py +701 -0
  623. infinity_context_mcp/application/service_base.py +29 -0
  624. infinity_context_mcp/application/service_constants.py +89 -0
  625. infinity_context_mcp/application/service_context_links.py +224 -0
  626. infinity_context_mcp/application/service_duplicates.py +62 -0
  627. infinity_context_mcp/application/service_facts.py +461 -0
  628. infinity_context_mcp/application/service_helpers.py +179 -0
  629. infinity_context_mcp/application/service_lifecycle.py +348 -0
  630. infinity_context_mcp/application/service_policy.py +74 -0
  631. infinity_context_mcp/application/service_query.py +384 -0
  632. infinity_context_mcp/application/service_resources.py +192 -0
  633. infinity_context_mcp/application/service_response.py +95 -0
  634. infinity_context_mcp/application/service_scope.py +132 -0
  635. infinity_context_mcp/application/service_suggestions.py +820 -0
  636. infinity_context_mcp/application/suggest_batch.py +71 -0
  637. infinity_context_mcp/application/usage_guide.py +74 -0
  638. infinity_context_mcp/bench.py +279 -0
  639. infinity_context_mcp/config.py +213 -0
  640. infinity_context_mcp/domain/__init__.py +1 -0
  641. infinity_context_mcp/domain/context_links.py +117 -0
  642. infinity_context_mcp/domain/local_runtime_models.py +56 -0
  643. infinity_context_mcp/domain/memory_browser.py +35 -0
  644. infinity_context_mcp/domain/models.py +1036 -0
  645. infinity_context_mcp/domain/obsidian_models.py +67 -0
  646. infinity_context_mcp/domain/policy.py +112 -0
  647. infinity_context_mcp/domain/prepare_models.py +24 -0
  648. infinity_context_mcp/plugin_hook.py +873 -0
  649. infinity_context_mcp/plugin_hook_settings.py +253 -0
  650. infinity_context_mcp/server.py +133 -0
  651. infinity_context_mcp/server_context_tools.py +404 -0
  652. infinity_context_mcp/server_fact_tools.py +928 -0
  653. infinity_context_mcp/server_hardening.py +54 -0
  654. infinity_context_mcp/server_local_runtime_tools.py +164 -0
  655. infinity_context_mcp/server_obsidian_tools.py +380 -0
  656. infinity_context_mcp/server_query_tools.py +626 -0
  657. infinity_context_mcp/server_request_mapping.py +73 -0
  658. infinity_context_mcp/server_resources.py +187 -0
  659. infinity_context_mcp/server_response.py +26 -0
  660. infinity_context_obsidian/__init__.py +5 -0
  661. infinity_context_obsidian/cli.py +594 -0
  662. infinity_context_obsidian/conflicts.py +110 -0
  663. infinity_context_obsidian/doctor.py +319 -0
  664. infinity_context_obsidian/domain.py +92 -0
  665. infinity_context_obsidian/frontmatter.py +68 -0
  666. infinity_context_obsidian/gateway.py +66 -0
  667. infinity_context_obsidian/layout.py +179 -0
  668. infinity_context_obsidian/note_format.py +159 -0
  669. infinity_context_obsidian/plugin_bundle/__init__.py +1 -0
  670. infinity_context_obsidian/plugin_bundle/main.js +5 -0
  671. infinity_context_obsidian/plugin_bundle/manifest.json +10 -0
  672. infinity_context_obsidian/plugin_bundle/styles.css +123 -0
  673. infinity_context_obsidian/plugin_install.py +139 -0
  674. infinity_context_obsidian/ports.py +72 -0
  675. infinity_context_obsidian/setup.py +202 -0
  676. infinity_context_obsidian/state.py +85 -0
  677. infinity_context_obsidian/sync.py +741 -0
  678. infinity_context_obsidian/vault.py +61 -0
  679. infinity_context_sdk/__init__.py +1049 -0
  680. infinity_context_sdk/_payloads.py +401 -0
  681. infinity_context_sdk/_redaction.py +31 -0
  682. infinity_context_sdk/anchors.py +249 -0
  683. infinity_context_sdk/assets.py +554 -0
  684. infinity_context_sdk/capabilities.py +199 -0
  685. infinity_context_sdk/context.py +540 -0
  686. infinity_context_sdk/context_bundle_diagnostics.py +905 -0
  687. infinity_context_sdk/context_payload_utils.py +219 -0
  688. infinity_context_sdk/export.py +123 -0
  689. infinity_context_sdk/scopes.py +74 -0
  690. infinity_context_sdk/thread_memory.py +55 -0
  691. infinity_context_server/__init__.py +5 -0
  692. infinity_context_server/__main__.py +19 -0
  693. infinity_context_server/admin.py +832 -0
  694. infinity_context_server/admin_invariants.py +388 -0
  695. infinity_context_server/admin_outbox.py +130 -0
  696. infinity_context_server/admin_projection_repair.py +374 -0
  697. infinity_context_server/api/__init__.py +1 -0
  698. infinity_context_server/api/auth.py +432 -0
  699. infinity_context_server/api/dependencies.py +9 -0
  700. infinity_context_server/api/errors.py +94 -0
  701. infinity_context_server/api/legacy_client.py +356 -0
  702. infinity_context_server/api/policy.py +35 -0
  703. infinity_context_server/api/public_payload.py +27 -0
  704. infinity_context_server/api/v1/__init__.py +54 -0
  705. infinity_context_server/api/v1/anchors.py +469 -0
  706. infinity_context_server/api/v1/assets.py +409 -0
  707. infinity_context_server/api/v1/capabilities.py +144 -0
  708. infinity_context_server/api/v1/captures.py +329 -0
  709. infinity_context_server/api/v1/context.py +362 -0
  710. infinity_context_server/api/v1/context_links.py +611 -0
  711. infinity_context_server/api/v1/diagnostics.py +333 -0
  712. infinity_context_server/api/v1/digest.py +107 -0
  713. infinity_context_server/api/v1/documents.py +164 -0
  714. infinity_context_server/api/v1/episodes.py +146 -0
  715. infinity_context_server/api/v1/export.py +184 -0
  716. infinity_context_server/api/v1/facts.py +265 -0
  717. infinity_context_server/api/v1/health.py +24 -0
  718. infinity_context_server/api/v1/insights.py +100 -0
  719. infinity_context_server/api/v1/internal_memory_comparison_runs.py +406 -0
  720. infinity_context_server/api/v1/memory_browser.py +183 -0
  721. infinity_context_server/api/v1/operations.py +81 -0
  722. infinity_context_server/api/v1/scope_resolution.py +389 -0
  723. infinity_context_server/api/v1/source_refs.py +111 -0
  724. infinity_context_server/api/v1/spaces_memory_scopes.py +141 -0
  725. infinity_context_server/api/v1/suggestions.py +237 -0
  726. infinity_context_server/api/v1/thread_memory.py +74 -0
  727. infinity_context_server/api/v1/usage.py +75 -0
  728. infinity_context_server/api/v1/users.py +164 -0
  729. infinity_context_server/auth_scope.py +492 -0
  730. infinity_context_server/auth_tokens.py +283 -0
  731. infinity_context_server/backpressure.py +47 -0
  732. infinity_context_server/benchmark_projection_absence.py +155 -0
  733. infinity_context_server/benchmark_projection_delete_outbox.py +162 -0
  734. infinity_context_server/composition.py +897 -0
  735. infinity_context_server/config.py +223 -0
  736. infinity_context_server/db.py +39 -0
  737. infinity_context_server/deployment_readiness.py +205 -0
  738. infinity_context_server/derived_identity_evidence.py +987 -0
  739. infinity_context_server/derived_identity_target.py +39 -0
  740. infinity_context_server/derived_projection_policy.py +85 -0
  741. infinity_context_server/diagnostics.py +536 -0
  742. infinity_context_server/doctor.py +71 -0
  743. infinity_context_server/eval.py +3066 -0
  744. infinity_context_server/eval_auto_memory.py +1735 -0
  745. infinity_context_server/eval_auto_memory_metrics.py +224 -0
  746. infinity_context_server/eval_auto_memory_types.py +75 -0
  747. infinity_context_server/eval_case_catalog.py +1590 -0
  748. infinity_context_server/eval_case_runner.py +1100 -0
  749. infinity_context_server/eval_common.py +336 -0
  750. infinity_context_server/eval_constants.py +310 -0
  751. infinity_context_server/eval_fixtures.py +150 -0
  752. infinity_context_server/eval_graph.py +92 -0
  753. infinity_context_server/eval_hybrid.py +99 -0
  754. infinity_context_server/eval_multimodal_offline.py +697 -0
  755. infinity_context_server/eval_prompt_contract.py +402 -0
  756. infinity_context_server/eval_scorecard.py +2627 -0
  757. infinity_context_server/eval_semantic_linking.py +1526 -0
  758. infinity_context_server/eval_semantic_retrieval_api_canary.py +405 -0
  759. infinity_context_server/eval_semantic_retrieval_canary.py +359 -0
  760. infinity_context_server/eval_types.py +88 -0
  761. infinity_context_server/evidence_bundle.py +523 -0
  762. infinity_context_server/extraction_capabilities.py +1234 -0
  763. infinity_context_server/features/__init__.py +3 -0
  764. infinity_context_server/features/context_building/__init__.py +5 -0
  765. infinity_context_server/features/context_building/benchmark_budget.py +29 -0
  766. infinity_context_server/features/context_building/composition.py +49 -0
  767. infinity_context_server/features/context_building/context_requests.py +151 -0
  768. infinity_context_server/features/context_building/contracts.py +96 -0
  769. infinity_context_server/features/context_building/digest_api_responses.py +225 -0
  770. infinity_context_server/features/context_building/digest_requests.py +65 -0
  771. infinity_context_server/features/context_building/insights_api_responses.py +132 -0
  772. infinity_context_server/features/context_building/legacy_api_responses.py +875 -0
  773. infinity_context_server/features/context_building/mappers.py +205 -0
  774. infinity_context_server/features/context_building/public.py +66 -0
  775. infinity_context_server/features/context_building/routes.py +44 -0
  776. infinity_context_server/features/document_ingestion/__init__.py +5 -0
  777. infinity_context_server/features/document_ingestion/asset_requests.py +45 -0
  778. infinity_context_server/features/document_ingestion/asset_responses.py +365 -0
  779. infinity_context_server/features/document_ingestion/composition.py +49 -0
  780. infinity_context_server/features/document_ingestion/contracts.py +104 -0
  781. infinity_context_server/features/document_ingestion/mappers.py +386 -0
  782. infinity_context_server/features/document_ingestion/public.py +58 -0
  783. infinity_context_server/features/document_ingestion/routes.py +44 -0
  784. infinity_context_server/features/memory_facts/__init__.py +7 -0
  785. infinity_context_server/features/memory_facts/compatibility.py +204 -0
  786. infinity_context_server/features/memory_facts/composition.py +72 -0
  787. infinity_context_server/features/memory_facts/contracts.py +187 -0
  788. infinity_context_server/features/memory_facts/mappers.py +620 -0
  789. infinity_context_server/features/memory_facts/public.py +168 -0
  790. infinity_context_server/features/memory_facts/routes.py +118 -0
  791. infinity_context_server/features/memory_facts/suggestion_requests.py +283 -0
  792. infinity_context_server/features/memory_facts/suggestion_responses.py +382 -0
  793. infinity_context_server/features/memory_scopes/__init__.py +5 -0
  794. infinity_context_server/features/memory_scopes/compatibility.py +231 -0
  795. infinity_context_server/features/memory_scopes/composition.py +49 -0
  796. infinity_context_server/features/memory_scopes/contracts.py +103 -0
  797. infinity_context_server/features/memory_scopes/graph_export_responses.py +93 -0
  798. infinity_context_server/features/memory_scopes/mappers.py +290 -0
  799. infinity_context_server/features/memory_scopes/public.py +136 -0
  800. infinity_context_server/features/memory_scopes/routes.py +185 -0
  801. infinity_context_server/features/memory_scopes/snapshot_compatibility.py +146 -0
  802. infinity_context_server/features/memory_scopes/thread_memory_requests.py +127 -0
  803. infinity_context_server/llm_provider_readiness.py +267 -0
  804. infinity_context_server/longmemeval_session_identity.py +167 -0
  805. infinity_context_server/main.py +68 -0
  806. infinity_context_server/mem0_benchmark_auth_challenge.py +160 -0
  807. infinity_context_server/memora_comparison.py +658 -0
  808. infinity_context_server/memory_comparison_answer_context.py +2442 -0
  809. infinity_context_server/memory_comparison_answer_context_backfill.py +1027 -0
  810. infinity_context_server/memory_comparison_answer_context_diagnostics.py +694 -0
  811. infinity_context_server/memory_comparison_answer_context_inspection.py +103 -0
  812. infinity_context_server/memory_comparison_answer_context_retrieval_slice.py +175 -0
  813. infinity_context_server/memory_comparison_answer_context_risks.py +223 -0
  814. infinity_context_server/memory_comparison_backend_target.py +41 -0
  815. infinity_context_server/memory_comparison_benchmark.py +651 -0
  816. infinity_context_server/memory_comparison_benchmark_compact.py +387 -0
  817. infinity_context_server/memory_comparison_benchmark_compact_fast_gate.py +387 -0
  818. infinity_context_server/memory_comparison_benchmark_compact_samples.py +931 -0
  819. infinity_context_server/memory_comparison_benchmark_config.py +105 -0
  820. infinity_context_server/memory_comparison_benchmark_control.py +215 -0
  821. infinity_context_server/memory_comparison_benchmark_execution.py +238 -0
  822. infinity_context_server/memory_comparison_benchmark_identity.py +65 -0
  823. infinity_context_server/memory_comparison_benchmark_metrics.py +686 -0
  824. infinity_context_server/memory_comparison_benchmark_replay.py +400 -0
  825. infinity_context_server/memory_comparison_benchmark_shared.py +284 -0
  826. infinity_context_server/memory_comparison_bounded_provider.py +295 -0
  827. infinity_context_server/memory_comparison_bundle_partial_support.py +107 -0
  828. infinity_context_server/memory_comparison_bundle_planner.py +3521 -0
  829. infinity_context_server/memory_comparison_bundle_source_windows.py +247 -0
  830. infinity_context_server/memory_comparison_candidate_features.py +2014 -0
  831. infinity_context_server/memory_comparison_candidate_fusion.py +893 -0
  832. infinity_context_server/memory_comparison_candidate_risks.py +124 -0
  833. infinity_context_server/memory_comparison_canonical_source_hash.py +109 -0
  834. infinity_context_server/memory_comparison_case_identity.py +100 -0
  835. infinity_context_server/memory_comparison_case_loader.py +123 -0
  836. infinity_context_server/memory_comparison_chat_completions.py +402 -0
  837. infinity_context_server/memory_comparison_clean_state.py +607 -0
  838. infinity_context_server/memory_comparison_clean_state_http.py +120 -0
  839. infinity_context_server/memory_comparison_clean_state_runner.py +103 -0
  840. infinity_context_server/memory_comparison_cli.py +295 -0
  841. infinity_context_server/memory_comparison_codex_canary.py +315 -0
  842. infinity_context_server/memory_comparison_codex_llm.py +345 -0
  843. infinity_context_server/memory_comparison_compact_gap_report.py +289 -0
  844. infinity_context_server/memory_comparison_comparative_preference.py +71 -0
  845. infinity_context_server/memory_comparison_conversation_ingestion.py +198 -0
  846. infinity_context_server/memory_comparison_evidence.py +877 -0
  847. infinity_context_server/memory_comparison_evidence_commitment.py +20 -0
  848. infinity_context_server/memory_comparison_failure_diagnostics.py +809 -0
  849. infinity_context_server/memory_comparison_full_canonical_evidence.py +746 -0
  850. infinity_context_server/memory_comparison_full_canonical_source_evidence_trust.py +450 -0
  851. infinity_context_server/memory_comparison_full_delete_evidence.py +670 -0
  852. infinity_context_server/memory_comparison_full_delete_evidence_trust.py +441 -0
  853. infinity_context_server/memory_comparison_full_delete_evidence_witnesses.py +308 -0
  854. infinity_context_server/memory_comparison_full_execution_validation.py +697 -0
  855. infinity_context_server/memory_comparison_full_execution_validation_slots.py +655 -0
  856. infinity_context_server/memory_comparison_full_methodology.py +556 -0
  857. infinity_context_server/memory_comparison_full_policy_component_validation.py +899 -0
  858. infinity_context_server/memory_comparison_full_profiles.py +398 -0
  859. infinity_context_server/memory_comparison_full_run_component_sets.py +304 -0
  860. infinity_context_server/memory_comparison_full_run_components.py +787 -0
  861. infinity_context_server/memory_comparison_full_run_evidence.py +759 -0
  862. infinity_context_server/memory_comparison_full_scope.py +244 -0
  863. infinity_context_server/memory_comparison_full_source_evidence.py +866 -0
  864. infinity_context_server/memory_comparison_full_verdict.py +252 -0
  865. infinity_context_server/memory_comparison_gold_blind.py +654 -0
  866. infinity_context_server/memory_comparison_gold_blind_answer_contract.py +492 -0
  867. infinity_context_server/memory_comparison_gold_blind_contract.py +760 -0
  868. infinity_context_server/memory_comparison_gold_blind_dispatch_models.py +34 -0
  869. infinity_context_server/memory_comparison_gold_blind_execution_validation.py +170 -0
  870. infinity_context_server/memory_comparison_gold_blind_judge_binding.py +167 -0
  871. infinity_context_server/memory_comparison_gold_blind_judge_capability.py +387 -0
  872. infinity_context_server/memory_comparison_gold_blind_retrieval_contract.py +413 -0
  873. infinity_context_server/memory_comparison_gold_blind_run_proof.py +880 -0
  874. infinity_context_server/memory_comparison_gold_blind_run_validation.py +109 -0
  875. infinity_context_server/memory_comparison_gold_blind_validation.py +319 -0
  876. infinity_context_server/memory_comparison_http.py +921 -0
  877. infinity_context_server/memory_comparison_http_ingest_observation.py +710 -0
  878. infinity_context_server/memory_comparison_http_ingest_request.py +204 -0
  879. infinity_context_server/memory_comparison_intent.py +2925 -0
  880. infinity_context_server/memory_comparison_latency.py +455 -0
  881. infinity_context_server/memory_comparison_llm.py +473 -0
  882. infinity_context_server/memory_comparison_location_roles.py +169 -0
  883. infinity_context_server/memory_comparison_locomo_cases.py +328 -0
  884. infinity_context_server/memory_comparison_locomo_expected_turn.py +297 -0
  885. infinity_context_server/memory_comparison_locomo_transport.py +873 -0
  886. infinity_context_server/memory_comparison_longmemeval_cases.py +339 -0
  887. infinity_context_server/memory_comparison_managed_attestation.py +771 -0
  888. infinity_context_server/memory_comparison_managed_benchmark_registry_abort_http.py +120 -0
  889. infinity_context_server/memory_comparison_managed_benchmark_registry_contracts.py +715 -0
  890. infinity_context_server/memory_comparison_managed_benchmark_registry_http.py +855 -0
  891. infinity_context_server/memory_comparison_managed_benchmark_registry_recovery_http.py +164 -0
  892. infinity_context_server/memory_comparison_managed_benchmark_registry_wire.py +890 -0
  893. infinity_context_server/memory_comparison_managed_composite_assembler.py +524 -0
  894. infinity_context_server/memory_comparison_managed_corpus_projection.py +653 -0
  895. infinity_context_server/memory_comparison_managed_execution_receipts.py +991 -0
  896. infinity_context_server/memory_comparison_managed_http_derived_evidence.py +724 -0
  897. infinity_context_server/memory_comparison_managed_http_exact_cleanup.py +476 -0
  898. infinity_context_server/memory_comparison_managed_http_execution.py +673 -0
  899. infinity_context_server/memory_comparison_managed_http_lifecycle.py +905 -0
  900. infinity_context_server/memory_comparison_managed_http_lifecycle_credentials.py +83 -0
  901. infinity_context_server/memory_comparison_managed_http_lifecycle_evidence.py +366 -0
  902. infinity_context_server/memory_comparison_managed_http_lifecycle_registration.py +106 -0
  903. infinity_context_server/memory_comparison_managed_http_policy_lifecycle.py +894 -0
  904. infinity_context_server/memory_comparison_managed_http_policy_material_projection.py +315 -0
  905. infinity_context_server/memory_comparison_managed_http_policy_receipts.py +219 -0
  906. infinity_context_server/memory_comparison_managed_http_policy_registry_evidence.py +177 -0
  907. infinity_context_server/memory_comparison_managed_http_policy_requirements.py +824 -0
  908. infinity_context_server/memory_comparison_managed_http_policy_support.py +108 -0
  909. infinity_context_server/memory_comparison_managed_http_policy_validation.py +762 -0
  910. infinity_context_server/memory_comparison_managed_ingest_manifest.py +449 -0
  911. infinity_context_server/memory_comparison_managed_live_admission.py +886 -0
  912. infinity_context_server/memory_comparison_managed_live_cli.py +536 -0
  913. infinity_context_server/memory_comparison_managed_live_composition.py +636 -0
  914. infinity_context_server/memory_comparison_managed_llm_execution.py +850 -0
  915. infinity_context_server/memory_comparison_managed_llm_execution_dispatch.py +269 -0
  916. infinity_context_server/memory_comparison_managed_llm_execution_ports.py +225 -0
  917. infinity_context_server/memory_comparison_managed_mem0_auth.py +65 -0
  918. infinity_context_server/memory_comparison_managed_mem0_runtime_authority.py +241 -0
  919. infinity_context_server/memory_comparison_managed_mem0_runtime_http.py +541 -0
  920. infinity_context_server/memory_comparison_managed_plan_builder.py +685 -0
  921. infinity_context_server/memory_comparison_managed_preflight.py +907 -0
  922. infinity_context_server/memory_comparison_managed_preflight_cli.py +431 -0
  923. infinity_context_server/memory_comparison_managed_production_cli.py +325 -0
  924. infinity_context_server/memory_comparison_managed_production_composition.py +140 -0
  925. infinity_context_server/memory_comparison_managed_production_ports.py +194 -0
  926. infinity_context_server/memory_comparison_managed_production_runner.py +450 -0
  927. infinity_context_server/memory_comparison_managed_projection_manifest.py +438 -0
  928. infinity_context_server/memory_comparison_managed_provider_calls.py +450 -0
  929. infinity_context_server/memory_comparison_managed_quality_projection.py +347 -0
  930. infinity_context_server/memory_comparison_managed_registry_policy_lifecycle.py +677 -0
  931. infinity_context_server/memory_comparison_managed_run.py +892 -0
  932. infinity_context_server/memory_comparison_managed_run_contract.py +454 -0
  933. infinity_context_server/memory_comparison_managed_run_ports.py +79 -0
  934. infinity_context_server/memory_comparison_managed_runtime_credentials.py +916 -0
  935. infinity_context_server/memory_comparison_managed_runtime_credentials_capability.py +361 -0
  936. infinity_context_server/memory_comparison_managed_runtime_credentials_context.py +132 -0
  937. infinity_context_server/memory_comparison_managed_runtime_credentials_integrity.py +213 -0
  938. infinity_context_server/memory_comparison_managed_runtime_credentials_models.py +81 -0
  939. infinity_context_server/memory_comparison_managed_runtime_credentials_targets.py +28 -0
  940. infinity_context_server/memory_comparison_mem0_contract.py +491 -0
  941. infinity_context_server/memory_comparison_mem0_http_observation.py +296 -0
  942. infinity_context_server/memory_comparison_mem0_locomo_prompts.py +328 -0
  943. infinity_context_server/memory_comparison_mem0_longmemeval_prompts.py +365 -0
  944. infinity_context_server/memory_comparison_mem0_official_chat.py +504 -0
  945. infinity_context_server/memory_comparison_mem0_official_prompt_renderer.py +307 -0
  946. infinity_context_server/memory_comparison_mem0_oss_contract.py +456 -0
  947. infinity_context_server/memory_comparison_mem0_oss_manifest.py +563 -0
  948. infinity_context_server/memory_comparison_mem0_platform_contract.py +467 -0
  949. infinity_context_server/memory_comparison_mem0_runtime_attestation.py +861 -0
  950. infinity_context_server/memory_comparison_models.py +398 -0
  951. infinity_context_server/memory_comparison_openai_official_transport.py +525 -0
  952. infinity_context_server/memory_comparison_preflight.py +1147 -0
  953. infinity_context_server/memory_comparison_probe_transport.py +154 -0
  954. infinity_context_server/memory_comparison_prompt_policy.py +603 -0
  955. infinity_context_server/memory_comparison_provider_provenance.py +392 -0
  956. infinity_context_server/memory_comparison_quality_accessors.py +339 -0
  957. infinity_context_server/memory_comparison_quality_actionable_gaps.py +2038 -0
  958. infinity_context_server/memory_comparison_quality_answer_context_gaps.py +450 -0
  959. infinity_context_server/memory_comparison_quality_answer_context_risks.py +75 -0
  960. infinity_context_server/memory_comparison_quality_bundle_gaps.py +860 -0
  961. infinity_context_server/memory_comparison_quality_bundle_table.py +805 -0
  962. infinity_context_server/memory_comparison_quality_diagnostics.py +2798 -0
  963. infinity_context_server/memory_comparison_quality_fusion.py +241 -0
  964. infinity_context_server/memory_comparison_quality_query_plan_gaps.py +533 -0
  965. infinity_context_server/memory_comparison_quality_query_role_gaps.py +845 -0
  966. infinity_context_server/memory_comparison_quality_query_roles.py +815 -0
  967. infinity_context_server/memory_comparison_quality_rerank_gaps.py +492 -0
  968. infinity_context_server/memory_comparison_quality_selected_weakness.py +544 -0
  969. infinity_context_server/memory_comparison_quality_support.py +921 -0
  970. infinity_context_server/memory_comparison_query_integrity.py +301 -0
  971. infinity_context_server/memory_comparison_query_plan.py +524 -0
  972. infinity_context_server/memory_comparison_query_terms.py +2055 -0
  973. infinity_context_server/memory_comparison_relation_support.py +2100 -0
  974. infinity_context_server/memory_comparison_rerank.py +3209 -0
  975. infinity_context_server/memory_comparison_rerank_intents.py +405 -0
  976. infinity_context_server/memory_comparison_rerank_policies.py +1726 -0
  977. infinity_context_server/memory_comparison_rerank_policy.py +675 -0
  978. infinity_context_server/memory_comparison_rerank_shapes.py +152 -0
  979. infinity_context_server/memory_comparison_rerank_terms.py +973 -0
  980. infinity_context_server/memory_comparison_rerank_text.py +722 -0
  981. infinity_context_server/memory_comparison_retrieval_policy.py +108 -0
  982. infinity_context_server/memory_comparison_retrieval_width.py +383 -0
  983. infinity_context_server/memory_comparison_service_probe.py +278 -0
  984. infinity_context_server/memory_comparison_service_probes.py +547 -0
  985. infinity_context_server/memory_comparison_session_identity_contract.py +328 -0
  986. infinity_context_server/memory_comparison_source_identity.py +1655 -0
  987. infinity_context_server/memory_comparison_subscription_chat.py +717 -0
  988. infinity_context_server/memory_comparison_subscription_live_probe.py +323 -0
  989. infinity_context_server/memory_comparison_subscription_probe.py +368 -0
  990. infinity_context_server/memory_comparison_target_identity.py +42 -0
  991. infinity_context_server/memory_comparison_temporal_grounding.py +771 -0
  992. infinity_context_server/memory_comparison_token_budget_contract.py +665 -0
  993. infinity_context_server/memory_comparison_token_latency.py +136 -0
  994. infinity_context_server/memory_scope_transfer.py +933 -0
  995. infinity_context_server/memory_scope_transfer_assets.py +181 -0
  996. infinity_context_server/memory_scope_transfer_conflicts.py +565 -0
  997. infinity_context_server/memory_scope_transfer_context.py +295 -0
  998. infinity_context_server/memory_scope_transfer_extractions.py +390 -0
  999. infinity_context_server/memory_scope_transfer_facts.py +65 -0
  1000. infinity_context_server/memory_scope_transfer_records.py +630 -0
  1001. infinity_context_server/memory_scope_transfer_relations.py +84 -0
  1002. infinity_context_server/memory_scope_transfer_remap.py +710 -0
  1003. infinity_context_server/memory_scope_transfer_scope.py +267 -0
  1004. infinity_context_server/memory_scope_transfer_support.py +108 -0
  1005. infinity_context_server/memory_scope_transfer_temporal.py +24 -0
  1006. infinity_context_server/metrics.py +264 -0
  1007. infinity_context_server/official_public_benchmark.py +979 -0
  1008. infinity_context_server/pagination.py +60 -0
  1009. infinity_context_server/processes/__init__.py +38 -0
  1010. infinity_context_server/processes/extractions.py +40 -0
  1011. infinity_context_server/processes/outbox.py +47 -0
  1012. infinity_context_server/processes/projections.py +372 -0
  1013. infinity_context_server/provider_budget.py +59 -0
  1014. infinity_context_server/provider_circuit.py +333 -0
  1015. infinity_context_server/public_benchmark.py +2532 -0
  1016. infinity_context_server/public_benchmark_artifacts.py +91 -0
  1017. infinity_context_server/public_benchmark_case_diagnostics.py +231 -0
  1018. infinity_context_server/public_benchmark_checkpoint.py +751 -0
  1019. infinity_context_server/public_benchmark_environment.py +102 -0
  1020. infinity_context_server/public_benchmark_execution.py +445 -0
  1021. infinity_context_server/public_benchmark_http.py +39 -0
  1022. infinity_context_server/public_benchmark_manifest.py +129 -0
  1023. infinity_context_server/public_benchmark_metrics.py +645 -0
  1024. infinity_context_server/public_benchmark_metrics_policy.py +117 -0
  1025. infinity_context_server/public_benchmark_models.py +112 -0
  1026. infinity_context_server/public_benchmark_progress.py +224 -0
  1027. infinity_context_server/public_benchmark_results.py +76 -0
  1028. infinity_context_server/public_benchmark_run_diagnostics.py +163 -0
  1029. infinity_context_server/public_benchmark_selection.py +379 -0
  1030. infinity_context_server/public_benchmark_transport.py +62 -0
  1031. infinity_context_server/public_benchmark_unsupported.py +228 -0
  1032. infinity_context_server/ranked_evidence_answer_support.py +665 -0
  1033. infinity_context_server/ranked_evidence_document_seed_contract.py +30 -0
  1034. infinity_context_server/ranked_evidence_evaluator_helpers.py +135 -0
  1035. infinity_context_server/ranked_evidence_retrieval_request.py +36 -0
  1036. infinity_context_server/ranked_evidence_seed_case.py +109 -0
  1037. infinity_context_server/ranked_evidence_semantic_gate.py +980 -0
  1038. infinity_context_server/ranked_evidence_semantic_gate_cli.py +137 -0
  1039. infinity_context_server/ranked_evidence_semantic_gate_decision.py +163 -0
  1040. infinity_context_server/ranked_evidence_semantic_metrics.py +375 -0
  1041. infinity_context_server/ranked_evidence_session_identity.py +100 -0
  1042. infinity_context_server/storage_maintenance.py +187 -0
  1043. infinity_context_server/top_evidence_dataset_profile.py +442 -0
  1044. infinity_context_server/top_evidence_policy.py +274 -0
  1045. infinity_context_server/top_evidence_preflight.py +693 -0
  1046. infinity_context_server/web/assets/memory-browser-capture.js +252 -0
  1047. infinity_context_server/web/assets/memory-browser-operations.js +143 -0
  1048. infinity_context_server/web/assets/memory-browser-review.js +687 -0
  1049. infinity_context_server/web/assets/memory-browser.css +854 -0
  1050. infinity_context_server/web/assets/memory-browser.js +3299 -0
  1051. infinity_context_server/web/index.html +261 -0
  1052. infinity_context_server/web_ui.py +29 -0
  1053. infinity_context_server/worker.py +380 -0
@@ -0,0 +1,3209 @@
1
+ """Question-only rerank helpers for memory comparison benchmark retrieval."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from collections.abc import Mapping, Sequence
7
+ from dataclasses import replace
8
+
9
+ from infinity_context_core.application.context_answer_unit_shapes import (
10
+ requested_answer_unit_shapes as _requested_answer_unit_shapes,
11
+ )
12
+ from infinity_context_core.application.context_source_grounding import (
13
+ is_source_grounding_query as _is_source_grounding_query,
14
+ )
15
+ from infinity_context_core.application.context_source_grounding import (
16
+ source_grounding_evidence as _source_grounding_evidence,
17
+ )
18
+ from infinity_context_core.domain.entities import SourceRef
19
+
20
+ from infinity_context_server.memory_comparison_candidate_features import (
21
+ build_candidate_evidence_features,
22
+ )
23
+ from infinity_context_server.memory_comparison_comparative_preference import (
24
+ comparative_option_preference_query as _comparative_option_preference_query,
25
+ )
26
+ from infinity_context_server.memory_comparison_comparative_preference import (
27
+ without_contrast_requirement as _without_contrast_requirement,
28
+ )
29
+ from infinity_context_server.memory_comparison_intent import (
30
+ RetrievalEntityIntent,
31
+ RetrievalIntent,
32
+ RetrievalTimeIntent,
33
+ infer_bundle_evidence_roles,
34
+ infer_evidence_need,
35
+ infer_relation_intents,
36
+ infer_risk_flags,
37
+ infer_time_intent_kind,
38
+ merge_relation_evidence_needs,
39
+ )
40
+ from infinity_context_server.memory_comparison_location_roles import (
41
+ has_current_location_query as _has_current_location_query,
42
+ )
43
+ from infinity_context_server.memory_comparison_models import RetrievedMemory
44
+ from infinity_context_server.memory_comparison_query_plan import (
45
+ QueryPlanCandidate,
46
+ QueryPlannerV2,
47
+ )
48
+ from infinity_context_server.memory_comparison_query_terms import (
49
+ _HIGH_SIGNAL_RELATION_VARIANTS,
50
+ _contrast_support_query_terms,
51
+ _location_support_query_terms,
52
+ _preference_support_query_terms,
53
+ _relation_query_terms,
54
+ _support_query_terms,
55
+ )
56
+ from infinity_context_server.memory_comparison_rerank_intents import (
57
+ focused_intent_policy_boosts,
58
+ )
59
+ from infinity_context_server.memory_comparison_rerank_policy import (
60
+ BenchmarkRerankFeatures,
61
+ score_benchmark_rerank_candidate,
62
+ )
63
+ from infinity_context_server.memory_comparison_rerank_shapes import (
64
+ focused_evidence_shape_boosts,
65
+ )
66
+ from infinity_context_server.memory_comparison_rerank_terms import (
67
+ RELATION_QUERY_VARIANTS as _RELATION_QUERY_VARIANTS,
68
+ )
69
+ from infinity_context_server.memory_comparison_rerank_text import (
70
+ HONORIFIC_ENTITY_RE as _HONORIFIC_ENTITY_RE,
71
+ )
72
+ from infinity_context_server.memory_comparison_rerank_text import (
73
+ QUERY_STOPWORDS as _QUERY_STOPWORDS,
74
+ )
75
+ from infinity_context_server.memory_comparison_rerank_text import (
76
+ QUERY_TOKEN_ALIASES as _QUERY_TOKEN_ALIASES,
77
+ )
78
+ from infinity_context_server.memory_comparison_rerank_text import (
79
+ compact_temporal_relation_terms as _compact_temporal_relation_terms,
80
+ )
81
+ from infinity_context_server.memory_comparison_rerank_text import (
82
+ entity_speaks_in_memory as _entity_speaks_in_memory,
83
+ )
84
+ from infinity_context_server.memory_comparison_rerank_text import (
85
+ entity_surface_in_memory as _entity_surface_in_memory,
86
+ )
87
+ from infinity_context_server.memory_comparison_rerank_text import (
88
+ entity_surfaces as _entity_surfaces,
89
+ )
90
+ from infinity_context_server.memory_comparison_rerank_text import (
91
+ is_contrast_query as _is_contrast_query,
92
+ )
93
+ from infinity_context_server.memory_comparison_rerank_text import (
94
+ is_preference_query as _is_preference_query,
95
+ )
96
+ from infinity_context_server.memory_comparison_rerank_text import (
97
+ memory_has_focused_turn_surface as _memory_has_focused_turn_surface,
98
+ )
99
+ from infinity_context_server.memory_comparison_rerank_text import (
100
+ memory_has_preference_evidence as _memory_has_preference_evidence,
101
+ )
102
+ from infinity_context_server.memory_comparison_rerank_text import (
103
+ memory_has_sequence_surface as _memory_has_sequence_surface,
104
+ )
105
+ from infinity_context_server.memory_comparison_rerank_text import (
106
+ memory_has_temporal_surface as _memory_has_temporal_surface,
107
+ )
108
+ from infinity_context_server.memory_comparison_rerank_text import (
109
+ memory_has_visual_evidence as _memory_has_visual_evidence,
110
+ )
111
+ from infinity_context_server.memory_comparison_rerank_text import (
112
+ memory_timestamp_values as _memory_timestamp_values,
113
+ )
114
+ from infinity_context_server.memory_comparison_rerank_text import (
115
+ normalized_terms as _normalized_terms,
116
+ )
117
+ from infinity_context_server.memory_comparison_rerank_text import (
118
+ optional_int as _optional_int,
119
+ )
120
+ from infinity_context_server.memory_comparison_rerank_text import (
121
+ question_phrase_terms as _question_phrase_terms,
122
+ )
123
+ from infinity_context_server.memory_comparison_rerank_text import (
124
+ render_query_terms as _render_query_terms,
125
+ )
126
+ from infinity_context_server.memory_comparison_rerank_text import (
127
+ speaker_match_surfaces as _speaker_match_surfaces,
128
+ )
129
+ from infinity_context_server.memory_comparison_rerank_text import (
130
+ speaker_surfaces as _speaker_surfaces,
131
+ )
132
+ from infinity_context_server.memory_comparison_rerank_text import (
133
+ string_sequence as _string_sequence,
134
+ )
135
+ from infinity_context_server.memory_comparison_rerank_text import (
136
+ timestamped_memory_count as _timestamped_memory_count,
137
+ )
138
+ from infinity_context_server.memory_comparison_rerank_text import (
139
+ visual_surface_terms as _visual_surface_terms,
140
+ )
141
+ from infinity_context_server.memory_comparison_source_identity import (
142
+ source_identity_refs_from_source_refs as _source_identity_refs_from_source_refs,
143
+ )
144
+ from infinity_context_server.public_benchmark_models import PublicBenchmarkCase
145
+
146
+ _RELATION_QUERY_TERMS = {
147
+ "activity",
148
+ "action",
149
+ "age",
150
+ "anniversary",
151
+ "advise",
152
+ "ask",
153
+ "attend",
154
+ "based",
155
+ "because",
156
+ "birthday",
157
+ "book",
158
+ "bookshelf",
159
+ "bought",
160
+ "between",
161
+ "bring",
162
+ "brought",
163
+ "camp",
164
+ "call",
165
+ "cancel",
166
+ "caus",
167
+ "cause",
168
+ "chat",
169
+ "choose",
170
+ "class",
171
+ "compare",
172
+ "consider",
173
+ "conference",
174
+ "contact",
175
+ "deadline",
176
+ "decide",
177
+ "destress",
178
+ "diet",
179
+ "discus",
180
+ "discuss",
181
+ "different",
182
+ "difference",
183
+ "education",
184
+ "employment",
185
+ "enjoy",
186
+ "avoid",
187
+ "dislike",
188
+ "exercise",
189
+ "enroll",
190
+ "excite",
191
+ "favorite",
192
+ "favourite",
193
+ "feel",
194
+ "former",
195
+ "gift",
196
+ "give",
197
+ "go",
198
+ "friend",
199
+ "get",
200
+ "got",
201
+ "group",
202
+ "grow",
203
+ "hate",
204
+ "health",
205
+ "help",
206
+ "hike",
207
+ "hobby",
208
+ "interest",
209
+ "identity",
210
+ "inspir",
211
+ "invit",
212
+ "invitation",
213
+ "invite",
214
+ "join",
215
+ "learn",
216
+ "like",
217
+ "live",
218
+ "love",
219
+ "make",
220
+ "marry",
221
+ "meet",
222
+ "message",
223
+ "messag",
224
+ "mention",
225
+ "motivat",
226
+ "motivate",
227
+ "motivation",
228
+ "move",
229
+ "nickname",
230
+ "offer",
231
+ "origin",
232
+ "participate",
233
+ "plan",
234
+ "political",
235
+ "prefer",
236
+ "preference",
237
+ "previous",
238
+ "prompt",
239
+ "prompted",
240
+ "promise",
241
+ "prioritize",
242
+ "purchas",
243
+ "purchase",
244
+ "pursue",
245
+ "raise",
246
+ "receive",
247
+ "recommend",
248
+ "register",
249
+ "remind",
250
+ "reminded",
251
+ "reschedule",
252
+ "request",
253
+ "read",
254
+ "religious",
255
+ "relationship",
256
+ "realize",
257
+ "reason",
258
+ "remember",
259
+ "research",
260
+ "run",
261
+ "say",
262
+ "said",
263
+ "sign",
264
+ "suggest",
265
+ "symbolize",
266
+ "support",
267
+ "status",
268
+ "stay",
269
+ "sport",
270
+ "talk",
271
+ "task",
272
+ "team",
273
+ "tell",
274
+ "text",
275
+ "think",
276
+ "told",
277
+ "travel",
278
+ "venue",
279
+ "vehicle",
280
+ "visit",
281
+ "want",
282
+ "warn",
283
+ "warned",
284
+ "work",
285
+ }
286
+ _RELATION_QUERY_TERMS.update(
287
+ {
288
+ "adopt",
289
+ "adoption",
290
+ "agency",
291
+ "ally",
292
+ "belong",
293
+ "belongs",
294
+ "boyfriend",
295
+ "boss",
296
+ "brother",
297
+ "colleague",
298
+ "cousin",
299
+ "community",
300
+ "counsel",
301
+ "coworker",
302
+ "career",
303
+ "child",
304
+ "children",
305
+ "charity",
306
+ "current",
307
+ "daughter",
308
+ "decision",
309
+ "dating",
310
+ "father",
311
+ "fiance",
312
+ "fiancee",
313
+ "field",
314
+ "girlfriend",
315
+ "grandfather",
316
+ "grandmother",
317
+ "husband",
318
+ "engag",
319
+ "individual",
320
+ "lgbt",
321
+ "lgbtq",
322
+ "kid",
323
+ "member",
324
+ "membership",
325
+ "manager",
326
+ "mentor",
327
+ "mother",
328
+ "music",
329
+ "necklace",
330
+ "neighbor",
331
+ "paint",
332
+ "park",
333
+ "parent",
334
+ "partner",
335
+ "part",
336
+ "path",
337
+ "personality",
338
+ "pet",
339
+ "process",
340
+ "race",
341
+ "relocate",
342
+ "relocated",
343
+ "relocation",
344
+ "roommate",
345
+ "roadtrip",
346
+ "school",
347
+ "self-care",
348
+ "sibling",
349
+ "sister",
350
+ "skill",
351
+ "song",
352
+ "son",
353
+ "speech",
354
+ "spouse",
355
+ "sunrise",
356
+ "summer",
357
+ "teammate",
358
+ "trans",
359
+ "transgender",
360
+ "trait",
361
+ "wife",
362
+ "write",
363
+ }
364
+ )
365
+ _TEMPORAL_QUERY_TERMS = (
366
+ "when",
367
+ "how long",
368
+ "long ago",
369
+ "during",
370
+ "before",
371
+ "beforehand",
372
+ "after",
373
+ "afterward",
374
+ "afterwards",
375
+ "since",
376
+ "ago",
377
+ "soon",
378
+ "yesterday",
379
+ "today",
380
+ "tomorrow",
381
+ "earlier today",
382
+ "tonight",
383
+ "earliest event",
384
+ "latest event",
385
+ "upcoming",
386
+ "upcoming event",
387
+ "last night",
388
+ "this morning",
389
+ "this afternoon",
390
+ "this evening",
391
+ "tomorrow morning",
392
+ "tomorrow afternoon",
393
+ "tomorrow evening",
394
+ "yesterday morning",
395
+ "yesterday afternoon",
396
+ "yesterday evening",
397
+ "last weekend",
398
+ "last week",
399
+ "last month",
400
+ "last quarter",
401
+ "last year",
402
+ "next weekend",
403
+ "next week",
404
+ "next month",
405
+ "next quarter",
406
+ "next year",
407
+ "this weekend",
408
+ "this week",
409
+ "this month",
410
+ "this quarter",
411
+ "this year",
412
+ "earlier",
413
+ "later",
414
+ "previous",
415
+ "recent",
416
+ "date",
417
+ "time",
418
+ )
419
+ _ORDERED_EVENT_REQUEST_RE = re.compile(
420
+ r"\b(?P<order>first|earliest|oldest|latest|newest|recent|"
421
+ r"most\s+recent|last|previous|prior|"
422
+ r"next|upcoming)\s+"
423
+ r"(?:conversation|call|meeting|chat|dm|message|text|discussion|sync|"
424
+ r"review|demo|interview|workshop|session)\b",
425
+ re.IGNORECASE,
426
+ )
427
+ _ORDINAL_EVENT_REQUEST_RE = re.compile(
428
+ r"\b(?P<ordinal>first|second|third|fourth|fifth|last|latest)\s+"
429
+ r"(?P<event>(?:(?!(?:at|for|in|of|on|place|the)\b)[a-z0-9-]+\s+){0,3}"
430
+ r"(?:call-?out|competition|event|game|project|screenplay|script|"
431
+ r"tournament|tourney|trip))\b",
432
+ re.IGNORECASE,
433
+ )
434
+ _PERIOD_ANCHOR_TERMS_RE = re.compile(
435
+ r"\b(?:january|february|march|april|may|june|july|august|september|"
436
+ r"october|november|december|spring|summer|fall|autumn|winter|\d{4})\b",
437
+ re.IGNORECASE,
438
+ )
439
+ _SEASON_TERMS = frozenset({"spring", "summer", "fall", "autumn", "winter"})
440
+ _RELATIVE_WEEKDAY_RE = re.compile(
441
+ r"\b(?:last|next|this)\s+"
442
+ r"(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday)\b",
443
+ re.IGNORECASE,
444
+ )
445
+ _TEMPORAL_SURFACE_TERMS = (
446
+ "monday",
447
+ "tuesday",
448
+ "wednesday",
449
+ "thursday",
450
+ "friday",
451
+ "saturday",
452
+ "sunday",
453
+ "christmas",
454
+ "easter",
455
+ "halloween",
456
+ "holiday",
457
+ "independence day",
458
+ "january",
459
+ "february",
460
+ "march",
461
+ "april",
462
+ "may",
463
+ "june",
464
+ "july",
465
+ "august",
466
+ "september",
467
+ "october",
468
+ "november",
469
+ "december",
470
+ "thanksgiving",
471
+ "weekend",
472
+ "quarter",
473
+ "week",
474
+ "month",
475
+ "year",
476
+ )
477
+ _NON_ENTITY_UPPERCASE_TERMS = frozenset({"dob"})
478
+ _QUERY_ENTITY_STOPWORDS = frozenset({"since"})
479
+ _RELATIVE_TEMPORAL_QUERY_SURFACES = (
480
+ "last",
481
+ "today",
482
+ "yesterday",
483
+ "tomorrow",
484
+ "weekend",
485
+ "week",
486
+ )
487
+ _CURRENT_STATE_QUERY_RE = re.compile(
488
+ r"\b(?:current(?:ly)?|now|these\s+days|lately|recent(?:ly)?|"
489
+ r"latest|newest|most\s+recent|last[-\s]+known)\b",
490
+ re.IGNORECASE,
491
+ )
492
+ _PREVIOUS_STATE_QUERY_RE = re.compile(
493
+ r"\b(?:previous|previously|former|formerly|used\s+to|before)\b",
494
+ re.IGNORECASE,
495
+ )
496
+ _VISUAL_QUERY_TERMS = (
497
+ "image",
498
+ "photo",
499
+ "picture",
500
+ "paint",
501
+ "painting",
502
+ "drawing",
503
+ "share",
504
+ "showed",
505
+ "show",
506
+ "shown",
507
+ "shared",
508
+ "saw",
509
+ "see",
510
+ "look",
511
+ )
512
+ _MULTI_HOP_BRIDGE_MARKER_TERMS = {
513
+ "why": ("reason", "because", "cause", "decision", "value", "fit"),
514
+ "how": ("process", "support", "help", "change", "result", "because"),
515
+ "after": ("after", "then", "later", "date", "time"),
516
+ "before": ("before", "earlier", "then", "date", "time"),
517
+ "compare": ("compare", "difference", "alternative", "more", "less"),
518
+ "between": ("between", "difference", "alternative", "more", "less"),
519
+ }
520
+ _COMMONALITY_QUERY_RE = re.compile(
521
+ r"\b(?:both|common|connects?|mutual|overlap|same|shared|similar)\b|"
522
+ r"\bin\s+common\b",
523
+ re.IGNORECASE,
524
+ )
525
+ _COMMONALITY_SUPPORT_SURFACES = (
526
+ "common",
527
+ "shared",
528
+ "both",
529
+ "mutual",
530
+ "same",
531
+ "similar",
532
+ "overlap",
533
+ "connect",
534
+ "place",
535
+ "location",
536
+ "event",
537
+ "activity",
538
+ "preference",
539
+ "interest",
540
+ "hobby",
541
+ "topic",
542
+ )
543
+
544
+
545
+ def expanded_search_query(case: PublicBenchmarkCase) -> tuple[str, dict[str, object]]:
546
+ """Build a fair query expansion from question text only."""
547
+
548
+ intent = _query_retrieval_intent(case)
549
+ profile = intent.to_query_profile()
550
+ focus_parts: list[str] = []
551
+ entities = intent.entity_names
552
+ entity_surfaces = intent.entity_surfaces
553
+ speaker_surfaces = intent.speaker_surfaces
554
+ relation_terms = intent.relation_terms
555
+ relation_variant_terms = intent.relation_variant_terms
556
+ temporal_terms = intent.time_intent.terms
557
+ temporal_surface_terms = intent.time_intent.surface_terms
558
+ visual_terms = intent.visual_terms
559
+ multi_hop_markers = intent.multi_hop_markers
560
+ if entities:
561
+ focus_parts.append(f"entities: {', '.join(entity_surfaces)}")
562
+ if speaker_surfaces:
563
+ focus_parts.append(
564
+ f"speakers: {', '.join(f'{entity}:' for entity in speaker_surfaces)}"
565
+ )
566
+ if relation_terms:
567
+ focus_actions = _support_query_terms(
568
+ relation_terms=relation_terms,
569
+ relation_variant_terms=relation_variant_terms,
570
+ lexical_terms=intent.lexical_terms,
571
+ entity_surfaces=entity_surfaces,
572
+ action_support="action_support" in intent.evidence_need,
573
+ communication_support=(
574
+ "communication_support" in intent.bundle_evidence_roles
575
+ ),
576
+ commitment_support="commitment_profile" in intent.evidence_need,
577
+ contact_support="contact_profile" in intent.evidence_need,
578
+ diet_support="diet_profile" in intent.evidence_need,
579
+ education_support="education_profile" in intent.evidence_need,
580
+ employment_support="employment_profile" in intent.evidence_need,
581
+ age_support="age_profile" in intent.evidence_need,
582
+ alias_support="alias_profile" in intent.evidence_need,
583
+ health_support="health_profile" in intent.evidence_need,
584
+ pet_support="pet_profile" in intent.evidence_need,
585
+ preference_support="preference" in intent.evidence_need,
586
+ skill_support="skill_profile" in intent.evidence_need,
587
+ vehicle_support="vehicle_profile" in intent.evidence_need,
588
+ )
589
+ focus_parts.append(
590
+ f"actions: {', '.join(_render_query_terms(focus_actions[:8]))}"
591
+ )
592
+ if temporal_terms:
593
+ focus_temporal = _temporal_search_terms(temporal_terms, temporal_surface_terms)
594
+ focus_parts.append(f"temporal: {', '.join(focus_temporal[:8])}")
595
+ if "negative_absence" in intent.evidence_need:
596
+ focus_negative = _negative_absence_support_query_terms(
597
+ relation_terms=relation_terms,
598
+ relation_variant_terms=relation_variant_terms,
599
+ lexical_terms=intent.lexical_terms,
600
+ entity_surfaces=entity_surfaces,
601
+ )
602
+ focus_parts.append(f"negative/absence: {', '.join(focus_negative[:8])}")
603
+ if visual_terms:
604
+ focus_visual = tuple(dict.fromkeys((*visual_terms, "image", "photo", "shows")))
605
+ focus_parts.append(f"visual: {', '.join(focus_visual[:8])}")
606
+ if multi_hop_markers:
607
+ focus_parts.append(f"multi-hop markers: {', '.join(multi_hop_markers)}")
608
+ if not focus_parts:
609
+ return case.question, {
610
+ "applied": False,
611
+ "original_query": case.question,
612
+ "expanded_query": case.question,
613
+ "query_profile": profile,
614
+ "retrieval_intent": intent.to_diagnostics(),
615
+ "uses_ground_truth": False,
616
+ }
617
+ expanded = f"{case.question}\nSearch focus: {'; '.join(focus_parts)}"
618
+ return expanded, {
619
+ "applied": True,
620
+ "original_query": case.question,
621
+ "expanded_query": expanded,
622
+ "query_profile": profile,
623
+ "retrieval_intent": intent.to_diagnostics(),
624
+ "uses_ground_truth": False,
625
+ }
626
+
627
+
628
+ def decomposed_search_queries(
629
+ case: PublicBenchmarkCase,
630
+ *,
631
+ max_queries: int = 3,
632
+ ) -> tuple[tuple[str, ...], dict[str, object]]:
633
+ """Build bounded subqueries from question text only."""
634
+
635
+ original_query = str(case.question or "").strip()
636
+ expanded_query, expansion = expanded_search_query(case)
637
+ intent = _query_retrieval_intent(case)
638
+ profile = intent.to_query_profile()
639
+ entities = intent.entity_names
640
+ entity_surfaces = intent.entity_surfaces
641
+ speaker_surfaces = intent.speaker_surfaces
642
+ relation_terms = intent.relation_terms
643
+ relation_variant_terms = intent.relation_variant_terms
644
+ temporal_terms = intent.time_intent.terms
645
+ temporal_surface_terms = intent.time_intent.surface_terms
646
+ lexical_terms = intent.lexical_terms
647
+ is_temporal_query = intent.time_intent.is_temporal
648
+ visual_terms = intent.visual_terms
649
+ multi_hop_markers = intent.multi_hop_markers
650
+ answer_unit_shapes = tuple(_string_sequence(profile.get("answer_unit_shapes")))
651
+
652
+ query_candidates: list[QueryPlanCandidate] = []
653
+ if original_query:
654
+ query_candidates.append(
655
+ QueryPlanCandidate(
656
+ role="original_question",
657
+ query=original_query,
658
+ priority=0,
659
+ query_type="semantic",
660
+ reason_codes=("original_question",),
661
+ )
662
+ )
663
+ if expansion["applied"]:
664
+ query_candidates.append(
665
+ QueryPlanCandidate(
666
+ role="expanded_focus",
667
+ query=expanded_query,
668
+ priority=10,
669
+ query_type="semantic",
670
+ reason_codes=("typed_intent_focus",),
671
+ )
672
+ )
673
+ if visual_terms and is_temporal_query:
674
+ visual_temporal_terms = tuple(
675
+ dict.fromkeys(
676
+ (
677
+ *visual_terms[:3],
678
+ *(
679
+ term
680
+ for term in lexical_terms
681
+ if term not in entity_surfaces and term not in visual_terms
682
+ ),
683
+ *_visual_surface_terms(visual_terms),
684
+ *temporal_terms[:2],
685
+ "date",
686
+ "time",
687
+ "image",
688
+ "caption",
689
+ "shows",
690
+ )
691
+ )
692
+ )
693
+ query_candidates.append(
694
+ QueryPlanCandidate(
695
+ role="visual_temporal_support",
696
+ query=" ".join(
697
+ (*entity_surfaces, *_render_query_terms(visual_temporal_terms[:8]))
698
+ ),
699
+ priority=20,
700
+ query_type="lexical",
701
+ reason_codes=("visual_evidence", "temporal_support"),
702
+ )
703
+ )
704
+ elif visual_terms:
705
+ query_candidates.append(
706
+ QueryPlanCandidate(
707
+ role="visual_support",
708
+ query=" ".join(
709
+ (
710
+ *entity_surfaces,
711
+ *_render_query_terms(visual_terms[:5]),
712
+ "image",
713
+ "shows",
714
+ )
715
+ ),
716
+ priority=20,
717
+ query_type="lexical",
718
+ reason_codes=("visual_evidence",),
719
+ )
720
+ )
721
+ if relation_terms:
722
+ compact_relation_role = _compact_relation_query_role(intent)
723
+ relation_query_terms = _support_query_terms(
724
+ relation_terms=relation_terms,
725
+ relation_variant_terms=relation_variant_terms,
726
+ lexical_terms=lexical_terms,
727
+ entity_surfaces=entity_surfaces,
728
+ action_support=compact_relation_role == "action_support",
729
+ communication_support=compact_relation_role == "communication_support",
730
+ commitment_support=compact_relation_role == "commitment_support",
731
+ contact_support=compact_relation_role == "contact_support",
732
+ diet_support=compact_relation_role == "diet_support",
733
+ education_support=compact_relation_role == "education_support",
734
+ employment_support=compact_relation_role == "employment_support",
735
+ age_support=compact_relation_role == "age_support",
736
+ alias_support=compact_relation_role == "alias_support",
737
+ health_support=compact_relation_role == "health_support",
738
+ pet_support=compact_relation_role == "pet_support",
739
+ preference_support=compact_relation_role
740
+ in {"favorite_support", "preference_support"},
741
+ skill_support=compact_relation_role == "skill_support",
742
+ vehicle_support=compact_relation_role == "vehicle_support",
743
+ )
744
+ if compact_relation_role == "causal_support" and _uses_generic_causal_compact_terms(
745
+ relation_terms=relation_terms,
746
+ multi_hop_markers=multi_hop_markers,
747
+ ):
748
+ relation_query_terms = _causal_compact_query_terms(
749
+ lexical_terms=lexical_terms,
750
+ relation_terms=relation_terms,
751
+ relation_variant_terms=relation_variant_terms,
752
+ fallback_terms=relation_query_terms,
753
+ )
754
+ compact_temporal_terms = (
755
+ _compact_temporal_relation_terms(lexical_terms) if is_temporal_query else ()
756
+ )
757
+ if compact_temporal_terms:
758
+ relation_query_terms = tuple(
759
+ dict.fromkeys(
760
+ (
761
+ *relation_query_terms[:4],
762
+ *compact_temporal_terms,
763
+ *relation_query_terms[4:],
764
+ )
765
+ )
766
+ )
767
+ relation_term_limit = 7
768
+ elif compact_relation_role in {"age_support", "communication_support"}:
769
+ relation_term_limit = 8
770
+ elif (
771
+ "activity" in relation_terms
772
+ or {"prioritize", "self-care"}.issubset(relation_terms)
773
+ or "destress" in relation_terms
774
+ ):
775
+ relation_term_limit = 10 if "destress" in relation_terms else 8
776
+ elif {"current", "live"} <= set(relation_terms):
777
+ relation_term_limit = 9
778
+ else:
779
+ relation_term_limit = 6
780
+ compact_entity_surfaces = speaker_surfaces or entity_surfaces
781
+ query_candidates.append(
782
+ QueryPlanCandidate(
783
+ role=compact_relation_role,
784
+ query=" ".join(
785
+ (
786
+ *compact_entity_surfaces,
787
+ *_render_query_terms(relation_query_terms[:relation_term_limit]),
788
+ )
789
+ ),
790
+ priority=30,
791
+ query_type="lexical",
792
+ reason_codes=(
793
+ "relation_terms",
794
+ "raw_turn_compact",
795
+ f"query_role:{compact_relation_role}",
796
+ ),
797
+ )
798
+ )
799
+ if (
800
+ "preference" in intent.evidence_need
801
+ and "causal_support" in intent.evidence_need
802
+ and compact_relation_role not in {"favorite_support", "preference_support"}
803
+ ):
804
+ preference_query_terms = _preference_support_query_terms(
805
+ relation_terms=relation_terms,
806
+ relation_variant_terms=relation_variant_terms,
807
+ lexical_terms=lexical_terms,
808
+ entity_surfaces=entity_surfaces,
809
+ )
810
+ if preference_query_terms:
811
+ query_candidates.append(
812
+ QueryPlanCandidate(
813
+ role="preference_support",
814
+ query=" ".join(
815
+ (
816
+ *compact_entity_surfaces,
817
+ *_render_query_terms(preference_query_terms[:8]),
818
+ )
819
+ ),
820
+ priority=34,
821
+ query_type="lexical",
822
+ reason_codes=(
823
+ "preference_support",
824
+ "preference_reason_evidence",
825
+ "question_only",
826
+ ),
827
+ )
828
+ )
829
+ contrast_query_terms = (
830
+ _contrast_support_query_terms(
831
+ relation_terms=relation_terms,
832
+ relation_variant_terms=relation_variant_terms,
833
+ lexical_terms=lexical_terms,
834
+ )
835
+ if "contrast" in intent.evidence_need
836
+ else ()
837
+ )
838
+ if contrast_query_terms and (entity_surfaces or len(contrast_query_terms) >= 4):
839
+ query_candidates.append(
840
+ QueryPlanCandidate(
841
+ role="contrast_support",
842
+ query=" ".join(
843
+ (*entity_surfaces, *_render_query_terms(contrast_query_terms[:9]))
844
+ ),
845
+ priority=35,
846
+ query_type="lexical",
847
+ reason_codes=(
848
+ "contrast_support",
849
+ "current_previous_evidence",
850
+ "question_only",
851
+ ),
852
+ )
853
+ )
854
+ negative_absence_query_terms = (
855
+ _negative_absence_support_query_terms(
856
+ relation_terms=relation_terms,
857
+ relation_variant_terms=relation_variant_terms,
858
+ lexical_terms=lexical_terms,
859
+ entity_surfaces=entity_surfaces,
860
+ )
861
+ if "negative_absence" in intent.evidence_need
862
+ else ()
863
+ )
864
+ if negative_absence_query_terms and (
865
+ entity_surfaces or len(negative_absence_query_terms) >= 4
866
+ ):
867
+ query_candidates.append(
868
+ QueryPlanCandidate(
869
+ role="negative_support",
870
+ query=" ".join(
871
+ (
872
+ *entity_surfaces,
873
+ *_render_query_terms(negative_absence_query_terms[:9]),
874
+ )
875
+ ),
876
+ priority=36,
877
+ query_type="lexical",
878
+ reason_codes=(
879
+ "negative_absence_support",
880
+ "question_only",
881
+ ),
882
+ )
883
+ )
884
+ location_query_terms = (
885
+ _location_support_query_terms(
886
+ relation_terms=relation_terms,
887
+ relation_variant_terms=relation_variant_terms,
888
+ lexical_terms=lexical_terms,
889
+ )
890
+ if "location_support" in intent.evidence_need
891
+ and (
892
+ "current" not in relation_terms
893
+ or (
894
+ _has_current_location_query(intent.question)
895
+ and "city" not in lexical_terms
896
+ )
897
+ )
898
+ else ()
899
+ )
900
+ if location_query_terms and (entity_surfaces or len(location_query_terms) >= 4):
901
+ query_candidates.append(
902
+ QueryPlanCandidate(
903
+ role="location_support",
904
+ query=" ".join(
905
+ (*entity_surfaces, *_render_query_terms(location_query_terms[:9]))
906
+ ),
907
+ priority=37,
908
+ query_type="lexical",
909
+ reason_codes=(
910
+ "location_support",
911
+ "location_transition",
912
+ "question_only",
913
+ ),
914
+ )
915
+ )
916
+ evidence_need_set = set(intent.evidence_need)
917
+ count_query_terms = (
918
+ _count_support_query_terms(
919
+ relation_terms=relation_terms,
920
+ relation_variant_terms=relation_variant_terms,
921
+ lexical_terms=lexical_terms,
922
+ entity_surfaces=entity_surfaces,
923
+ )
924
+ if "count_support" in evidence_need_set
925
+ else ()
926
+ )
927
+ if count_query_terms and (entity_surfaces or len(count_query_terms) >= 4):
928
+ query_candidates.append(
929
+ QueryPlanCandidate(
930
+ role="count_support",
931
+ query=" ".join(
932
+ (*entity_surfaces, *_render_query_terms(count_query_terms[:10]))
933
+ ),
934
+ priority=38,
935
+ query_type="lexical",
936
+ reason_codes=(
937
+ "count_support",
938
+ "quantity_aggregation",
939
+ "question_only",
940
+ ),
941
+ )
942
+ )
943
+ list_query_terms = (
944
+ _list_support_query_terms(
945
+ relation_terms=relation_terms,
946
+ relation_variant_terms=relation_variant_terms,
947
+ lexical_terms=lexical_terms,
948
+ entity_surfaces=entity_surfaces,
949
+ )
950
+ if "list_support" in evidence_need_set
951
+ else ()
952
+ )
953
+ if list_query_terms and (entity_surfaces or len(list_query_terms) >= 4):
954
+ query_candidates.append(
955
+ QueryPlanCandidate(
956
+ role="list_support",
957
+ query=" ".join(
958
+ (*entity_surfaces, *_render_query_terms(list_query_terms[:10]))
959
+ ),
960
+ priority=38,
961
+ query_type="lexical",
962
+ reason_codes=(
963
+ "list_support",
964
+ "multi_item_evidence",
965
+ "question_only",
966
+ ),
967
+ )
968
+ )
969
+ value_query_terms = (
970
+ _value_support_query_terms(
971
+ relation_terms=relation_terms,
972
+ relation_variant_terms=relation_variant_terms,
973
+ lexical_terms=lexical_terms,
974
+ entity_surfaces=entity_surfaces,
975
+ )
976
+ if "quantity_dollar" in set(answer_unit_shapes)
977
+ else ()
978
+ )
979
+ if value_query_terms and (entity_surfaces or len(value_query_terms) >= 4):
980
+ query_candidates.append(
981
+ QueryPlanCandidate(
982
+ role="value_support",
983
+ query=" ".join(
984
+ (*entity_surfaces, *_render_query_terms(value_query_terms[:10]))
985
+ ),
986
+ priority=39,
987
+ query_type="lexical",
988
+ reason_codes=(
989
+ "value_support",
990
+ "answer_unit:quantity_dollar",
991
+ "question_only",
992
+ ),
993
+ )
994
+ )
995
+ commonality_query_terms = _commonality_support_query_terms(
996
+ question=original_query,
997
+ entities=entities,
998
+ entity_surfaces=entity_surfaces,
999
+ relation_terms=relation_terms,
1000
+ relation_variant_terms=relation_variant_terms,
1001
+ lexical_terms=lexical_terms,
1002
+ )
1003
+ if commonality_query_terms and len(entity_surfaces) >= 2:
1004
+ query_candidates.append(
1005
+ QueryPlanCandidate(
1006
+ role="commonality_support",
1007
+ query=" ".join(
1008
+ (
1009
+ *entity_surfaces,
1010
+ *_render_query_terms(commonality_query_terms[:12]),
1011
+ )
1012
+ ),
1013
+ priority=36,
1014
+ query_type="lexical",
1015
+ reason_codes=(
1016
+ "commonality_support",
1017
+ "shared_attribute_evidence",
1018
+ "question_only",
1019
+ ),
1020
+ )
1021
+ )
1022
+ temporal_query_terms = (
1023
+ _temporal_search_terms(temporal_terms, temporal_surface_terms)
1024
+ if is_temporal_query
1025
+ else ()
1026
+ )
1027
+ if temporal_query_terms:
1028
+ temporal_role = _temporal_query_role(intent.time_intent.kind)
1029
+ query_candidates.append(
1030
+ QueryPlanCandidate(
1031
+ role=temporal_role,
1032
+ query=" ".join(
1033
+ (*entity_surfaces, *_render_query_terms(temporal_query_terms[:7]))
1034
+ ),
1035
+ priority=40,
1036
+ query_type="lexical",
1037
+ reason_codes=(
1038
+ "temporal_support",
1039
+ temporal_role,
1040
+ f"time_kind:{intent.time_intent.kind}",
1041
+ ),
1042
+ )
1043
+ )
1044
+ bridge_query_terms = (
1045
+ _temporal_multi_hop_bridge_query_terms(
1046
+ relation_terms=relation_terms,
1047
+ relation_variant_terms=relation_variant_terms,
1048
+ lexical_terms=lexical_terms,
1049
+ temporal_terms=temporal_terms,
1050
+ temporal_surface_terms=temporal_surface_terms,
1051
+ multi_hop_markers=multi_hop_markers,
1052
+ )
1053
+ if temporal_query_terms
1054
+ else _multi_hop_bridge_query_terms(
1055
+ relation_terms=relation_terms,
1056
+ relation_variant_terms=relation_variant_terms,
1057
+ lexical_terms=lexical_terms,
1058
+ multi_hop_markers=multi_hop_markers,
1059
+ )
1060
+ )
1061
+ if multi_hop_markers and entity_surfaces and bridge_query_terms:
1062
+ bridge_query_render_terms = tuple(
1063
+ term for term in bridge_query_terms if term not in set(entity_surfaces)
1064
+ )
1065
+ bridge_query_term_limit = 10 if temporal_query_terms else 8
1066
+ query_candidates.append(
1067
+ QueryPlanCandidate(
1068
+ role="multi_hop_bridge",
1069
+ query=" ".join(
1070
+ (
1071
+ *entity_surfaces,
1072
+ *_render_query_terms(
1073
+ bridge_query_render_terms[:bridge_query_term_limit]
1074
+ ),
1075
+ )
1076
+ ),
1077
+ priority=45,
1078
+ query_type="lexical",
1079
+ reason_codes=(
1080
+ "multi_hop_bridge",
1081
+ "entity_relation_bridge",
1082
+ "question_only",
1083
+ ),
1084
+ )
1085
+ )
1086
+ causal_temporal_bridge_terms = _causal_temporal_bridge_query_terms(
1087
+ relation_terms=relation_terms,
1088
+ relation_variant_terms=relation_variant_terms,
1089
+ lexical_terms=lexical_terms,
1090
+ temporal_terms=temporal_terms,
1091
+ temporal_surface_terms=temporal_surface_terms,
1092
+ enabled=(
1093
+ "causal_support" in evidence_need_set
1094
+ and "temporal_sequence" in evidence_need_set
1095
+ ),
1096
+ )
1097
+ if entity_surfaces and causal_temporal_bridge_terms:
1098
+ causal_temporal_bridge_query_terms = tuple(
1099
+ term for term in causal_temporal_bridge_terms if term not in set(entity_surfaces)
1100
+ )
1101
+ query_candidates.append(
1102
+ QueryPlanCandidate(
1103
+ role="multi_hop_bridge",
1104
+ query=" ".join(
1105
+ (
1106
+ *entity_surfaces,
1107
+ *_render_query_terms(causal_temporal_bridge_query_terms[:9]),
1108
+ )
1109
+ ),
1110
+ priority=45,
1111
+ query_type="lexical",
1112
+ reason_codes=(
1113
+ "multi_hop_bridge",
1114
+ "causal_temporal_bridge",
1115
+ "question_only",
1116
+ ),
1117
+ )
1118
+ )
1119
+ causal_bridge_terms = _causal_bridge_query_terms(
1120
+ relation_terms=relation_terms,
1121
+ relation_variant_terms=relation_variant_terms,
1122
+ lexical_terms=lexical_terms,
1123
+ enabled=(
1124
+ "causal_support" in evidence_need_set
1125
+ and not multi_hop_markers
1126
+ and not temporal_query_terms
1127
+ ),
1128
+ )
1129
+ if entity_surfaces and causal_bridge_terms:
1130
+ causal_bridge_query_terms = tuple(
1131
+ term for term in causal_bridge_terms if term not in set(entity_surfaces)
1132
+ )
1133
+ query_candidates.append(
1134
+ QueryPlanCandidate(
1135
+ role="multi_hop_bridge",
1136
+ query=" ".join(
1137
+ (
1138
+ *entity_surfaces,
1139
+ *_render_query_terms(causal_bridge_query_terms[:9]),
1140
+ )
1141
+ ),
1142
+ priority=45,
1143
+ query_type="lexical",
1144
+ reason_codes=(
1145
+ "multi_hop_bridge",
1146
+ "causal_bridge",
1147
+ "question_only",
1148
+ ),
1149
+ )
1150
+ )
1151
+ if multi_hop_markers and entities:
1152
+ query_candidates.append(
1153
+ QueryPlanCandidate(
1154
+ role="multi_hop_support",
1155
+ query=f"{original_query} supporting evidence {' '.join(entity_surfaces)}",
1156
+ priority=50,
1157
+ query_type="semantic",
1158
+ reason_codes=("multi_hop_support",),
1159
+ )
1160
+ )
1161
+
1162
+ extra_query_slots = 0
1163
+ if any(candidate.role == "count_support" for candidate in query_candidates):
1164
+ extra_query_slots += 1
1165
+ if any(candidate.role == "value_support" for candidate in query_candidates):
1166
+ extra_query_slots += 1
1167
+ if any(candidate.role == "contrast_support" for candidate in query_candidates):
1168
+ extra_query_slots += 1
1169
+ if any(candidate.role == "commonality_support" for candidate in query_candidates):
1170
+ extra_query_slots += 1
1171
+ has_temporal_support_query = any(
1172
+ candidate.role == "temporal_support"
1173
+ or candidate.role.endswith("_temporal_support")
1174
+ or candidate.role == "temporal_sequence_support"
1175
+ for candidate in query_candidates
1176
+ )
1177
+ if has_temporal_support_query and max_queries < 3:
1178
+ extra_query_slots += 1
1179
+ has_location_support_query = any(
1180
+ candidate.role == "location_support" for candidate in query_candidates
1181
+ )
1182
+ if has_location_support_query and temporal_query_terms:
1183
+ extra_query_slots += 1
1184
+ has_multi_hop_bridge_query = any(
1185
+ candidate.role == "multi_hop_bridge" for candidate in query_candidates
1186
+ )
1187
+ needs_causal_temporal_bridge = (
1188
+ "causal_support" in evidence_need_set
1189
+ and "temporal_sequence" in evidence_need_set
1190
+ )
1191
+ needs_temporal_multi_hop_bridge = bool(
1192
+ temporal_query_terms and multi_hop_markers and has_multi_hop_bridge_query
1193
+ )
1194
+ if (
1195
+ (
1196
+ not temporal_query_terms
1197
+ or needs_causal_temporal_bridge
1198
+ or needs_temporal_multi_hop_bridge
1199
+ )
1200
+ and has_multi_hop_bridge_query
1201
+ ):
1202
+ extra_query_slots += 1
1203
+ max_selected_queries = max_queries + extra_query_slots
1204
+ max_queries_per_type = (
1205
+ 3
1206
+ if (
1207
+ (has_location_support_query and temporal_query_terms)
1208
+ or ("count_support" in evidence_need_set and visual_terms)
1209
+ or ("count_support" in evidence_need_set and has_multi_hop_bridge_query)
1210
+ or ("count_support" in evidence_need_set and temporal_query_terms)
1211
+ or ("value_support" in evidence_need_set and temporal_query_terms)
1212
+ or needs_causal_temporal_bridge
1213
+ or needs_temporal_multi_hop_bridge
1214
+ or (
1215
+ "causal_support" in evidence_need_set
1216
+ and multi_hop_markers
1217
+ and has_multi_hop_bridge_query
1218
+ )
1219
+ or (
1220
+ "preference" in evidence_need_set
1221
+ and "causal_support" in evidence_need_set
1222
+ and has_multi_hop_bridge_query
1223
+ )
1224
+ or (visual_terms and has_multi_hop_bridge_query)
1225
+ or (
1226
+ contrast_query_terms
1227
+ and (temporal_query_terms or has_location_support_query)
1228
+ )
1229
+ )
1230
+ else 2
1231
+ )
1232
+ query_plan = QueryPlannerV2(
1233
+ max_queries=max_selected_queries,
1234
+ max_queries_per_type=max_queries_per_type,
1235
+ ).plan(
1236
+ query_candidates,
1237
+ fallback_query=original_query,
1238
+ recommended_role_families=_recommended_query_role_families(intent),
1239
+ )
1240
+ unique_queries = query_plan.queries
1241
+ return unique_queries, {
1242
+ "applied": query_plan.applied,
1243
+ "strategy": "question_only_multi_query",
1244
+ "query_count": len(unique_queries),
1245
+ "queries": list(unique_queries),
1246
+ "original_query": original_query,
1247
+ "expanded_query": expanded_query,
1248
+ "query_profile": profile,
1249
+ "retrieval_intent": intent.to_diagnostics(),
1250
+ "query_plan": query_plan.to_diagnostics(),
1251
+ "uses_ground_truth": False,
1252
+ }
1253
+
1254
+
1255
+ def _multi_hop_bridge_query_terms(
1256
+ *,
1257
+ relation_terms: tuple[str, ...],
1258
+ relation_variant_terms: tuple[str, ...],
1259
+ lexical_terms: tuple[str, ...],
1260
+ multi_hop_markers: tuple[str, ...],
1261
+ ) -> tuple[str, ...]:
1262
+ if not multi_hop_markers:
1263
+ return ()
1264
+ bridge_terms: list[str] = []
1265
+ bridge_terms.extend(_relation_query_terms(relation_terms, relation_variant_terms)[:6])
1266
+ for marker in multi_hop_markers:
1267
+ bridge_terms.extend(_MULTI_HOP_BRIDGE_MARKER_TERMS.get(marker, ()))
1268
+ bridge_terms.extend(
1269
+ term
1270
+ for term in lexical_terms
1271
+ if term not in _QUERY_STOPWORDS and term not in bridge_terms
1272
+ )
1273
+ return tuple(dict.fromkeys(bridge_terms))
1274
+
1275
+
1276
+ def _temporal_multi_hop_bridge_query_terms(
1277
+ *,
1278
+ relation_terms: tuple[str, ...],
1279
+ relation_variant_terms: tuple[str, ...],
1280
+ lexical_terms: tuple[str, ...],
1281
+ temporal_terms: tuple[str, ...],
1282
+ temporal_surface_terms: tuple[str, ...],
1283
+ multi_hop_markers: tuple[str, ...],
1284
+ ) -> tuple[str, ...]:
1285
+ if not multi_hop_markers:
1286
+ return ()
1287
+ bridge_terms: list[str] = []
1288
+ bridge_terms.extend(_relation_query_terms(relation_terms, relation_variant_terms)[:6])
1289
+ bridge_terms.extend(
1290
+ term
1291
+ for term in (*temporal_terms, *temporal_surface_terms, *lexical_terms)
1292
+ if term not in _QUERY_STOPWORDS and term not in bridge_terms
1293
+ )
1294
+ for marker in multi_hop_markers:
1295
+ bridge_terms.extend(_MULTI_HOP_BRIDGE_MARKER_TERMS.get(marker, ()))
1296
+ return tuple(dict.fromkeys(bridge_terms))
1297
+
1298
+
1299
+ def _causal_temporal_bridge_query_terms(
1300
+ *,
1301
+ relation_terms: tuple[str, ...],
1302
+ relation_variant_terms: tuple[str, ...],
1303
+ lexical_terms: tuple[str, ...],
1304
+ temporal_terms: tuple[str, ...],
1305
+ temporal_surface_terms: tuple[str, ...],
1306
+ enabled: bool,
1307
+ ) -> tuple[str, ...]:
1308
+ if not enabled:
1309
+ return ()
1310
+ bridge_terms: list[str] = []
1311
+ bridge_terms.extend(_relation_query_terms(relation_terms, relation_variant_terms)[:6])
1312
+ bridge_terms.extend(
1313
+ term
1314
+ for term in (*temporal_terms, *temporal_surface_terms, *lexical_terms)
1315
+ if term not in _QUERY_STOPWORDS and term not in bridge_terms
1316
+ )
1317
+ return tuple(dict.fromkeys(bridge_terms))
1318
+
1319
+
1320
+ def _causal_bridge_query_terms(
1321
+ *,
1322
+ relation_terms: tuple[str, ...],
1323
+ relation_variant_terms: tuple[str, ...],
1324
+ lexical_terms: tuple[str, ...],
1325
+ enabled: bool,
1326
+ ) -> tuple[str, ...]:
1327
+ if not enabled:
1328
+ return ()
1329
+ bridge_terms: list[str] = []
1330
+ relation_query_terms = _relation_query_terms(relation_terms, relation_variant_terms)
1331
+ if set(relation_terms) == {"cause"} and "made" not in set(lexical_terms):
1332
+ relation_query_terms = tuple(
1333
+ term for term in relation_query_terms if term not in {"prompt", "inspir"}
1334
+ )
1335
+ bridge_terms.extend(relation_query_terms[:6])
1336
+ bridge_terms.extend(
1337
+ term
1338
+ for term in lexical_terms
1339
+ if term not in _QUERY_STOPWORDS and term not in bridge_terms
1340
+ )
1341
+ return tuple(dict.fromkeys(bridge_terms))
1342
+
1343
+
1344
+ def _uses_generic_causal_compact_terms(
1345
+ *,
1346
+ relation_terms: tuple[str, ...],
1347
+ multi_hop_markers: tuple[str, ...],
1348
+ ) -> bool:
1349
+ relation_set = set(relation_terms)
1350
+ if relation_set & {"realize", "help"}:
1351
+ return False
1352
+ return bool(
1353
+ {"why"} & set(multi_hop_markers)
1354
+ or relation_set
1355
+ & {
1356
+ "because",
1357
+ "caus",
1358
+ "cause",
1359
+ "motivat",
1360
+ "motivate",
1361
+ "motivation",
1362
+ "reason",
1363
+ }
1364
+ )
1365
+
1366
+
1367
+ def _count_support_query_terms(
1368
+ *,
1369
+ relation_terms: tuple[str, ...],
1370
+ relation_variant_terms: tuple[str, ...],
1371
+ lexical_terms: tuple[str, ...],
1372
+ entity_surfaces: tuple[str, ...],
1373
+ ) -> tuple[str, ...]:
1374
+ entity_tokens = {
1375
+ token for surface in entity_surfaces for token in _normalized_terms(surface)
1376
+ }
1377
+ count_terms: list[str] = []
1378
+ count_terms.extend(_relation_query_terms(relation_terms, relation_variant_terms)[:6])
1379
+ count_terms.extend(
1380
+ term
1381
+ for term in lexical_terms
1382
+ if term not in _QUERY_STOPWORDS
1383
+ and term not in entity_tokens
1384
+ and term not in count_terms
1385
+ )
1386
+ count_terms.extend(("count", "number", "total", "times"))
1387
+ if "time" in lexical_terms:
1388
+ count_terms.extend(("once", "twice", "three times", "repeated"))
1389
+ return tuple(dict.fromkeys(count_terms))
1390
+
1391
+
1392
+ def _list_support_query_terms(
1393
+ *,
1394
+ relation_terms: tuple[str, ...],
1395
+ relation_variant_terms: tuple[str, ...],
1396
+ lexical_terms: tuple[str, ...],
1397
+ entity_surfaces: tuple[str, ...],
1398
+ ) -> tuple[str, ...]:
1399
+ list_terms = list(
1400
+ _count_support_query_terms(
1401
+ relation_terms=relation_terms,
1402
+ relation_variant_terms=relation_variant_terms,
1403
+ lexical_terms=lexical_terms,
1404
+ entity_surfaces=entity_surfaces,
1405
+ )
1406
+ )
1407
+ list_terms.extend(("list", "names", "items", "including"))
1408
+ return tuple(dict.fromkeys(list_terms))
1409
+
1410
+
1411
+ def _value_support_query_terms(
1412
+ *,
1413
+ relation_terms: tuple[str, ...],
1414
+ relation_variant_terms: tuple[str, ...],
1415
+ lexical_terms: tuple[str, ...],
1416
+ entity_surfaces: tuple[str, ...],
1417
+ ) -> tuple[str, ...]:
1418
+ entity_tokens = {
1419
+ token for surface in entity_surfaces for token in _normalized_terms(surface)
1420
+ }
1421
+ value_terms: list[str] = []
1422
+ value_terms.extend(_relation_query_terms(relation_terms, relation_variant_terms)[:5])
1423
+ value_terms.extend(
1424
+ term
1425
+ for term in lexical_terms
1426
+ if term not in _QUERY_STOPWORDS
1427
+ and term not in entity_tokens
1428
+ and term not in value_terms
1429
+ )
1430
+ value_terms.extend(
1431
+ (
1432
+ "amount",
1433
+ "cost",
1434
+ "price",
1435
+ "value",
1436
+ "dollar",
1437
+ "dollars",
1438
+ "usd",
1439
+ "paid",
1440
+ "fee",
1441
+ "deposit",
1442
+ "budget",
1443
+ "total",
1444
+ )
1445
+ )
1446
+ return tuple(dict.fromkeys(value_terms))
1447
+
1448
+
1449
+ def _commonality_support_query_terms(
1450
+ *,
1451
+ question: str,
1452
+ entities: tuple[str, ...],
1453
+ entity_surfaces: tuple[str, ...],
1454
+ relation_terms: tuple[str, ...],
1455
+ relation_variant_terms: tuple[str, ...],
1456
+ lexical_terms: tuple[str, ...],
1457
+ ) -> tuple[str, ...]:
1458
+ if not _has_commonality_support_intent(question=question, entities=entities):
1459
+ return ()
1460
+ entity_tokens = {
1461
+ token for surface in entity_surfaces for token in _normalized_terms(surface)
1462
+ }
1463
+ commonality_terms: list[str] = list(_COMMONALITY_SUPPORT_SURFACES)
1464
+ commonality_terms.extend(
1465
+ _relation_query_terms(relation_terms, relation_variant_terms)[:6]
1466
+ )
1467
+ commonality_terms.extend(
1468
+ term
1469
+ for term in lexical_terms
1470
+ if term not in _QUERY_STOPWORDS
1471
+ and term not in entity_tokens
1472
+ and term not in commonality_terms
1473
+ )
1474
+ return tuple(dict.fromkeys(commonality_terms))
1475
+
1476
+
1477
+ def _has_commonality_support_intent(
1478
+ *,
1479
+ question: str,
1480
+ entities: tuple[str, ...],
1481
+ ) -> bool:
1482
+ return len(entities) >= 2 and _COMMONALITY_QUERY_RE.search(question) is not None
1483
+
1484
+
1485
+ def _causal_compact_query_terms(
1486
+ *,
1487
+ lexical_terms: tuple[str, ...],
1488
+ relation_terms: tuple[str, ...],
1489
+ relation_variant_terms: tuple[str, ...],
1490
+ fallback_terms: tuple[str, ...],
1491
+ ) -> tuple[str, ...]:
1492
+ emotion_cue_terms = (
1493
+ "happy",
1494
+ "sad",
1495
+ "angry",
1496
+ "frustrat",
1497
+ "frustration",
1498
+ "nervous",
1499
+ "proud",
1500
+ "relieved",
1501
+ "upset",
1502
+ "worried",
1503
+ "excite",
1504
+ "excited",
1505
+ )
1506
+ causal_variant_order = (
1507
+ "motivat",
1508
+ "motivation",
1509
+ "reason",
1510
+ "because",
1511
+ "cause",
1512
+ "caus",
1513
+ "decision",
1514
+ "explain",
1515
+ "prompt",
1516
+ "inspir",
1517
+ "reflect",
1518
+ "felt",
1519
+ "reaction",
1520
+ "response",
1521
+ )
1522
+ variant_set = set(relation_variant_terms)
1523
+ relation_set = set(relation_terms)
1524
+ lexical_set = set(lexical_terms)
1525
+ if {"choose", "adoption", "agency"}.issubset(relation_set):
1526
+ prioritized = (
1527
+ "adoption",
1528
+ "chose",
1529
+ "reason",
1530
+ "cause",
1531
+ "fit",
1532
+ "value",
1533
+ "because",
1534
+ "decision",
1535
+ )
1536
+ return tuple(
1537
+ dict.fromkeys(
1538
+ (
1539
+ *prioritized,
1540
+ *(term for term in fallback_terms if term not in set(prioritized)),
1541
+ )
1542
+ )
1543
+ )
1544
+ prioritized_emotion_terms = tuple(
1545
+ term for term in emotion_cue_terms if term in lexical_set
1546
+ )
1547
+ prioritized_variants = tuple(
1548
+ term for term in causal_variant_order if term in variant_set
1549
+ )
1550
+ missing_generic_causal_terms = tuple(
1551
+ term
1552
+ for term in ("reason", "because", "cause")
1553
+ if term not in relation_set and term not in variant_set
1554
+ )
1555
+ return tuple(
1556
+ dict.fromkeys(
1557
+ (
1558
+ *relation_terms,
1559
+ *prioritized_emotion_terms,
1560
+ *prioritized_variants,
1561
+ *missing_generic_causal_terms,
1562
+ *fallback_terms,
1563
+ )
1564
+ )
1565
+ )
1566
+
1567
+
1568
+ def _recommended_query_role_families(intent: RetrievalIntent) -> tuple[str, ...]:
1569
+ families: list[str] = ["base_query"]
1570
+ if _has_commonality_support_intent(
1571
+ question=intent.question,
1572
+ entities=intent.entity_names,
1573
+ ):
1574
+ families.append("commonality_support")
1575
+ if intent.relation_terms or intent.relation_variant_terms:
1576
+ families.append("relation_compact")
1577
+ if "preference" in intent.evidence_need:
1578
+ families.append("preference_support")
1579
+ if intent.visual_terms:
1580
+ families.append("visual_support")
1581
+ if intent.time_intent.is_temporal and not (
1582
+ "contrast" in intent.evidence_need
1583
+ and intent.time_intent.kind == "temporal_sequence"
1584
+ ):
1585
+ families.append("temporal_support")
1586
+ if "contrast" in intent.evidence_need:
1587
+ families.append("contrast_support")
1588
+ if "negative_absence" in intent.evidence_need:
1589
+ families.append("negative_support")
1590
+ if "location_support" in intent.evidence_need:
1591
+ families.append("location_support")
1592
+ if "count_support" in intent.evidence_need:
1593
+ families.append("count_support")
1594
+ if "list_support" in intent.evidence_need:
1595
+ families.append("list_support")
1596
+ if "value_support" in intent.evidence_need:
1597
+ families.append("value_support")
1598
+ if "causal_support" in intent.evidence_need:
1599
+ families.append("causal_support")
1600
+ families.append("multi_hop")
1601
+ if "multi_hop" in intent.evidence_need or intent.multi_hop_markers:
1602
+ families.append("multi_hop")
1603
+ return tuple(dict.fromkeys(families))
1604
+
1605
+
1606
+ def _compact_relation_query_role(intent: RetrievalIntent) -> str:
1607
+ evidence_needs = set(intent.evidence_need)
1608
+ if "education_profile" in evidence_needs:
1609
+ return "education_support"
1610
+ if "action_support" in evidence_needs:
1611
+ return "action_support"
1612
+ if "commitment_profile" in evidence_needs:
1613
+ return "commitment_support"
1614
+ if "contact_profile" in evidence_needs:
1615
+ return "contact_support"
1616
+ if "date_profile" in evidence_needs:
1617
+ return "date_support"
1618
+ if "diet_profile" in evidence_needs:
1619
+ return "diet_support"
1620
+ if "identity_profile" in evidence_needs:
1621
+ return "identity_support"
1622
+ if "community_membership" in evidence_needs:
1623
+ return "community_membership_support"
1624
+ if "communication" in evidence_needs:
1625
+ return "communication_support"
1626
+ if "causal_support" in evidence_needs and "reason" in set(intent.relation_terms):
1627
+ return "causal_support"
1628
+ if "causal_support" in evidence_needs and {
1629
+ "because",
1630
+ "caus",
1631
+ "cause",
1632
+ } & set(intent.relation_terms):
1633
+ return "causal_support"
1634
+ if "causal_support" in evidence_needs and {
1635
+ "motivat",
1636
+ "motivate",
1637
+ "motivation",
1638
+ } & set(intent.relation_terms):
1639
+ return "causal_support"
1640
+ if (
1641
+ "causal_support" in evidence_needs
1642
+ and "emotion_response" in evidence_needs
1643
+ and "inspir" in set(intent.relation_terms)
1644
+ ):
1645
+ return "causal_support"
1646
+ if {"activity_profile", "activity_support"} & evidence_needs:
1647
+ return "activity_support"
1648
+ if "employment_profile" in evidence_needs:
1649
+ return "employment_support"
1650
+ if "age_profile" in evidence_needs:
1651
+ return "age_support"
1652
+ if "alias_profile" in evidence_needs:
1653
+ return "alias_support"
1654
+ if "health_profile" in evidence_needs:
1655
+ return "health_support"
1656
+ if "pet_profile" in evidence_needs:
1657
+ return "pet_support"
1658
+ if "skill_profile" in evidence_needs:
1659
+ return "skill_support"
1660
+ if "status_profile" in evidence_needs:
1661
+ return "status_support"
1662
+ if "vehicle_profile" in evidence_needs:
1663
+ return "vehicle_support"
1664
+ if "causal_support" in evidence_needs:
1665
+ return "causal_support"
1666
+ if "support_goal" in evidence_needs:
1667
+ return "support_goal_support"
1668
+ if "current_goal" in evidence_needs:
1669
+ return "current_goal_support"
1670
+ if "favorite_preference" in evidence_needs:
1671
+ return "favorite_support"
1672
+ role_priority = (
1673
+ "communication_support",
1674
+ "event_support",
1675
+ "exchange_support",
1676
+ "emotion_response_support",
1677
+ "symbolic_meaning_support",
1678
+ "preference_support",
1679
+ "causal_support",
1680
+ )
1681
+ roles = set(intent.bundle_evidence_roles)
1682
+ for role in role_priority:
1683
+ if role in roles:
1684
+ return role
1685
+ return "compact_relation"
1686
+
1687
+
1688
+ def _negative_absence_support_query_terms(
1689
+ *,
1690
+ relation_terms: tuple[str, ...],
1691
+ relation_variant_terms: tuple[str, ...],
1692
+ lexical_terms: tuple[str, ...],
1693
+ entity_surfaces: tuple[str, ...],
1694
+ ) -> tuple[str, ...]:
1695
+ entity_tokens = {
1696
+ token for surface in entity_surfaces for token in _normalized_terms(surface)
1697
+ }
1698
+ topical_terms = tuple(
1699
+ term
1700
+ for term in lexical_terms
1701
+ if term not in _QUERY_STOPWORDS
1702
+ and term not in relation_terms
1703
+ and term not in relation_variant_terms
1704
+ and term not in entity_tokens
1705
+ )
1706
+ return tuple(
1707
+ dict.fromkeys(
1708
+ (
1709
+ *_relation_query_terms(relation_terms, relation_variant_terms),
1710
+ *topical_terms[:5],
1711
+ "no",
1712
+ "not",
1713
+ "never",
1714
+ "none",
1715
+ "not yet",
1716
+ "no longer",
1717
+ "without",
1718
+ "missing",
1719
+ "absent",
1720
+ "stale",
1721
+ )
1722
+ )
1723
+ )
1724
+
1725
+
1726
+ def _temporal_query_role(time_kind: str) -> str:
1727
+ return {
1728
+ "duration": "duration_temporal_support",
1729
+ "explicit_time": "explicit_temporal_support",
1730
+ "relative_time": "relative_temporal_support",
1731
+ "temporal_sequence": "temporal_sequence_support",
1732
+ }.get(time_kind, "temporal_support")
1733
+
1734
+
1735
+ def query_support_terms(case: PublicBenchmarkCase) -> tuple[str, ...]:
1736
+ """Return question-only terms useful for evidence support diagnostics."""
1737
+
1738
+ profile = _query_retrieval_intent(case).to_query_profile()
1739
+ terms: list[str] = []
1740
+ for key in (
1741
+ "entities",
1742
+ "entity_surfaces",
1743
+ "relation_terms",
1744
+ "relation_variant_terms",
1745
+ "temporal_terms",
1746
+ "temporal_surface_terms",
1747
+ "visual_terms",
1748
+ "lexical_terms",
1749
+ ):
1750
+ terms.extend(_string_sequence(profile.get(key)))
1751
+ return tuple(dict.fromkeys(terms))
1752
+
1753
+
1754
+ def temporal_rerank_memories(
1755
+ case: PublicBenchmarkCase,
1756
+ memories: Sequence[RetrievedMemory],
1757
+ ) -> tuple[list[RetrievedMemory], dict[str, object]]:
1758
+ profile = _temporal_query_profile(case)
1759
+ if not profile["is_temporal_query"] or not memories:
1760
+ return list(memories), {
1761
+ **profile,
1762
+ "applied": False,
1763
+ "timestamped_memory_count": _timestamped_memory_count(memories),
1764
+ "reranked_memory_count": 0,
1765
+ }
1766
+ timestamp_order_boosts = _temporal_timestamp_order_boosts(memories, profile)
1767
+ session_order_boosts = _temporal_session_order_boosts(
1768
+ memories,
1769
+ profile,
1770
+ timestamp_order_boosts=timestamp_order_boosts,
1771
+ )
1772
+ reranked = [
1773
+ _with_temporal_rerank_boost(
1774
+ memory,
1775
+ timestamp_order_boost=timestamp_order_boosts.get(index, 0.0),
1776
+ session_order_boost=session_order_boosts.get(index, 0.0),
1777
+ )
1778
+ if _memory_timestamp_values(memory)
1779
+ or session_order_boosts.get(index, 0.0) > 0
1780
+ else memory
1781
+ for index, memory in enumerate(memories)
1782
+ ]
1783
+ reranked.sort(key=lambda memory: (-memory.score, memory.rank))
1784
+ timestamped_count = _timestamped_memory_count(memories)
1785
+ return reranked, {
1786
+ **profile,
1787
+ "applied": timestamped_count > 0,
1788
+ "timestamped_memory_count": timestamped_count,
1789
+ "reranked_memory_count": len(reranked),
1790
+ "boost": 0.3 if timestamped_count > 0 else 0.0,
1791
+ "timestamp_order_boosted_count": sum(
1792
+ 1 for boost in timestamp_order_boosts.values() if boost > 0
1793
+ ),
1794
+ "session_order_boosted_count": sum(
1795
+ 1 for boost in session_order_boosts.values() if boost > 0
1796
+ ),
1797
+ }
1798
+
1799
+
1800
+ def benchmark_rerank_memories(
1801
+ case: PublicBenchmarkCase,
1802
+ memories: Sequence[RetrievedMemory],
1803
+ ) -> tuple[list[RetrievedMemory], dict[str, object]]:
1804
+ intent = _query_retrieval_intent(case)
1805
+ profile = _query_profile_for_rerank(case, intent)
1806
+ if not memories or not profile["lexical_terms"]:
1807
+ return list(memories), {
1808
+ "applied": False,
1809
+ "boosted_memory_count": 0,
1810
+ "max_boost": 0.0,
1811
+ "query_profile": profile,
1812
+ "retrieval_intent": intent.to_diagnostics(),
1813
+ "uses_ground_truth": False,
1814
+ }
1815
+
1816
+ reranked: list[RetrievedMemory] = []
1817
+ boosts: list[float] = []
1818
+ for memory in memories:
1819
+ reranked_memory, boost = _with_benchmark_rerank_boost(
1820
+ memory,
1821
+ profile,
1822
+ question=str(case.question or ""),
1823
+ )
1824
+ reranked.append(reranked_memory)
1825
+ if boost > 0:
1826
+ boosts.append(boost)
1827
+
1828
+ reranked.sort(key=_benchmark_rerank_sort_key)
1829
+ return reranked, {
1830
+ "applied": bool(boosts),
1831
+ "boosted_memory_count": len(boosts),
1832
+ "max_boost": round(max(boosts), 6) if boosts else 0.0,
1833
+ "query_profile": profile,
1834
+ "retrieval_intent": intent.to_diagnostics(),
1835
+ "uses_ground_truth": False,
1836
+ }
1837
+
1838
+
1839
+ def _benchmark_rerank_sort_key(memory: RetrievedMemory) -> tuple[float, float, float, int]:
1840
+ diagnostics = (
1841
+ memory.metadata.get("diagnostics")
1842
+ if isinstance(memory.metadata.get("diagnostics"), Mapping)
1843
+ else {}
1844
+ )
1845
+ score_signals = (
1846
+ diagnostics.get("score_signals")
1847
+ if isinstance(diagnostics.get("score_signals"), Mapping)
1848
+ else {}
1849
+ )
1850
+ visual_boost = _positive_float(
1851
+ score_signals.get("benchmark_visual_evidence_boost")
1852
+ )
1853
+ focused_support_boost = sum(
1854
+ _positive_float(score_signals.get(key))
1855
+ for key in (
1856
+ "benchmark_focused_turn_boost",
1857
+ "benchmark_political_context_boost",
1858
+ "benchmark_roadtrip_incident_boost",
1859
+ "benchmark_destress_running_shape_boost",
1860
+ "benchmark_outdoor_park_preference_boost",
1861
+ "benchmark_activity_coverage_shape_boost",
1862
+ "benchmark_adoption_reaction_boost",
1863
+ "benchmark_birthday_memory_boost",
1864
+ "benchmark_bookshelf_collection_boost",
1865
+ "benchmark_career_contrast_shape_boost",
1866
+ "benchmark_excited_outcome_boost",
1867
+ "benchmark_friend_duration_boost",
1868
+ "benchmark_kids_preference_shape_boost",
1869
+ "benchmark_personality_trait_shape_boost",
1870
+ "benchmark_realization_self_care_boost",
1871
+ )
1872
+ )
1873
+ return (-memory.score, -focused_support_boost, -visual_boost, memory.rank)
1874
+
1875
+
1876
+ def _positive_float(value: object) -> float:
1877
+ try:
1878
+ parsed = float(value)
1879
+ except (TypeError, ValueError):
1880
+ return 0.0
1881
+ return parsed if parsed > 0 else 0.0
1882
+
1883
+
1884
+ def _with_temporal_rerank_boost(
1885
+ memory: RetrievedMemory,
1886
+ *,
1887
+ timestamp_order_boost: float = 0.0,
1888
+ session_order_boost: float = 0.0,
1889
+ ) -> RetrievedMemory:
1890
+ diagnostics = (
1891
+ dict(memory.metadata.get("diagnostics"))
1892
+ if isinstance(memory.metadata.get("diagnostics"), Mapping)
1893
+ else {}
1894
+ )
1895
+ score_signals = (
1896
+ dict(diagnostics.get("score_signals"))
1897
+ if isinstance(diagnostics.get("score_signals"), Mapping)
1898
+ else {}
1899
+ )
1900
+ score_signals["benchmark_temporal_source_ref_boost"] = 0.3
1901
+ if timestamp_order_boost > 0:
1902
+ score_signals["benchmark_temporal_timestamp_order_boost"] = round(
1903
+ timestamp_order_boost,
1904
+ 6,
1905
+ )
1906
+ if session_order_boost > 0:
1907
+ score_signals["benchmark_temporal_session_order_boost"] = round(
1908
+ session_order_boost,
1909
+ 6,
1910
+ )
1911
+ diagnostics["score_signals"] = score_signals
1912
+ diagnostics["temporal_rerank_boosted"] = True
1913
+ return replace(
1914
+ memory,
1915
+ score=round(memory.score + 0.3 + timestamp_order_boost + session_order_boost, 6),
1916
+ metadata={**dict(memory.metadata), "diagnostics": diagnostics},
1917
+ )
1918
+
1919
+
1920
+ def _temporal_timestamp_order_boosts(
1921
+ memories: Sequence[RetrievedMemory],
1922
+ profile: Mapping[str, object],
1923
+ ) -> dict[int, float]:
1924
+ matched_terms = set(_string_sequence(profile.get("matched_terms")))
1925
+ if not _requests_temporal_order_boost(matched_terms):
1926
+ return {}
1927
+ earliest_requested = "earliest event" in matched_terms
1928
+ timestamped: list[tuple[int, int]] = []
1929
+ for index, memory in enumerate(memories):
1930
+ timestamps = _memory_timestamp_values(memory)
1931
+ if timestamps:
1932
+ representative_timestamp = (
1933
+ min(timestamps) if earliest_requested else max(timestamps)
1934
+ )
1935
+ timestamped.append((index, representative_timestamp))
1936
+ if len(timestamped) <= 1:
1937
+ return {}
1938
+ ordered_timestamps = sorted({timestamp for _, timestamp in timestamped})
1939
+ if len(ordered_timestamps) <= 1:
1940
+ return {}
1941
+ denominator = len(ordered_timestamps) - 1
1942
+ return {
1943
+ index: round(
1944
+ 0.12
1945
+ * (
1946
+ 1.0 - (ordered_timestamps.index(timestamp) / denominator)
1947
+ if earliest_requested
1948
+ else ordered_timestamps.index(timestamp) / denominator
1949
+ ),
1950
+ 6,
1951
+ )
1952
+ for index, timestamp in timestamped
1953
+ }
1954
+
1955
+
1956
+ def _temporal_session_order_boosts(
1957
+ memories: Sequence[RetrievedMemory],
1958
+ profile: Mapping[str, object],
1959
+ *,
1960
+ timestamp_order_boosts: Mapping[int, float],
1961
+ ) -> dict[int, float]:
1962
+ matched_terms = set(_string_sequence(profile.get("matched_terms")))
1963
+ if not _requests_temporal_order_boost(matched_terms):
1964
+ return {}
1965
+ earliest_requested = "earliest event" in matched_terms
1966
+ session_indexed: list[tuple[int, int]] = []
1967
+ for index, memory in enumerate(memories):
1968
+ if index in timestamp_order_boosts:
1969
+ continue
1970
+ session_indices = _memory_session_indices(memory)
1971
+ if session_indices:
1972
+ representative_session = (
1973
+ min(session_indices) if earliest_requested else max(session_indices)
1974
+ )
1975
+ session_indexed.append((index, representative_session))
1976
+ if len(session_indexed) <= 1:
1977
+ return {}
1978
+ ordered_sessions = sorted({session for _, session in session_indexed})
1979
+ if len(ordered_sessions) <= 1:
1980
+ return {}
1981
+ denominator = len(ordered_sessions) - 1
1982
+ return {
1983
+ index: round(
1984
+ 0.1
1985
+ * (
1986
+ 1.0 - (ordered_sessions.index(session) / denominator)
1987
+ if earliest_requested
1988
+ else ordered_sessions.index(session) / denominator
1989
+ ),
1990
+ 6,
1991
+ )
1992
+ for index, session in session_indexed
1993
+ }
1994
+
1995
+
1996
+ def _requests_temporal_order_boost(matched_terms: set[str]) -> bool:
1997
+ return bool(
1998
+ {
1999
+ "again",
2000
+ "currently",
2001
+ "earliest event",
2002
+ "latest event",
2003
+ "recent",
2004
+ "soon",
2005
+ "upcoming",
2006
+ "upcoming event",
2007
+ }
2008
+ & matched_terms
2009
+ )
2010
+
2011
+
2012
+ def _memory_session_indices(memory: RetrievedMemory) -> tuple[int, ...]:
2013
+ raw_values = [
2014
+ memory.metadata.get("session_index"),
2015
+ memory.metadata.get("session_id"),
2016
+ ]
2017
+ session_key = memory.metadata.get("session_key")
2018
+ if isinstance(session_key, str):
2019
+ raw_values.append(session_key)
2020
+ raw_values.extend(memory.source_refs)
2021
+ raw_values.append(memory.text)
2022
+ indices: list[int] = []
2023
+ for value in raw_values:
2024
+ if (parsed := _optional_int(value)) is not None:
2025
+ indices.append(parsed)
2026
+ continue
2027
+ for match in re.finditer(r"\bsession_(\d+)\b", str(value or ""), re.IGNORECASE):
2028
+ indices.append(int(match.group(1)))
2029
+ return tuple(dict.fromkeys(index for index in indices if index > 0))
2030
+
2031
+
2032
+ def query_retrieval_intent(case: PublicBenchmarkCase) -> RetrievalIntent:
2033
+ """Build question-only retrieval intent shared by planner, rerank and evidence."""
2034
+
2035
+ return _query_retrieval_intent(case)
2036
+
2037
+
2038
+ def _query_retrieval_intent(case: PublicBenchmarkCase) -> RetrievalIntent:
2039
+ question = str(case.question or "")
2040
+ lexical_terms = tuple(
2041
+ dict.fromkeys((*_normalized_terms(question), *_question_phrase_terms(question)))
2042
+ )
2043
+ entity_names = tuple(dict.fromkeys(_query_entities(question)))
2044
+ entities = tuple(
2045
+ RetrievalEntityIntent(
2046
+ canonical=entity,
2047
+ surfaces=_entity_surfaces((entity,)),
2048
+ speaker_surfaces=_speaker_surfaces(_entity_surfaces((entity,))),
2049
+ )
2050
+ for entity in entity_names
2051
+ )
2052
+ relation_terms = tuple(term for term in lexical_terms if term in _RELATION_QUERY_TERMS)
2053
+ relation_terms = _filter_relation_terms_for_profile(
2054
+ question=question,
2055
+ relation_terms=relation_terms,
2056
+ )
2057
+ normalized_question = re.sub(r"[^0-9a-z]+", " ", question.casefold()).strip()
2058
+ if "skill" not in relation_terms and _has_skill_profile_question(normalized_question):
2059
+ relation_terms = (*relation_terms, "skill")
2060
+ if "diet" not in relation_terms and _has_diet_profile_question(normalized_question):
2061
+ relation_terms = (*relation_terms, "diet")
2062
+ relation_variant_terms = tuple(
2063
+ dict.fromkeys(
2064
+ variant
2065
+ for relation in relation_terms
2066
+ for variant in _relation_variant_terms(relation)
2067
+ )
2068
+ )
2069
+ relation_variant_terms = _filter_relation_variant_terms_for_profile(
2070
+ question=question,
2071
+ relation_terms=relation_terms,
2072
+ relation_variant_terms=relation_variant_terms,
2073
+ )
2074
+ temporal_profile = _temporal_query_profile(case)
2075
+ visual_terms = tuple(term for term in lexical_terms if term in _VISUAL_QUERY_TERMS)
2076
+ category = _optional_int(case.metadata.get("category"))
2077
+ marker_candidates = ["why"]
2078
+ is_count_question = bool(
2079
+ re.search(r"\b(?:how\s+many|number\s+of|count\s+of)\b", question, re.IGNORECASE)
2080
+ )
2081
+ if (category == 1 and not is_count_question) or _non_temporal_process_how_marker(
2082
+ question
2083
+ ):
2084
+ marker_candidates.append("how")
2085
+ multi_hop_markers = tuple(
2086
+ marker
2087
+ for marker in marker_candidates
2088
+ if re.search(rf"\b{re.escape(marker)}\b", question, flags=re.IGNORECASE)
2089
+ )
2090
+ temporal_terms = tuple(temporal_profile["matched_terms"])
2091
+ temporal_surface_terms = tuple(temporal_profile["surface_terms"])
2092
+ answer_unit_shapes = _requested_answer_unit_shapes(question)
2093
+ time_intent = RetrievalTimeIntent(
2094
+ is_temporal=bool(temporal_profile["is_temporal_query"]),
2095
+ terms=temporal_terms,
2096
+ surface_terms=temporal_surface_terms,
2097
+ kind=infer_time_intent_kind(
2098
+ is_temporal=bool(temporal_profile["is_temporal_query"]),
2099
+ temporal_terms=temporal_terms,
2100
+ temporal_surface_terms=temporal_surface_terms,
2101
+ ),
2102
+ )
2103
+ relation_intents = infer_relation_intents(
2104
+ question=question,
2105
+ relation_terms=relation_terms,
2106
+ relation_variant_terms=relation_variant_terms,
2107
+ time_intent=time_intent,
2108
+ visual_terms=visual_terms,
2109
+ multi_hop_markers=multi_hop_markers,
2110
+ )
2111
+ evidence_need = merge_relation_evidence_needs(
2112
+ infer_evidence_need(
2113
+ question=question,
2114
+ relation_terms=relation_terms,
2115
+ time_intent=time_intent,
2116
+ visual_terms=visual_terms,
2117
+ multi_hop_markers=multi_hop_markers,
2118
+ benchmark_category=category,
2119
+ answer_unit_shapes=answer_unit_shapes,
2120
+ ),
2121
+ relation_intents,
2122
+ )
2123
+ return RetrievalIntent(
2124
+ question=question,
2125
+ lexical_terms=lexical_terms,
2126
+ entities=entities,
2127
+ relation_terms=relation_terms,
2128
+ relation_variant_terms=relation_variant_terms,
2129
+ time_intent=time_intent,
2130
+ visual_terms=visual_terms,
2131
+ multi_hop_markers=multi_hop_markers,
2132
+ evidence_need=evidence_need,
2133
+ risk_flags=infer_risk_flags(
2134
+ entity_count=len(entities),
2135
+ relation_terms=relation_terms,
2136
+ relation_variant_terms=relation_variant_terms,
2137
+ time_intent=time_intent,
2138
+ ),
2139
+ bundle_evidence_roles=infer_bundle_evidence_roles(
2140
+ evidence_need=evidence_need,
2141
+ benchmark_category=category,
2142
+ ),
2143
+ relation_intents=relation_intents,
2144
+ answer_unit_shapes=answer_unit_shapes,
2145
+ )
2146
+
2147
+
2148
+ def _query_rerank_profile(case: PublicBenchmarkCase) -> dict[str, object]:
2149
+ intent = _query_retrieval_intent(case)
2150
+ return _query_profile_for_rerank(case, intent)
2151
+
2152
+
2153
+ def _query_profile_for_rerank(
2154
+ case: PublicBenchmarkCase,
2155
+ intent: RetrievalIntent,
2156
+ ) -> dict[str, object]:
2157
+ profile = intent.to_query_profile()
2158
+ current_state_query = _has_current_state_query(case.question)
2159
+ comparative_option_preference = _comparative_option_preference_query(
2160
+ case.question,
2161
+ profile,
2162
+ current_state_query=current_state_query,
2163
+ )
2164
+ if comparative_option_preference:
2165
+ profile = _without_contrast_requirement(profile)
2166
+ return {
2167
+ **profile,
2168
+ "question": str(case.question or ""),
2169
+ "current_state_query": current_state_query,
2170
+ "comparative_option_preference_query": comparative_option_preference,
2171
+ "source_grounding_query": _is_source_grounding_query(case.question),
2172
+ }
2173
+
2174
+
2175
+ def _non_temporal_process_how_marker(question: str) -> bool:
2176
+ if not re.search(r"\bhow\b", question, flags=re.IGNORECASE):
2177
+ return False
2178
+ if re.search(r"\bhow\s+(?:long|many|much|old)\b", question, flags=re.IGNORECASE):
2179
+ return False
2180
+ if re.search(
2181
+ r"\bhow\s+(?:can|could|do|does|did)\s+(?:i|we|you)\s+"
2182
+ r"(?:contact|reach)\b",
2183
+ question,
2184
+ flags=re.IGNORECASE,
2185
+ ):
2186
+ return False
2187
+ return not re.search(
2188
+ r"\b(?:compare|between|different|difference|previous|former)\b",
2189
+ question,
2190
+ flags=re.IGNORECASE,
2191
+ )
2192
+
2193
+
2194
+ def _relation_variant_terms(relation: str) -> tuple[str, ...]:
2195
+ variants = _RELATION_QUERY_VARIANTS.get(relation, ())
2196
+ terms: list[str] = []
2197
+ for phrase in variants:
2198
+ terms.extend(_normalized_terms(phrase))
2199
+ return tuple(
2200
+ term
2201
+ for term in terms
2202
+ if term != relation
2203
+ and term not in _QUERY_TOKEN_ALIASES
2204
+ and (
2205
+ relation not in _QUERY_TOKEN_ALIASES.get(term, ())
2206
+ or {relation, term} <= {"say", "said"}
2207
+ )
2208
+ )
2209
+
2210
+
2211
+ def _filter_relation_terms_for_profile(
2212
+ *,
2213
+ question: str,
2214
+ relation_terms: Sequence[str],
2215
+ ) -> tuple[str, ...]:
2216
+ normalized_question = re.sub(r"[^0-9a-z]+", " ", question.casefold()).strip()
2217
+ relation_set = set(relation_terms)
2218
+ has_diet_profile_question = _has_diet_profile_question(normalized_question)
2219
+ filtered: list[str] = []
2220
+ for term in relation_terms:
2221
+ if term == "work" and _has_employment_profile_question(normalized_question):
2222
+ continue
2223
+ if term == "health" and not _has_health_profile_question(
2224
+ normalized_question,
2225
+ ):
2226
+ continue
2227
+ if term == "contact" and not _has_contact_profile_question(
2228
+ normalized_question,
2229
+ ):
2230
+ continue
2231
+ if term in {
2232
+ "cancel",
2233
+ "deadline",
2234
+ "promise",
2235
+ "remember",
2236
+ "reschedule",
2237
+ "task",
2238
+ } and not (
2239
+ _has_commitment_profile_question(normalized_question)
2240
+ ):
2241
+ continue
2242
+ if term == "diet" and not has_diet_profile_question:
2243
+ continue
2244
+ if term == "avoid" and has_diet_profile_question:
2245
+ continue
2246
+ if term in {"avoid", "dislike", "hate"} and _has_diet_profile_question(
2247
+ normalized_question
2248
+ ):
2249
+ continue
2250
+ if term in {"exercise", "hobby", "sport"} and not _has_activity_profile_question(
2251
+ normalized_question,
2252
+ ):
2253
+ continue
2254
+ if term == "age" and not _has_age_profile_question(normalized_question):
2255
+ continue
2256
+ if term == "pet" and not _has_pet_profile_question(normalized_question):
2257
+ continue
2258
+ if term == "skill" and not _has_skill_profile_question(normalized_question):
2259
+ continue
2260
+ if term == "vehicle" and not _has_vehicle_profile_question(
2261
+ normalized_question,
2262
+ ):
2263
+ continue
2264
+ if term in {"class", "education"} and {"enroll", "register", "sign"} & relation_set:
2265
+ continue
2266
+ if term == "education" and not _has_education_profile_question(
2267
+ normalized_question,
2268
+ ):
2269
+ continue
2270
+ if term == "class" and not re.search(
2271
+ r"\bwhat\s+class\b|\bclass\b.+\b(?:take|taking|study|studying)\b",
2272
+ normalized_question,
2273
+ ):
2274
+ continue
2275
+ if term == "stay" and not re.search(
2276
+ r"\bwhere\b.+\bstay(?:ing)?\b|\bstay(?:ed|ing)?\b.+\b(?:in|at|near)\b",
2277
+ normalized_question,
2278
+ ):
2279
+ continue
2280
+ if term == "raise" and re.search(
2281
+ r"\bwhere\b.+\braised\b|\braised\b.+\bwhere\b",
2282
+ normalized_question,
2283
+ ):
2284
+ continue
2285
+ filtered.append(term)
2286
+ return tuple(filtered)
2287
+
2288
+
2289
+ def _has_education_profile_question(normalized_question: str) -> bool:
2290
+ return bool(
2291
+ re.search(
2292
+ r"\b(?:what|which)\s+school\b|"
2293
+ r"\b(?:college|university)\b|"
2294
+ r"\b(?:study|studies|studying|majoring)\b|"
2295
+ r"\bwhat\s+(?:is|was)\b.+\bmajor\b(?:\s+(?:in|at)\b|$)|"
2296
+ r"\bwhat\s+(?:is|was)\b.+\bdegree\b(?:\s+(?:in|from)\b|$)|"
2297
+ r"\bwhat\s+degree\s+(?:does|did|is|was|has|have)\b|"
2298
+ r"\bdegree\s+(?:does|did)\b.+\bhave\b|"
2299
+ r"\b(?:major|degree)\s+in\b|"
2300
+ r"\b(?:where|when|what\s+school)\b.+\bgraduat(?:e|ed|ion)\b|"
2301
+ r"\bgraduat(?:e|ed|ion)\b.+\b(?:from|school|college|university)\b|"
2302
+ r"\bwhat\s+class\b",
2303
+ normalized_question,
2304
+ )
2305
+ )
2306
+
2307
+
2308
+ def _has_activity_profile_question(normalized_question: str) -> bool:
2309
+ return bool(
2310
+ re.search(
2311
+ r"\b(?:what|which)\s+(?:activity|activities|hobby|hobbies|sport|sports)\b|"
2312
+ r"\b(?:hobby|hobbies|pastime|free\s+time|for\s+fun)\b|"
2313
+ r"\bwhat\b.+\b(?:do|does)\b.+\b(?:for\s+fun|free\s+time|relax)\b|"
2314
+ r"\b(?:exercise|workout)\b",
2315
+ normalized_question,
2316
+ )
2317
+ )
2318
+
2319
+
2320
+ def _has_employment_profile_question(normalized_question: str) -> bool:
2321
+ return bool(
2322
+ re.search(
2323
+ r"\b(?:what|which)\s+(?:company|job|occupation|profession|workplace)\b|"
2324
+ r"\bwhat\s+(?:is|was)\b.+\b(?:salary|wage|pay\s+rate|hourly\s+rate)\b|"
2325
+ r"\b(?:job|occupation|profession|workplace)\b|"
2326
+ r"\b(?:where|which\s+(?:city|country|place))\b.+\bwork(?:ed|ing)?\b|"
2327
+ r"\bwhat\b.+\bdo\b.+\bfor\s+work\b|"
2328
+ r"\bwork\b.+\b(?:company|for)\b",
2329
+ normalized_question,
2330
+ )
2331
+ )
2332
+
2333
+
2334
+ def _has_age_profile_question(normalized_question: str) -> bool:
2335
+ return bool(
2336
+ re.search(
2337
+ r"\bhow\s+old\b|\bwhat\b.+\bage\b|\bage\b.+\b(?:is|of)\b",
2338
+ normalized_question,
2339
+ )
2340
+ )
2341
+
2342
+
2343
+ def _has_health_profile_question(normalized_question: str) -> bool:
2344
+ return bool(
2345
+ re.search(
2346
+ r"\b(?:doctor|physician|therapist|medication|medicine|prescription|allerg"
2347
+ r"(?:y|ic)|health\s+issue|condition|dentist|dental)\b"
2348
+ r"|\bblood\s+type\b"
2349
+ r"|\bprimary\s+care\s+(?:doctor|physician|provider)\b"
2350
+ r"|\b(?:medical|doctor(?:'s)?|dentist(?:'s)?|therapy|clinic)\s+"
2351
+ r"appointment\b",
2352
+ normalized_question,
2353
+ )
2354
+ )
2355
+
2356
+
2357
+ def _has_contact_profile_question(normalized_question: str) -> bool:
2358
+ if re.search(
2359
+ r"\baddress(?:ed|es|ing)?\s+(?:a|an|the|their|his|her|my|our)?\s*"
2360
+ r"(?:concern|issue|problem|question|risk|topic)\b|"
2361
+ r"\b(?:concern|issue|problem|question|risk|topic)\b.+"
2362
+ r"\baddress(?:ed|es|ing)?\b|"
2363
+ r"\baddress(?:ed|es|ing)?\b.+\bwith\b",
2364
+ normalized_question,
2365
+ ):
2366
+ return False
2367
+ return bool(
2368
+ re.search(
2369
+ r"\b(?:contact\s+(?:info|information|details)|"
2370
+ r"emergency\s+contact|"
2371
+ r"email|e mail|phone|telephone|cell|mobile|address)\b|"
2372
+ r"\b(?:phone|telephone|cell|mobile)\s+number\b|"
2373
+ r"\b(?:instagram|signal|slack|telegram|whatsapp)\s+"
2374
+ r"(?:handle|username|number)\b|"
2375
+ r"\bwhat\s+is\s+(?:[a-z0-9]+(?:\s+s)?|my|his|her|their|our|your)\s+"
2376
+ r"(?:handle|number|username)\b|"
2377
+ r"\bhow\s+(?:can|could|do|does|did)\s+(?:i|we|you)\s+"
2378
+ r"(?:contact|reach)\b",
2379
+ normalized_question,
2380
+ )
2381
+ )
2382
+
2383
+
2384
+ def _has_commitment_profile_question(normalized_question: str) -> bool:
2385
+ if re.search(
2386
+ r"\bremember(?:ed|s|ing)?\s+(?:childhood|story|trip|vacation|birthday)\b|"
2387
+ r"\bpromise\s+ring\b",
2388
+ normalized_question,
2389
+ ):
2390
+ return False
2391
+ return bool(
2392
+ re.search(
2393
+ r"\b(?:deadline|due\s+date|when\b.+\bdue|"
2394
+ r"what\b.+\b(?:task|todo|to do|to-do)|"
2395
+ r"what\b.+\bpromise(?:d)?|"
2396
+ r"(?:task|todo|to do|to-do|plan|promise|deadline)\b.+"
2397
+ r"\b(?:cancel(?:ed|led|s)?|reschedul(?:e|ed|es|ing)?)\b|"
2398
+ r"(?:cancel(?:ed|led|s)?|reschedul(?:e|ed|es|ing)?)\b.+"
2399
+ r"\b(?:task|todo|to do|to-do|plan|promise|deadline)\b|"
2400
+ r"(?:need|needs|needed)\s+to\s+remember|"
2401
+ r"remember\s+to)\b",
2402
+ normalized_question,
2403
+ )
2404
+ )
2405
+
2406
+
2407
+ def _has_diet_profile_question(normalized_question: str) -> bool:
2408
+ return bool(
2409
+ re.search(
2410
+ r"\b(?:dietary\s+(?:restriction|restrictions)|"
2411
+ r"vegetarian|vegan|gluten\s?free|dairy\s?free)\b|"
2412
+ r"\b(?:avoid|avoids|can t|cannot|can\s+not|doesn t|does\s+not|"
2413
+ r"don t|do\s+not)\s+eat\b|"
2414
+ r"\bwhat\s+can\b.+\bnot\s+eat\b|"
2415
+ r"\bwhat\s+food\b.+\b(?:avoid|eat)\b",
2416
+ normalized_question,
2417
+ )
2418
+ )
2419
+
2420
+
2421
+ def _has_pet_profile_question(normalized_question: str) -> bool:
2422
+ return bool(
2423
+ re.search(
2424
+ r"\bwhat\s+pet\b|\b(?:dog|cat|pet)\b.+\bnamed?\b|"
2425
+ r"\bname\b.+\b(?:dog|cat|pet)\b|"
2426
+ r"\bbreed\b.+\b(?:dog|cat|pet)\b|\b(?:dog|cat|pet)\b.+\bbreed\b|"
2427
+ r"\b(?:dog|cat|pet|puppy|kitten)\b.+\bmicrochip\b|"
2428
+ r"\bmicrochip\b.+\b(?:dog|cat|pet|puppy|kitten)\b",
2429
+ normalized_question,
2430
+ )
2431
+ )
2432
+
2433
+
2434
+ def _has_skill_profile_question(normalized_question: str) -> bool:
2435
+ return bool(
2436
+ re.search(
2437
+ r"\blanguages?\b.+\b(?:speak|know|fluent|bilingual)\b|"
2438
+ r"\b(?:speak|know)\b.+\blanguages?\b|"
2439
+ r"\b(?:fluent|bilingual)\b.+\blanguages?\b|"
2440
+ r"\blanguages?\b.+\blearn(?:ed|ing)?\b|"
2441
+ r"\blearn(?:ed|ing)?\b.+\blanguages?\b|"
2442
+ r"\bprogramming\s+languages?\b|\blanguages?\b.+\bprogramming\b|"
2443
+ r"\bskill\b.+\blearn(?:ed|ing)?\b|"
2444
+ r"\blearn(?:ed|ing)?\b.+\bskill\b|"
2445
+ r"\b(?:certification|credential)\b|"
2446
+ r"\bcertified\s+in\b|"
2447
+ r"\binstrument\b.+\bplay\b|\bplay\b.+\binstrument\b|"
2448
+ r"\bplay\s+(?:guitar|piano|violin|drums?)\b",
2449
+ normalized_question,
2450
+ )
2451
+ )
2452
+
2453
+
2454
+ def _has_vehicle_profile_question(normalized_question: str) -> bool:
2455
+ return bool(
2456
+ re.search(
2457
+ r"\blicen[cs]e\s+plate\b|"
2458
+ r"\b(?:what|which|kind\s+of|color)\b.+"
2459
+ r"\b(?:car|vehicle|truck|suv|sedan|van)\b|"
2460
+ r"\b(?:car|vehicle|truck|suv|sedan|van)\b.+"
2461
+ r"\b(?:drive|have|has|own|color)\b|"
2462
+ r"\bdrive\s+(?:a|an|the|my|his|her|their)\s+"
2463
+ r"(?:car|vehicle|truck|suv|sedan|van)\b",
2464
+ normalized_question,
2465
+ )
2466
+ )
2467
+
2468
+
2469
+ def _filter_relation_variant_terms_for_profile(
2470
+ *,
2471
+ question: str,
2472
+ relation_terms: Sequence[str],
2473
+ relation_variant_terms: Sequence[str],
2474
+ ) -> tuple[str, ...]:
2475
+ relation_term_set = set(relation_terms)
2476
+ blocked_terms: set[str] = set()
2477
+ normalized_question = " ".join(str(question or "").casefold().split())
2478
+ if _has_future_home_move_goal_intent(normalized_question, relation_terms):
2479
+ blocked_terms.update(
2480
+ {
2481
+ "came",
2482
+ "country",
2483
+ "home",
2484
+ "moved",
2485
+ "origin",
2486
+ "relocated",
2487
+ }
2488
+ )
2489
+ if {"choose", "adoption", "agency"}.issubset(relation_term_set):
2490
+ blocked_terms.update(
2491
+ {
2492
+ "folk",
2493
+ "children",
2494
+ "family",
2495
+ "help",
2496
+ "inclusive",
2497
+ "inclusivity",
2498
+ "individual",
2499
+ "kid",
2500
+ "lgbtq",
2501
+ "support",
2502
+ }
2503
+ )
2504
+ if {"excite", "adoption", "process"}.issubset(relation_term_set):
2505
+ blocked_terms.update(
2506
+ {
2507
+ "children",
2508
+ "family",
2509
+ "inclusive",
2510
+ "inclusivity",
2511
+ "kid",
2512
+ "lgbtq",
2513
+ "mom",
2514
+ }
2515
+ )
2516
+ if {"think", "decision", "adopt"}.issubset(relation_term_set):
2517
+ blocked_terms.update(
2518
+ {
2519
+ "agencies",
2520
+ "agency",
2521
+ "creating",
2522
+ "creat",
2523
+ "children",
2524
+ "family",
2525
+ "kid",
2526
+ "kids",
2527
+ "lovely",
2528
+ "luck",
2529
+ "mom",
2530
+ "process",
2531
+ "support",
2532
+ }
2533
+ )
2534
+ if {"individual", "adoption", "support"}.issubset(
2535
+ relation_term_set
2536
+ ) and not re.search(
2537
+ r"\b(?:inclusive|inclusivity|lgbtq|queer|transgender)\b",
2538
+ normalized_question,
2539
+ ):
2540
+ blocked_terms.update(
2541
+ {
2542
+ "children",
2543
+ "family",
2544
+ "inclusive",
2545
+ "inclusivity",
2546
+ "kid",
2547
+ "kids",
2548
+ "lgbtq",
2549
+ "process",
2550
+ }
2551
+ )
2552
+ if {"plan", "summer"}.issubset(relation_term_set) and not re.search(
2553
+ r"\b(?:adopt|adoption|child|children|family|home|kid|kids)\b",
2554
+ normalized_question,
2555
+ ):
2556
+ blocked_terms.update(
2557
+ {
2558
+ "children",
2559
+ "dream",
2560
+ "family",
2561
+ "home",
2562
+ "kid",
2563
+ "kids",
2564
+ "loving",
2565
+ "lov",
2566
+ }
2567
+ )
2568
+ if {"go", "support", "group"}.issubset(relation_term_set) and not re.search(
2569
+ r"\b(?:inclusive|inclusivity|lgbtq|queer|transgender)\b",
2570
+ normalized_question,
2571
+ ):
2572
+ blocked_terms.update({"inclusive", "inclusivity", "lgbtq"})
2573
+ if {"personality", "trait"} & relation_term_set:
2574
+ blocked_terms.update({"mention", "mentioned", "said", "say", "tell", "told"})
2575
+ if "prompt" in relation_term_set and not re.search(
2576
+ r"\bprompt(?:ed|ing)?\b.+\b(?:to|into)\b"
2577
+ r"|\bthat\s+prompt(?:ed|ing)?\b",
2578
+ normalized_question,
2579
+ ):
2580
+ blocked_terms.update({"because", "cause", "prompted", "reason", "reflect"})
2581
+ if not blocked_terms:
2582
+ return tuple(relation_variant_terms)
2583
+ return tuple(term for term in relation_variant_terms if term not in blocked_terms)
2584
+
2585
+
2586
+ def _has_future_home_move_goal_intent(
2587
+ normalized_question: str,
2588
+ relation_terms: Sequence[str],
2589
+ ) -> bool:
2590
+ if not {"want", "move"} <= set(relation_terms):
2591
+ return False
2592
+ if re.search(
2593
+ r"\b(?:where|which\s+(?:city|country|place)|from|origin)\b",
2594
+ normalized_question,
2595
+ ):
2596
+ return False
2597
+ return bool(
2598
+ re.search(
2599
+ r"\b(?:would|want|wants|wanted|hope|hoping|plan|plans)\b",
2600
+ normalized_question,
2601
+ )
2602
+ and re.search(r"\bmove\s+back\b", normalized_question)
2603
+ and re.search(r"\bhome\s+country\b", normalized_question)
2604
+ )
2605
+
2606
+
2607
+ def _temporal_query_profile(case: PublicBenchmarkCase) -> dict[str, object]:
2608
+ query = " ".join(str(case.question or "").casefold().split())
2609
+ category = _optional_int(case.metadata.get("category"))
2610
+ temporal_query = re.sub(r"\b(?:free\s+time|pastime)\b", " ", query)
2611
+ matched_terms = tuple(
2612
+ term
2613
+ for term in _TEMPORAL_QUERY_TERMS
2614
+ if _contains_temporal_query_term(temporal_query, term)
2615
+ )
2616
+ period_modifier_terms = _period_modifier_temporal_terms(query)
2617
+ if period_modifier_terms:
2618
+ matched_terms = tuple(dict.fromkeys((*matched_terms, *period_modifier_terms)))
2619
+ ordinal_period_terms = _ordinal_period_temporal_terms(query)
2620
+ if ordinal_period_terms:
2621
+ matched_terms = tuple(dict.fromkeys((*matched_terms, *ordinal_period_terms)))
2622
+ season_terms = _season_temporal_terms(query)
2623
+ if season_terms:
2624
+ matched_terms = tuple(dict.fromkeys((*matched_terms, *season_terms)))
2625
+ ordinal_event_terms = _ordinal_event_temporal_terms(query)
2626
+ if ordinal_event_terms:
2627
+ matched_terms = tuple(dict.fromkeys((*matched_terms, *ordinal_event_terms)))
2628
+ repeated_event_terms = _repeated_event_temporal_terms(query)
2629
+ if repeated_event_terms:
2630
+ matched_terms = tuple(dict.fromkeys((*matched_terms, *repeated_event_terms)))
2631
+ duration_amount_terms = _duration_amount_temporal_terms(query)
2632
+ if duration_amount_terms:
2633
+ matched_terms = tuple(dict.fromkeys((*matched_terms, *duration_amount_terms)))
2634
+ since_when_duration_terms = _since_when_duration_temporal_terms(query)
2635
+ if since_when_duration_terms:
2636
+ matched_terms = tuple(
2637
+ dict.fromkeys((*matched_terms, *since_when_duration_terms))
2638
+ )
2639
+ relative_offset_terms = _relative_offset_temporal_terms(query)
2640
+ if relative_offset_terms:
2641
+ matched_terms = tuple(dict.fromkeys((*matched_terms, *relative_offset_terms)))
2642
+ relative_weekday_terms = _relative_weekday_temporal_terms(query)
2643
+ if relative_weekday_terms:
2644
+ matched_terms = tuple(dict.fromkeys((*matched_terms, *relative_weekday_terms)))
2645
+ explicit_date_anchor_terms = _explicit_date_anchor_temporal_terms(query)
2646
+ if explicit_date_anchor_terms:
2647
+ matched_terms = tuple(
2648
+ dict.fromkeys((*matched_terms, *explicit_date_anchor_terms))
2649
+ )
2650
+ current_state_terms = _current_state_temporal_terms(query)
2651
+ if current_state_terms:
2652
+ matched_terms = tuple(dict.fromkeys((*matched_terms, *current_state_terms)))
2653
+ ordered_event_term = _ordered_event_temporal_term(query)
2654
+ if ordered_event_term:
2655
+ matched_terms = tuple(dict.fromkeys((*matched_terms, ordered_event_term)))
2656
+ if "during" in matched_terms and not re.search(
2657
+ r"\b(?:session|conversation|chat|call|meeting|event|interview)\b",
2658
+ temporal_query,
2659
+ ):
2660
+ matched_terms = tuple(term for term in matched_terms if term != "during")
2661
+ matched_terms = _without_overlapped_relative_temporal_terms(matched_terms)
2662
+ surface_terms = tuple(term for term in _TEMPORAL_SURFACE_TERMS if term in query)
2663
+ is_temporal = category == 2 or bool(matched_terms) or bool(surface_terms)
2664
+ reasons: list[str] = []
2665
+ if category == 2:
2666
+ reasons.append("locomo_temporal_category")
2667
+ reasons.extend(f"query_term:{term}" for term in matched_terms)
2668
+ reasons.extend(f"surface_term:{term}" for term in surface_terms)
2669
+ return {
2670
+ "is_temporal_query": is_temporal,
2671
+ "reasons": reasons,
2672
+ "matched_terms": list(matched_terms),
2673
+ "surface_terms": list(surface_terms),
2674
+ }
2675
+
2676
+
2677
+ def _contains_temporal_query_term(query: str, term: str) -> bool:
2678
+ if term == "date":
2679
+ return bool(re.search(r"\b(?:date|birthdate)\b", query))
2680
+ if term == "time":
2681
+ return bool(re.search(r"\btimes?\b", query))
2682
+ if term not in {
2683
+ "after",
2684
+ "afterward",
2685
+ "afterwards",
2686
+ "before",
2687
+ "during",
2688
+ "since",
2689
+ }:
2690
+ return term in query
2691
+ escaped = re.escape(term)
2692
+ return bool(re.search(rf"(?<![a-z0-9]){escaped}(?![a-z0-9])", query))
2693
+
2694
+
2695
+ def _ordered_event_temporal_term(query: str) -> str:
2696
+ match = _ORDERED_EVENT_REQUEST_RE.search(query)
2697
+ if match is None:
2698
+ return ""
2699
+ order = match.group("order").casefold()
2700
+ if order in {"next", "upcoming"}:
2701
+ return "upcoming event"
2702
+ if order in {"first", "earliest", "oldest"}:
2703
+ return "earliest event"
2704
+ return "latest event"
2705
+
2706
+
2707
+ def _period_modifier_temporal_terms(query: str) -> tuple[str, ...]:
2708
+ terms: list[str] = []
2709
+ for match in re.finditer(r"\b(early|late)\s+([a-z]+|\d{4})\b", query):
2710
+ anchor = match.group(2)
2711
+ if _PERIOD_ANCHOR_TERMS_RE.fullmatch(anchor):
2712
+ terms.append(match.group(1))
2713
+ if anchor in _SEASON_TERMS:
2714
+ terms.append(anchor)
2715
+ for match in re.finditer(r"\b(first|second)\s+half\s+of\s+([a-z]+|\d{4})\b", query):
2716
+ anchor = match.group(2)
2717
+ if _PERIOD_ANCHOR_TERMS_RE.fullmatch(anchor):
2718
+ terms.append(f"{match.group(1)} half")
2719
+ if anchor in _SEASON_TERMS:
2720
+ terms.append(anchor)
2721
+ for match in re.finditer(
2722
+ r"\b(?:towards?|near|around)?\s*(?:the\s+)?"
2723
+ r"(start|beginning|end)\s+of\s+(?:the\s+)?([a-z]+|\d{4})\b",
2724
+ query,
2725
+ ):
2726
+ anchor = match.group(2)
2727
+ if _PERIOD_ANCHOR_TERMS_RE.fullmatch(anchor):
2728
+ boundary = "start" if match.group(1) == "beginning" else match.group(1)
2729
+ terms.append(boundary)
2730
+ if anchor in _SEASON_TERMS:
2731
+ terms.append(anchor)
2732
+ return tuple(dict.fromkeys(terms))
2733
+
2734
+
2735
+ def _ordinal_period_temporal_terms(query: str) -> tuple[str, ...]:
2736
+ terms: list[str] = []
2737
+ for match in re.finditer(
2738
+ r"\b(first|second|third|fourth|last)\s+"
2739
+ r"(weekend|week|half|quarter|month)\s+of\s+(?:the\s+)?([a-z]+|\d{4})\b",
2740
+ query,
2741
+ ):
2742
+ anchor = match.group(3)
2743
+ if _PERIOD_ANCHOR_TERMS_RE.fullmatch(anchor):
2744
+ terms.append(f"{match.group(1)} {match.group(2)}")
2745
+ if anchor in _SEASON_TERMS:
2746
+ terms.append(anchor)
2747
+ return tuple(dict.fromkeys(terms))
2748
+
2749
+
2750
+ def _season_temporal_terms(query: str) -> tuple[str, ...]:
2751
+ terms: list[str] = []
2752
+ season = r"spring|summer|fall|autumn|winter"
2753
+ for match in re.finditer(rf"\b(last|next|this)\s+({season})\b", query):
2754
+ terms.append(f"{match.group(1)} {match.group(2)}")
2755
+ for match in re.finditer(rf"\b({season})\s+((?:19|20)\d{{2}})\b", query):
2756
+ terms.extend((match.group(1), match.group(2)))
2757
+ return tuple(dict.fromkeys(terms))
2758
+
2759
+
2760
+ def _ordinal_event_temporal_terms(query: str) -> tuple[str, ...]:
2761
+ terms: list[str] = []
2762
+ for match in _ORDINAL_EVENT_REQUEST_RE.finditer(query):
2763
+ terms.append(f"{match.group('ordinal')} {match.group('event')}")
2764
+ return tuple(dict.fromkeys(terms))
2765
+
2766
+
2767
+ def _repeated_event_temporal_terms(query: str) -> tuple[str, ...]:
2768
+ if not re.search(r"\bagain\b", query):
2769
+ return ()
2770
+ action = (
2771
+ r"attend|finish|go|join|meet|move|read|reconnect|return|run|start|"
2772
+ r"travel|visit|watch|win|write"
2773
+ )
2774
+ if re.search(rf"\b(?:{action})\b(?:\W+\w+){{0,6}}\W+again\b", query):
2775
+ return ("again",)
2776
+ if re.search(rf"\bagain\b(?:\W+\w+){{0,6}}\W+\b(?:{action})\b", query):
2777
+ return ("again",)
2778
+ return ()
2779
+
2780
+
2781
+ def _duration_amount_temporal_terms(query: str) -> tuple[str, ...]:
2782
+ match = re.search(
2783
+ r"\bhow\s+many\s+"
2784
+ r"(day|days|week|weeks|month|months|year|years|hour|hours)\b",
2785
+ query,
2786
+ )
2787
+ if match is None:
2788
+ return ()
2789
+ return ("duration", match.group(1))
2790
+
2791
+
2792
+ def _since_when_duration_temporal_terms(query: str) -> tuple[str, ...]:
2793
+ if not re.search(r"\bsince\s+when\b", query):
2794
+ return ()
2795
+ return ("duration", "start", "year", "month")
2796
+
2797
+
2798
+ def _relative_offset_temporal_terms(query: str) -> tuple[str, ...]:
2799
+ amount = r"\d+|one|two|three|four|five|six|seven|few|couple"
2800
+ unit = r"day|days|week|weeks|month|months|year|years"
2801
+ return tuple(
2802
+ dict.fromkeys(
2803
+ f"{match.group(1)} {match.group(2)}"
2804
+ for match in re.finditer(
2805
+ rf"\b({amount})\s+({unit})\s+(?:before|after)\b",
2806
+ query,
2807
+ )
2808
+ )
2809
+ )
2810
+
2811
+
2812
+ def _relative_weekday_temporal_terms(query: str) -> tuple[str, ...]:
2813
+ return tuple(
2814
+ dict.fromkeys(match.group(0) for match in _RELATIVE_WEEKDAY_RE.finditer(query))
2815
+ )
2816
+
2817
+
2818
+ def _explicit_date_anchor_temporal_terms(query: str) -> tuple[str, ...]:
2819
+ terms: list[str] = []
2820
+ month_pattern = (
2821
+ r"january|february|march|april|may|june|july|august|september|"
2822
+ r"october|november|december"
2823
+ )
2824
+ for match in re.finditer(
2825
+ rf"\b(?:{month_pattern})\s+(\d{{1,2}}(?:st|nd|rd|th)?)"
2826
+ r"(?:\s*,?\s*(\d{4}))?\b",
2827
+ query,
2828
+ ):
2829
+ terms.extend(term for term in match.groups() if term)
2830
+ for match in re.finditer(
2831
+ rf"\b(\d{{1,2}}(?:st|nd|rd|th)?)\s+(?:of\s+)?(?:{month_pattern})"
2832
+ r"(?:\s*,?\s*(\d{4}))?\b",
2833
+ query,
2834
+ ):
2835
+ terms.extend(term for term in match.groups() if term)
2836
+ for match in re.finditer(rf"\b(?:{month_pattern})\s+((?:19|20)\d{{2}})\b", query):
2837
+ terms.append(match.group(1))
2838
+ return tuple(dict.fromkeys(terms))
2839
+
2840
+
2841
+ def _current_state_temporal_terms(query: str) -> tuple[str, ...]:
2842
+ if not re.search(r"\bcurrently\b", query):
2843
+ return ()
2844
+ if _PERIOD_ANCHOR_TERMS_RE.search(query):
2845
+ return ()
2846
+ return ("currently",)
2847
+
2848
+
2849
+ def _without_overlapped_relative_temporal_terms(
2850
+ matched_terms: tuple[str, ...],
2851
+ ) -> tuple[str, ...]:
2852
+ term_set = set(matched_terms)
2853
+ blocked: set[str] = set()
2854
+ if "last weekend" in term_set:
2855
+ blocked.add("last week")
2856
+ if "next weekend" in term_set:
2857
+ blocked.add("next week")
2858
+ if "this weekend" in term_set:
2859
+ blocked.add("this week")
2860
+ return tuple(term for term in matched_terms if term not in blocked)
2861
+
2862
+
2863
+ def _query_entities(text: str) -> tuple[str, ...]:
2864
+ entities: list[tuple[int, str]] = []
2865
+ protected_spans: list[tuple[int, int]] = []
2866
+ for match in _HONORIFIC_ENTITY_RE.finditer(text):
2867
+ entity = _clean_query_entity(match.group(0))
2868
+ if entity:
2869
+ entities.append((match.start(), entity))
2870
+ protected_spans.append(match.span())
2871
+ for match in re.finditer(r"\b[A-Z][a-zA-Z]+(?:\s+[A-Z][a-zA-Z]+)?\b", text):
2872
+ if _span_overlaps(match.span(), protected_spans):
2873
+ continue
2874
+ entity = _clean_query_entity(match.group(0))
2875
+ if entity:
2876
+ entities.append((match.start(), entity))
2877
+ for match in re.finditer(r"\b[A-Z]{2,}\+?\b", text):
2878
+ if _span_overlaps(match.span(), protected_spans):
2879
+ continue
2880
+ entity = _clean_query_entity(match.group(0))
2881
+ if entity and entity not in (
2882
+ _QUERY_STOPWORDS
2883
+ | _QUERY_ENTITY_STOPWORDS
2884
+ | set(_TEMPORAL_SURFACE_TERMS)
2885
+ | _NON_ENTITY_UPPERCASE_TERMS
2886
+ ):
2887
+ entities.append((match.start(), entity))
2888
+ return tuple(entity for _, entity in sorted(entities, key=lambda item: item[0]))
2889
+
2890
+
2891
+ def _clean_query_entity(raw: str) -> str:
2892
+ terms: list[str] = []
2893
+ for raw_term in raw.split():
2894
+ term = raw_term.casefold().strip(" .'\"")
2895
+ if term.endswith("'s"):
2896
+ term = term[:-2]
2897
+ if term and term not in (
2898
+ _QUERY_STOPWORDS
2899
+ | _QUERY_ENTITY_STOPWORDS
2900
+ | set(_TEMPORAL_SURFACE_TERMS)
2901
+ | _NON_ENTITY_UPPERCASE_TERMS
2902
+ ):
2903
+ terms.append(term)
2904
+ return " ".join(terms)
2905
+
2906
+
2907
+ def _span_overlaps(
2908
+ span: tuple[int, int],
2909
+ protected_spans: Sequence[tuple[int, int]],
2910
+ ) -> bool:
2911
+ return any(
2912
+ span[0] < protected[1] and protected[0] < span[1]
2913
+ for protected in protected_spans
2914
+ )
2915
+
2916
+
2917
+ def _with_benchmark_rerank_boost(
2918
+ memory: RetrievedMemory,
2919
+ profile: Mapping[str, object],
2920
+ *,
2921
+ question: str,
2922
+ ) -> tuple[RetrievedMemory, float]:
2923
+ boost, signals = _benchmark_rerank_boost(memory, profile, question=question)
2924
+ if boost <= 0:
2925
+ return memory, 0.0
2926
+
2927
+ diagnostics = (
2928
+ dict(memory.metadata.get("diagnostics"))
2929
+ if isinstance(memory.metadata.get("diagnostics"), Mapping)
2930
+ else {}
2931
+ )
2932
+ score_signals = (
2933
+ dict(diagnostics.get("score_signals"))
2934
+ if isinstance(diagnostics.get("score_signals"), Mapping)
2935
+ else {}
2936
+ )
2937
+ score_signals.update(signals["score_signals"])
2938
+ diagnostics["score_signals"] = score_signals
2939
+ diagnostics["benchmark_rerank_boosted"] = True
2940
+ diagnostics["benchmark_query_overlap_terms"] = signals["overlap_terms"]
2941
+ diagnostics["benchmark_query_entities"] = signals["entity_hits"]
2942
+ diagnostics["benchmark_candidate_features"] = signals["candidate_features"]
2943
+ diagnostics["benchmark_rerank_policy"] = signals["policy_contributions"]
2944
+ return replace(
2945
+ memory,
2946
+ score=round(memory.score + boost, 6),
2947
+ metadata={**dict(memory.metadata), "diagnostics": diagnostics},
2948
+ ), boost
2949
+
2950
+
2951
+ def _benchmark_rerank_boost(
2952
+ memory: RetrievedMemory,
2953
+ profile: Mapping[str, object],
2954
+ *,
2955
+ question: str = "",
2956
+ ) -> tuple[float, dict[str, object]]:
2957
+ memory_terms = set(_normalized_terms(memory.text))
2958
+ query_terms = tuple(_string_sequence(profile.get("lexical_terms")))
2959
+ relation_terms = tuple(_string_sequence(profile.get("relation_terms")))
2960
+ relation_variant_terms = tuple(_string_sequence(profile.get("relation_variant_terms")))
2961
+ relation_category_terms = _relation_category_terms(profile)
2962
+ entities = tuple(_string_sequence(profile.get("entities")))
2963
+ entity_surfaces = tuple(_string_sequence(profile.get("entity_surfaces"))) or entities
2964
+ speaker_surfaces = tuple(_string_sequence(profile.get("speaker_surfaces")))
2965
+ primary_speaker_surfaces = speaker_surfaces[:1] or speaker_surfaces
2966
+ speaker_match_surfaces = (
2967
+ speaker_surfaces
2968
+ if profile.get("comparative_option_preference_query") is True
2969
+ else primary_speaker_surfaces
2970
+ )
2971
+ entity_hits = tuple(
2972
+ entity
2973
+ for entity in entity_surfaces
2974
+ if _entity_surface_in_memory(entity, memory.text)
2975
+ )
2976
+ speaker_hits = tuple(
2977
+ entity
2978
+ for entity in _speaker_match_surfaces(speaker_match_surfaces)
2979
+ if _entity_speaks_in_memory(entity, memory.text)
2980
+ )
2981
+ candidate_features = build_candidate_evidence_features(
2982
+ memory,
2983
+ memory_terms=memory_terms,
2984
+ query_terms=query_terms,
2985
+ relation_terms=relation_terms,
2986
+ relation_variant_terms=relation_variant_terms,
2987
+ relation_category_terms=relation_category_terms,
2988
+ entities=entities,
2989
+ entity_hits=entity_hits,
2990
+ speaker_hits=speaker_hits,
2991
+ high_signal_relation_terms=_HIGH_SIGNAL_RELATION_VARIANTS,
2992
+ is_temporal_query=bool(profile.get("is_temporal_query")),
2993
+ time_intent_kind=str(profile.get("time_intent_kind") or ""),
2994
+ is_preference_query=_is_preference_query(profile),
2995
+ is_contrast_query=_is_contrast_query(profile),
2996
+ has_visual_terms=bool(profile.get("visual_terms")),
2997
+ has_multi_hop_markers=bool(profile.get("multi_hop_markers")),
2998
+ has_temporal_surface=_memory_has_temporal_surface(memory),
2999
+ has_sequence_surface=_memory_has_sequence_surface(memory),
3000
+ has_preference_evidence=_memory_has_preference_evidence(memory),
3001
+ has_visual_evidence=_memory_has_visual_evidence(memory),
3002
+ has_focused_turn_surface=_memory_has_focused_turn_surface(memory),
3003
+ question=question or str(profile.get("question") or ""),
3004
+ )
3005
+ intent_policy_boosts = focused_intent_policy_boosts(
3006
+ memory_terms=set(candidate_features.memory_terms),
3007
+ relation_terms=relation_terms,
3008
+ relation_hits=candidate_features.relation_hits,
3009
+ focused_turn_boost=candidate_features.focused_turn_score,
3010
+ )
3011
+ focused_shape_boosts = focused_evidence_shape_boosts(
3012
+ memory_terms=set(candidate_features.memory_terms),
3013
+ relation_terms=relation_terms,
3014
+ focused_turn_boost=candidate_features.focused_turn_score,
3015
+ relation_category_hits=candidate_features.relation_category_hits,
3016
+ direct_speaker_turn=candidate_features.direct_speaker_turn,
3017
+ )
3018
+ source_grounding = _memory_source_grounding_evidence(
3019
+ question=question,
3020
+ memory=memory,
3021
+ )
3022
+ score = score_benchmark_rerank_candidate(
3023
+ BenchmarkRerankFeatures(
3024
+ overlap_terms=candidate_features.overlap_terms,
3025
+ entity_hits=candidate_features.entity_hits,
3026
+ speaker_hits=candidate_features.speaker_hits,
3027
+ relation_hits=candidate_features.relation_hits,
3028
+ relation_terms=relation_terms,
3029
+ relation_categories=candidate_features.relation_categories,
3030
+ relation_category_hits=candidate_features.relation_category_hits,
3031
+ relation_category_coverage_ratio=(
3032
+ candidate_features.relation_category_coverage_ratio
3033
+ ),
3034
+ query_has_entities=candidate_features.query_has_entities,
3035
+ high_signal_relation_hit_count=(
3036
+ candidate_features.high_signal_relation_hit_count
3037
+ ),
3038
+ communication_direction_grounded=(
3039
+ candidate_features.communication_direction_grounded
3040
+ ),
3041
+ communication_direction_ungrounded=(
3042
+ candidate_features.communication_direction_ungrounded
3043
+ ),
3044
+ communication_query_direction=(
3045
+ candidate_features.communication_query_direction
3046
+ ),
3047
+ covered_answer_unit_shapes=candidate_features.covered_answer_unit_shapes,
3048
+ exact_count_evidence=candidate_features.exact_count_evidence,
3049
+ list_item_count=candidate_features.list_item_count,
3050
+ is_temporal_query=candidate_features.is_temporal_query,
3051
+ has_temporal_surface=candidate_features.has_temporal_surface,
3052
+ has_sequence_surface=candidate_features.has_sequence_surface,
3053
+ time_intent_kind=candidate_features.time_intent_kind,
3054
+ has_duration_surface=candidate_features.has_duration_surface,
3055
+ has_relative_time_surface=candidate_features.has_relative_time_surface,
3056
+ has_explicit_time_surface=candidate_features.has_explicit_time_surface,
3057
+ has_explicit_time_content_surface=(
3058
+ candidate_features.has_explicit_time_content_surface
3059
+ ),
3060
+ has_temporal_sequence_surface=(
3061
+ candidate_features.has_temporal_sequence_surface
3062
+ ),
3063
+ temporal_sequence_direction=(
3064
+ candidate_features.temporal_sequence_direction
3065
+ ),
3066
+ is_preference_query=candidate_features.is_preference_query,
3067
+ has_preference_evidence=candidate_features.has_preference_evidence,
3068
+ has_visual_terms=candidate_features.has_visual_terms,
3069
+ has_visual_evidence=candidate_features.has_visual_evidence,
3070
+ focused_turn_boost=candidate_features.focused_turn_score,
3071
+ has_multi_hop_markers=candidate_features.has_multi_hop_markers,
3072
+ policy_boosts=intent_policy_boosts,
3073
+ shape_boosts=focused_shape_boosts,
3074
+ source_type=candidate_features.source_type,
3075
+ source_ref_count=candidate_features.source_ref_count,
3076
+ turn_ref_count=candidate_features.turn_ref_count,
3077
+ source_ref_density=candidate_features.source_ref_density,
3078
+ source_locality_score=candidate_features.source_locality_score,
3079
+ direct_speaker_turn=candidate_features.direct_speaker_turn,
3080
+ broad_summary=candidate_features.broad_summary,
3081
+ conflict_or_stale=candidate_features.conflict_or_stale,
3082
+ negation_surface=candidate_features.negation_surface,
3083
+ currentness_surface=candidate_features.currentness_surface,
3084
+ stale_surface=candidate_features.stale_surface,
3085
+ contrast_surface=candidate_features.contrast_surface,
3086
+ answerability_score=candidate_features.answerability_score,
3087
+ answerability_reason_codes=candidate_features.answerability_reason_codes,
3088
+ evidence_need=tuple(_string_sequence(profile.get("evidence_need"))),
3089
+ query_roles=candidate_features.query_roles,
3090
+ temporal_query_terms=tuple(
3091
+ _string_sequence(profile.get("temporal_terms"))
3092
+ ),
3093
+ current_state_query=bool(profile.get("current_state_query")),
3094
+ source_grounding_query=bool(profile.get("source_grounding_query")),
3095
+ source_grounding_support=source_grounding.grounded,
3096
+ source_grounding_support_reason=source_grounding.reason,
3097
+ source_grounding_quote_relevant=source_grounding.quote_relevant,
3098
+ )
3099
+ )
3100
+ return score.boost, {
3101
+ **score.signals,
3102
+ "candidate_features": candidate_features.to_diagnostics(),
3103
+ }
3104
+
3105
+
3106
+ def _memory_source_grounding_evidence(
3107
+ *,
3108
+ question: str,
3109
+ memory: RetrievedMemory,
3110
+ ):
3111
+ return _source_grounding_evidence(
3112
+ query=question,
3113
+ text=memory.text,
3114
+ source_refs=_memory_source_refs_for_grounding(memory),
3115
+ )
3116
+
3117
+
3118
+ def _memory_source_refs_for_grounding(memory: RetrievedMemory) -> tuple[SourceRef, ...]:
3119
+ refs: list[SourceRef] = []
3120
+ for index, raw_ref in enumerate(memory.source_refs):
3121
+ ref_text = str(raw_ref or "").strip()
3122
+ if not ref_text:
3123
+ continue
3124
+ refs.append(
3125
+ SourceRef(
3126
+ source_type="benchmark",
3127
+ source_id=ref_text,
3128
+ chunk_id=str(index),
3129
+ )
3130
+ )
3131
+ for raw_ref in _metadata_source_ref_payloads(memory.metadata):
3132
+ for identity_ref in _source_identity_refs_from_source_refs((raw_ref,)):
3133
+ refs.append(
3134
+ SourceRef(
3135
+ source_type="benchmark",
3136
+ source_id=identity_ref,
3137
+ )
3138
+ )
3139
+ source_id = _mapping_text(raw_ref, "source_id", "source_external_id", "id")
3140
+ if not source_id:
3141
+ continue
3142
+ refs.append(
3143
+ SourceRef(
3144
+ source_type=_mapping_text(raw_ref, "source_type") or "benchmark",
3145
+ source_id=source_id,
3146
+ chunk_id=_mapping_text(raw_ref, "chunk_id"),
3147
+ quote_preview=_mapping_text(raw_ref, "quote_preview"),
3148
+ )
3149
+ )
3150
+ return tuple(refs)
3151
+
3152
+
3153
+ def _metadata_source_ref_payloads(
3154
+ metadata: Mapping[str, object],
3155
+ ) -> tuple[Mapping[str, object], ...]:
3156
+ refs = metadata.get("source_refs") or metadata.get("source_ref_payloads")
3157
+ if not isinstance(refs, Sequence) or isinstance(refs, str | bytes):
3158
+ nested = metadata.get("metadata")
3159
+ if isinstance(nested, Mapping):
3160
+ return _metadata_source_ref_payloads(nested)
3161
+ return ()
3162
+ return tuple(ref for ref in refs if isinstance(ref, Mapping))
3163
+
3164
+
3165
+ def _mapping_text(mapping: Mapping[str, object], *keys: str) -> str:
3166
+ for key in keys:
3167
+ value = mapping.get(key)
3168
+ if isinstance(value, str) and value.strip():
3169
+ return value.strip()
3170
+ return ""
3171
+
3172
+
3173
+ def _relation_category_terms(
3174
+ profile: Mapping[str, object],
3175
+ ) -> dict[str, tuple[str, ...]]:
3176
+ raw_value = profile.get("relation_category_terms")
3177
+ if not isinstance(raw_value, Mapping):
3178
+ return {}
3179
+ return {
3180
+ str(category): tuple(_string_sequence(terms))
3181
+ for category, terms in raw_value.items()
3182
+ if str(category).strip()
3183
+ }
3184
+
3185
+
3186
+ def _has_current_state_query(question: str) -> bool:
3187
+ normalized = " ".join(str(question or "").casefold().split())
3188
+ return bool(
3189
+ normalized
3190
+ and _CURRENT_STATE_QUERY_RE.search(normalized)
3191
+ and not _PREVIOUS_STATE_QUERY_RE.search(normalized)
3192
+ )
3193
+
3194
+
3195
+ def _temporal_search_terms(
3196
+ temporal_terms: Sequence[str],
3197
+ temporal_surface_terms: Sequence[str],
3198
+ ) -> tuple[str, ...]:
3199
+ return tuple(
3200
+ dict.fromkeys(
3201
+ (
3202
+ *temporal_terms,
3203
+ *temporal_surface_terms,
3204
+ "session",
3205
+ "date",
3206
+ "time",
3207
+ )
3208
+ )
3209
+ )