virtual-context 0.4.4__tar.gz → 0.4.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. {virtual_context-0.4.4 → virtual_context-0.4.5}/PKG-INFO +1 -1
  2. {virtual_context-0.4.4 → virtual_context-0.4.5}/pyproject.toml +1 -1
  3. virtual_context-0.4.5/tests/test_retrieval_assembler_post_compaction.py +250 -0
  4. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/__init__.py +1 -1
  5. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/retrieval_assembler.py +15 -4
  6. {virtual_context-0.4.4 → virtual_context-0.4.5}/.gitignore +0 -0
  7. {virtual_context-0.4.4 → virtual_context-0.4.5}/LICENSE +0 -0
  8. {virtual_context-0.4.4 → virtual_context-0.4.5}/README.md +0 -0
  9. {virtual_context-0.4.4 → virtual_context-0.4.5}/assets/dashboard.png +0 -0
  10. {virtual_context-0.4.4 → virtual_context-0.4.5}/assets/hero.png +0 -0
  11. {virtual_context-0.4.4 → virtual_context-0.4.5}/models.yaml +0 -0
  12. {virtual_context-0.4.4 → virtual_context-0.4.5}/scripts/install.ps1 +0 -0
  13. {virtual_context-0.4.4 → virtual_context-0.4.5}/scripts/install.sh +0 -0
  14. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/REGRESSION_MAP.md +0 -0
  15. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/conftest.py +0 -0
  16. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/docker-compose.test.yml +0 -0
  17. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/haiku/__init__.py +0 -0
  18. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/haiku/conftest.py +0 -0
  19. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/haiku/test_compaction.py +0 -0
  20. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/haiku/test_retrieval.py +0 -0
  21. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/haiku/test_tagging.py +0 -0
  22. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/ollama/__init__.py +0 -0
  23. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/ollama/conftest.py +0 -0
  24. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/ollama/test_compactor.py +0 -0
  25. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/ollama/test_pipeline.py +0 -0
  26. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/ollama/test_provider.py +0 -0
  27. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/ollama/test_tag_generator.py +0 -0
  28. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/proxy/__init__.py +0 -0
  29. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/proxy/test_dashboard_cors.py +0 -0
  30. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/proxy/test_metrics.py +0 -0
  31. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_active_compaction_op_invariants.py +0 -0
  32. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_admin_backfill_cli.py +0 -0
  33. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_assembler.py +0 -0
  34. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_backend_integration.py +0 -0
  35. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_beam_judge.py +0 -0
  36. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_budget_enforcement.py +0 -0
  37. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_canonical_row_epoch_guards.py +0 -0
  38. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_canonical_row_epoch_guards_postgres.py +0 -0
  39. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_canonical_turn_grouping.py +0 -0
  40. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_canonical_turns_schema.py +0 -0
  41. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_canonical_turns_schema_postgres.py +0 -0
  42. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_claim_compaction_lease_signature.py +0 -0
  43. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_claim_compaction_lease_signature_postgres.py +0 -0
  44. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_cleanup_abandoned_compaction.py +0 -0
  45. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_cleanup_abandoned_compaction_postgres.py +0 -0
  46. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_cli_init.py +0 -0
  47. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compacting_phase_takeover.py +0 -0
  48. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_commit_prune.py +0 -0
  49. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_heartbeat_sidecar.py +0 -0
  50. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_lease_lost_abort.py +0 -0
  51. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_lifecycle.py +0 -0
  52. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_lifecycle_contract.py +0 -0
  53. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_lifecycle_wiring.py +0 -0
  54. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_operation.py +0 -0
  55. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_operation_crud.py +0 -0
  56. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_operation_crud_postgres.py +0 -0
  57. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_operation_id_uuid.py +0 -0
  58. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_operation_postgres.py +0 -0
  59. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_ownership_guards.py +0 -0
  60. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_progress_event.py +0 -0
  61. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_resume_e2e_postgres.py +0 -0
  62. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_resume_schema_migration.py +0 -0
  63. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compaction_resume_schema_migration_postgres.py +0 -0
  64. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compactor.py +0 -0
  65. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_compactor_concurrent.py +0 -0
  66. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_composite_store.py +0 -0
  67. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_config.py +0 -0
  68. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_context_bleed.py +0 -0
  69. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_conversation_coverage_report.py +0 -0
  70. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_conversation_identity.py +0 -0
  71. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_conversation_lifecycle.py +0 -0
  72. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_conversation_schema.py +0 -0
  73. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_conversation_schema_postgres.py +0 -0
  74. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_conversation_scoping.py +0 -0
  75. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_conversations_tenant_id_backfill_postgres.py +0 -0
  76. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_conversations_tenant_id_propagation.py +0 -0
  77. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_deferred_payload_compaction.py +0 -0
  78. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_delete_resurrect_epoch_races.py +0 -0
  79. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_embedding_tag_generator.py +0 -0
  80. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_empty_turn_skip.py +0 -0
  81. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_engine_alias_resolution.py +0 -0
  82. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_engine_event_bus.py +0 -0
  83. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_engine_integration.py +0 -0
  84. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_engine_lifecycle_epoch.py +0 -0
  85. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_engine_lookback.py +0 -0
  86. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_engine_state.py +0 -0
  87. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_engine_sync_turns.py +0 -0
  88. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_fact_enrichment.py +0 -0
  89. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_fact_graph_integration.py +0 -0
  90. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_fact_link_checker.py +0 -0
  91. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_fact_link_query.py +0 -0
  92. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_fact_link_types.py +0 -0
  93. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_fact_links_sqlite.py +0 -0
  94. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_fact_redesign.py +0 -0
  95. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_filesystem_store_compaction_compat.py +0 -0
  96. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_fill_pass.py +0 -0
  97. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_find_idle_deletable_conversations.py +0 -0
  98. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_find_quote.py +0 -0
  99. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_find_stale_lease_helpers.py +0 -0
  100. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_format_agnostic.py +0 -0
  101. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_handle_prepare_payload.py +0 -0
  102. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_headless.py +0 -0
  103. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_history_filter.py +0 -0
  104. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_idf_retrieval.py +0 -0
  105. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_import_adapters.py +0 -0
  106. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingest_index_integrity.py +0 -0
  107. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingest_reconciler_append_fastpath.py +0 -0
  108. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingest_reconciler_epoch.py +0 -0
  109. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingestion_compaction_full_cycle.py +0 -0
  110. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingestion_db_sweep_catchup.py +0 -0
  111. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingestion_episode.py +0 -0
  112. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingestion_episode_crud.py +0 -0
  113. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingestion_episode_crud_postgres.py +0 -0
  114. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingestion_episode_postgres.py +0 -0
  115. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingestion_finalize_self_heal.py +0 -0
  116. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingestion_progress_event.py +0 -0
  117. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_ingestion_regression_resume.py +0 -0
  118. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_legacy_ingestion_lease_ownership.py +0 -0
  119. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_lifecycle_epoch.py +0 -0
  120. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_lifecycle_epoch_store.py +0 -0
  121. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_lifecycle_epoch_store_postgres.py +0 -0
  122. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_longmemeval_auth.py +0 -0
  123. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_mark_canonical_turns_compacted_all_halves.py +0 -0
  124. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_mcp_server.py +0 -0
  125. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_media.py +0 -0
  126. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_message_filter.py +0 -0
  127. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_metrics_persistence.py +0 -0
  128. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_model_catalog.py +0 -0
  129. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_model_limits.py +0 -0
  130. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_monitor.py +0 -0
  131. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_multi_instance.py +0 -0
  132. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_multi_worker_sliding_window.py +0 -0
  133. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_neo4j_falkordb_compaction_compat.py +0 -0
  134. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_noop_fact_link_store.py +0 -0
  135. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_openrouter_provider.py +0 -0
  136. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_orphan_compacting_repair.py +0 -0
  137. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_paging.py +0 -0
  138. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_passthrough_filter.py +0 -0
  139. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_phase_transition_events.py +0 -0
  140. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_postgres_store.py +0 -0
  141. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_presets.py +0 -0
  142. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_prev_context_leak.py +0 -0
  143. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_progress_event_bus.py +0 -0
  144. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_progress_events.py +0 -0
  145. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_progress_snapshot.py +0 -0
  146. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_progress_snapshot_postgres.py +0 -0
  147. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_provider_adapters.py +0 -0
  148. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_proxy.py +0 -0
  149. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_proxy_dashboard.py +0 -0
  150. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_proxy_formats.py +0 -0
  151. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_proxy_message_filter.py +0 -0
  152. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_proxy_session.py +0 -0
  153. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_proxy_streaming.py +0 -0
  154. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_raw_content.py +0 -0
  155. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_recall_all.py +0 -0
  156. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_refresh_compaction_heartbeat.py +0 -0
  157. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_registry_lifecycle.py +0 -0
  158. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_request_captures_persistence.py +0 -0
  159. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_request_metadata.py +0 -0
  160. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_request_metadata_postgres.py +0 -0
  161. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_retriever.py +0 -0
  162. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_rrf_scoring.py +0 -0
  163. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_segmenter.py +0 -0
  164. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_semantic_search.py +0 -0
  165. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_sender_identity.py +0 -0
  166. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_session_cache.py +0 -0
  167. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_session_date.py +0 -0
  168. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_session_state.py +0 -0
  169. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_sqlite_schema_add_column_race.py +0 -0
  170. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_storage_protocols.py +0 -0
  171. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_store_recovery.py +0 -0
  172. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_store_sqlite.py +0 -0
  173. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_stub_turn_handling.py +0 -0
  174. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_supersession.py +0 -0
  175. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_supersession_migration.py +0 -0
  176. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tag_canonicalizer.py +0 -0
  177. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tag_consolidator.py +0 -0
  178. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tag_generator.py +0 -0
  179. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tag_splitter.py +0 -0
  180. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tag_summary_backfill.py +0 -0
  181. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tagger_loop.py +0 -0
  182. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_telemetry.py +0 -0
  183. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_telemetry_integration.py +0 -0
  184. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_temporal_resolver.py +0 -0
  185. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tool_loop.py +0 -0
  186. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tool_output_interceptor.py +0 -0
  187. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tool_result_filter.py +0 -0
  188. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tool_tags.py +0 -0
  189. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_tui.py +0 -0
  190. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_turn_grouping.py +0 -0
  191. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_turn_tag_index.py +0 -0
  192. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_unified_budget.py +0 -0
  193. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_upstream_trim.py +0 -0
  194. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_vcattach.py +0 -0
  195. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_vcmerge_body_method.py +0 -0
  196. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_vcmerge_body_method_postgres.py +0 -0
  197. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_vcmerge_composite_forwarders.py +0 -0
  198. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_vcmerge_dual_handler_refuse.py +0 -0
  199. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_vcmerge_schema.py +0 -0
  200. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_vcmerge_schema_postgres.py +0 -0
  201. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_vcmerge_storage.py +0 -0
  202. {virtual_context-0.4.4 → virtual_context-0.4.5}/tests/test_verb_expansion.py +0 -0
  203. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual-context.yaml.example +0 -0
  204. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/cli/__init__.py +0 -0
  205. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/cli/import_cmd.py +0 -0
  206. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/cli/main.py +0 -0
  207. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/config.py +0 -0
  208. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/conversation_identity.py +0 -0
  209. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/__init__.py +0 -0
  210. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/alias_resolution.py +0 -0
  211. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/assembler.py +0 -0
  212. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/canonical_turns.py +0 -0
  213. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/compaction_pipeline.py +0 -0
  214. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/compactor.py +0 -0
  215. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/composite_store.py +0 -0
  216. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/conversation_store.py +0 -0
  217. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/coverage_report.py +0 -0
  218. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/embedding_provider.py +0 -0
  219. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/embedding_tag_generator.py +0 -0
  220. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/engine_utils.py +0 -0
  221. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/event_bus.py +0 -0
  222. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/exceptions.py +0 -0
  223. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/fact_query.py +0 -0
  224. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/fts_preprocessor.py +0 -0
  225. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/hint_builder.py +0 -0
  226. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/ingest_reconciler.py +0 -0
  227. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/lifecycle_epoch.py +0 -0
  228. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/llm_utils.py +0 -0
  229. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/math_utils.py +0 -0
  230. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/model_catalog.py +0 -0
  231. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/monitor.py +0 -0
  232. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/paging_manager.py +0 -0
  233. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/progress_events.py +0 -0
  234. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/progress_snapshot.py +0 -0
  235. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/protocols.py +0 -0
  236. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/provider_adapters.py +0 -0
  237. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/quote_search.py +0 -0
  238. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/retrieval_scoring.py +0 -0
  239. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/retriever.py +0 -0
  240. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/search_engine.py +0 -0
  241. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/segmenter.py +0 -0
  242. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/semantic_search.py +0 -0
  243. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/store.py +0 -0
  244. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/tag_canonicalizer.py +0 -0
  245. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/tag_consolidator.py +0 -0
  246. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/tag_generator.py +0 -0
  247. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/tag_scoring.py +0 -0
  248. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/tag_splitter.py +0 -0
  249. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/tagging_pipeline.py +0 -0
  250. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/telemetry.py +0 -0
  251. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/temporal_resolver.py +0 -0
  252. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/tool_loop.py +0 -0
  253. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/tool_query.py +0 -0
  254. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/core/turn_tag_index.py +0 -0
  255. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/data/anthropic-tokenizer/tokenizer.json +0 -0
  256. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/data/models.yaml +0 -0
  257. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/engine.py +0 -0
  258. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/import_adapters/__init__.py +0 -0
  259. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/import_adapters/base.py +0 -0
  260. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/import_adapters/chatgpt.py +0 -0
  261. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/import_adapters/claude.py +0 -0
  262. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/import_adapters/grok.py +0 -0
  263. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/import_adapters/loader.py +0 -0
  264. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/ingest/__init__.py +0 -0
  265. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/ingest/curator.py +0 -0
  266. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/ingest/date_resolver.py +0 -0
  267. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/ingest/parsers.py +0 -0
  268. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/ingest/supersession.py +0 -0
  269. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/mcp/__init__.py +0 -0
  270. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/mcp/server.py +0 -0
  271. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/model_limits.py +0 -0
  272. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/openclaw/virtual-context.mjs +0 -0
  273. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/patterns.py +0 -0
  274. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/presets/__init__.py +0 -0
  275. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/presets/agentic.py +0 -0
  276. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/presets/base.py +0 -0
  277. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/presets/coding.py +0 -0
  278. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/providers/__init__.py +0 -0
  279. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/providers/anthropic.py +0 -0
  280. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/providers/base.py +0 -0
  281. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/providers/generic_openai.py +0 -0
  282. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/providers/ollama_native.py +0 -0
  283. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/__init__.py +0 -0
  284. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/_envelope.py +0 -0
  285. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/dashboard.html +0 -0
  286. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/dashboard.py +0 -0
  287. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/formats.py +0 -0
  288. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/handlers.py +0 -0
  289. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/helpers.py +0 -0
  290. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/media.py +0 -0
  291. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/message_filter.py +0 -0
  292. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/metrics.py +0 -0
  293. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/multi.py +0 -0
  294. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/registry.py +0 -0
  295. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/server.py +0 -0
  296. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/session_cache.py +0 -0
  297. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/session_state.py +0 -0
  298. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/state.py +0 -0
  299. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/static/android-chrome-192x192.png +0 -0
  300. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/static/android-chrome-512x512.png +0 -0
  301. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/static/apple-touch-icon.png +0 -0
  302. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/static/favicon-16x16.png +0 -0
  303. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/static/favicon-32x32.png +0 -0
  304. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/static/favicon.ico +0 -0
  305. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/static/site.webmanifest +0 -0
  306. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/tool_output_interceptor.py +0 -0
  307. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/proxy/vcattach.py +0 -0
  308. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/storage/__init__.py +0 -0
  309. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/storage/falkordb.py +0 -0
  310. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/storage/filesystem.py +0 -0
  311. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/storage/helpers.py +0 -0
  312. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/storage/neo4j.py +0 -0
  313. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/storage/noop_fact_link_store.py +0 -0
  314. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/storage/postgres.py +0 -0
  315. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/storage/sqlite.py +0 -0
  316. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/token_counter.py +0 -0
  317. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/__init__.py +0 -0
  318. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/app.py +0 -0
  319. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/chat.tcss +0 -0
  320. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/chat_provider.py +0 -0
  321. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/headless.py +0 -0
  322. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/modals/__init__.py +0 -0
  323. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/modals/turn_inspector.py +0 -0
  324. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/state.py +0 -0
  325. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/widgets/__init__.py +0 -0
  326. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/widgets/budget_bar.py +0 -0
  327. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/widgets/chat_view.py +0 -0
  328. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/widgets/input_box.py +0 -0
  329. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/widgets/tag_panel.py +0 -0
  330. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/tui/widgets/turn_list.py +0 -0
  331. {virtual_context-0.4.4 → virtual_context-0.4.5}/virtual_context/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: virtual-context
3
- Version: 0.4.4
3
+ Version: 0.4.5
4
4
  Summary: OS-style virtual memory for LLM session context management
5
5
  Project-URL: Homepage, https://virtual-context.com
6
6
  Project-URL: Repository, https://github.com/virtual-context/virtual-context
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "virtual-context"
7
- version = "0.4.4"
7
+ version = "0.4.5"
8
8
  description = "OS-style virtual memory for LLM session context management"
9
9
  readme = "README.md"
10
10
  license = "AGPL-3.0-or-later"
@@ -0,0 +1,250 @@
1
+ """Regression test for the retriever's ``post_compaction`` gate.
2
+
3
+ The gate must consult ``_engine_state.compacted_prefix_messages``
4
+ (durable, re-derived from canonical_turns on every hydration) rather
5
+ than ``_engine_state.flushed_prefix_messages`` (session-scoped,
6
+ designed to lag compacted under deferred-payload-mutation
7
+ deployments).
8
+
9
+ Concretely: when a freshly-hydrated engine carries the
10
+ post-compaction values that ``hydrate_from_session_state``'s
11
+ canonical-turns derivation produces (``compacted_prefix_messages > 0``
12
+ but ``flushed_prefix_messages == 0`` because the loaded SessionState
13
+ predates the next ``prepare_payload`` flush gate write), the first
14
+ inbound message of the request MUST still see ``post_compaction =
15
+ True`` so the retriever's ``summary_floor`` prefetch fires. Gating on
16
+ ``flushed_prefix_messages`` made that first request fail closed.
17
+
18
+ These tests also assert the converse — pre-compaction state stays
19
+ gated False — and pin that the gate change does NOT mutate
20
+ ``flushed_prefix_messages`` (preserving the deferred-payload
21
+ invariant ``flushed <= compacted`` and the session-scoped semantics
22
+ of the flushed watermark).
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import os
28
+
29
+ os.environ.setdefault("KMP_DUPLICATE_LIB_OK", "TRUE")
30
+
31
+ from types import SimpleNamespace
32
+ from unittest.mock import MagicMock
33
+
34
+ import pytest
35
+
36
+ from virtual_context.core.retrieval_assembler import RetrievalAssembler
37
+ from virtual_context.types import (
38
+ AssembledContext,
39
+ AssemblerConfig,
40
+ EngineState,
41
+ RetrievalResult,
42
+ RetrieverConfig,
43
+ TagGeneratorConfig,
44
+ VirtualContextConfig,
45
+ )
46
+
47
+
48
+ def _make_assembler(
49
+ *,
50
+ compacted_prefix_messages: int,
51
+ flushed_prefix_messages: int,
52
+ ) -> tuple[RetrievalAssembler, MagicMock]:
53
+ """Build a RetrievalAssembler with stubbed delegates, captured retriever.
54
+
55
+ Returns ``(assembler, retriever_mock)`` so tests can inspect the
56
+ keyword arguments the assembler passes when delegating to
57
+ ``retriever.retrieve``.
58
+ """
59
+ retriever = MagicMock()
60
+ retriever.retrieve.return_value = RetrievalResult(
61
+ tags_matched=[],
62
+ summaries=[],
63
+ total_tokens=0,
64
+ facts=[],
65
+ overflow_summaries=[],
66
+ retrieval_metadata={},
67
+ )
68
+
69
+ assembler_delegate = MagicMock()
70
+ assembler_delegate.assemble.return_value = AssembledContext()
71
+
72
+ monitor = MagicMock()
73
+ monitor.build_snapshot.return_value = SimpleNamespace(
74
+ total_tokens=0,
75
+ budget_tokens=10_000,
76
+ )
77
+
78
+ paging = MagicMock()
79
+ paging.working_set = {}
80
+
81
+ store = MagicMock()
82
+ turn_tag_index = MagicMock()
83
+ turn_tag_index.entries = []
84
+ fact_curator = None
85
+
86
+ engine_state = EngineState()
87
+ engine_state.compacted_prefix_messages = compacted_prefix_messages
88
+ engine_state.flushed_prefix_messages = flushed_prefix_messages
89
+ engine_state.last_completed_turn = max(
90
+ 0, compacted_prefix_messages // 2 - 1,
91
+ )
92
+
93
+ config = VirtualContextConfig(
94
+ context_window=10_000,
95
+ tag_generator=TagGeneratorConfig(type="keyword"),
96
+ retriever=RetrieverConfig(),
97
+ assembler=AssemblerConfig(),
98
+ )
99
+
100
+ assembler = RetrievalAssembler(
101
+ retriever=retriever,
102
+ assembler=assembler_delegate,
103
+ monitor=monitor,
104
+ paging=paging,
105
+ store=store,
106
+ turn_tag_index=turn_tag_index,
107
+ engine_state=engine_state,
108
+ fact_curator=fact_curator,
109
+ config=config,
110
+ token_counter=lambda text: len(text) // 4,
111
+ session_state_provider=None,
112
+ )
113
+ # ``_set_semantic`` is required to wire the optional semantic-search
114
+ # dependency. Pass a mock so ``_get_recent_context`` doesn't blow up
115
+ # on the bleed-threshold path.
116
+ assembler._set_semantic(MagicMock())
117
+ return assembler, retriever
118
+
119
+
120
+ def test_post_compaction_gate_true_when_compacted_positive_and_flushed_zero():
121
+ """The bug shape: SessionState reports zero-flushed (because the
122
+ loaded blob predates the prepare_payload flush gate) but
123
+ canonical_turns derivation has bumped compacted to a positive
124
+ value during ``hydrate_from_session_state``.
125
+
126
+ Before the fix, the retriever's ``post_compaction`` argument was
127
+ computed from ``flushed_prefix_messages > 0`` and stayed False,
128
+ causing the ``summary_floor`` prefetch path to be skipped on the
129
+ first request of a freshly-hydrated engine — exactly the
130
+ user-visible VCATTACH recall failure shape.
131
+
132
+ The fix moves the gate onto ``compacted_prefix_messages > 0``,
133
+ which is the durable signal — re-derived from canonical_turns on
134
+ every hydration, never zero when compaction has actually happened.
135
+ """
136
+ assembler, retriever = _make_assembler(
137
+ compacted_prefix_messages=958,
138
+ flushed_prefix_messages=0,
139
+ )
140
+
141
+ assembler.on_message_inbound(message="what topics?", conversation_history=[])
142
+
143
+ assert retriever.retrieve.call_count >= 1
144
+ call_kwargs = retriever.retrieve.call_args.kwargs
145
+ assert call_kwargs["post_compaction"] is True, (
146
+ "Gate must consult compacted_prefix_messages — the durable "
147
+ "watermark — not flushed_prefix_messages, which can be 0 on a "
148
+ "freshly-hydrated engine before prepare_payload's flush gate "
149
+ "writes."
150
+ )
151
+
152
+
153
+ def test_post_compaction_gate_false_when_compacted_zero():
154
+ """Pre-compaction state (no segments yet) must stay gated False
155
+ regardless of any flushed value. ``compacted_prefix_messages == 0``
156
+ is the binary "compaction has not happened" signal."""
157
+ assembler, retriever = _make_assembler(
158
+ compacted_prefix_messages=0,
159
+ flushed_prefix_messages=0,
160
+ )
161
+
162
+ assembler.on_message_inbound(message="what topics?", conversation_history=[])
163
+
164
+ assert retriever.retrieve.call_count >= 1
165
+ call_kwargs = retriever.retrieve.call_args.kwargs
166
+ assert call_kwargs["post_compaction"] is False, (
167
+ "Pre-compaction state must NOT trigger summary_floor; the gate "
168
+ "requires compacted_prefix_messages > 0."
169
+ )
170
+
171
+
172
+ def test_post_compaction_gate_true_when_both_positive():
173
+ """Normal post-flush steady state: both watermarks positive, gate
174
+ True. Ensures the fix didn't break the happy path."""
175
+ assembler, retriever = _make_assembler(
176
+ compacted_prefix_messages=958,
177
+ flushed_prefix_messages=958,
178
+ )
179
+
180
+ assembler.on_message_inbound(message="what topics?", conversation_history=[])
181
+
182
+ assert retriever.retrieve.call_count >= 1
183
+ call_kwargs = retriever.retrieve.call_args.kwargs
184
+ assert call_kwargs["post_compaction"] is True
185
+
186
+
187
+ def test_active_tags_cleared_under_bug_shape_compacted_positive_flushed_zero():
188
+ """Companion to the primary post_compaction gate test: the
189
+ active-tag clearing at the head of ``on_message_inbound``
190
+ (``retrieval_assembler.py:157-160``) MUST also route through the
191
+ new compacted-driven gate, not the legacy flushed-driven gate.
192
+
193
+ Before the fix the assembler ran ``active_tags =
194
+ self._get_active_tags(...)`` for the bug-shape input (compacted
195
+ positive, flushed zero), which suppressed cross-tag retrieval on
196
+ the first request of a freshly-hydrated post-compaction engine
197
+ — exactly the comment's "don't suppress retrieval -- stored
198
+ summaries are needed since raw turns have been compacted away"
199
+ intent, inverted. The fix routes the same gate through
200
+ ``_post_compaction``, so the assembler now passes ``active_tags
201
+ = []`` to the retriever for the bug shape.
202
+ """
203
+ assembler, retriever = _make_assembler(
204
+ compacted_prefix_messages=958,
205
+ flushed_prefix_messages=0,
206
+ )
207
+
208
+ assembler.on_message_inbound(message="what topics?", conversation_history=[])
209
+
210
+ call_kwargs = retriever.retrieve.call_args.kwargs
211
+ assert call_kwargs["current_active_tags"] == [], (
212
+ "Bug shape (compacted > 0 with flushed == 0): active_tags "
213
+ "must clear to []. Routing this gate through the flushed "
214
+ "watermark suppressed retrieval on the first request of a "
215
+ "freshly-hydrated post-compaction engine — the same failure "
216
+ "shape as the primary summary_floor gate."
217
+ )
218
+
219
+
220
+ def test_retrieval_does_not_mutate_flushed_prefix_messages():
221
+ """Preserve the deferred-payload-mutation invariant that
222
+ ``flushed_prefix_messages`` is session-scoped and lags
223
+ ``compacted_prefix_messages``. The gate fix changes which field
224
+ drives ``post_compaction``; it must NOT have a side effect on
225
+ the flushed watermark.
226
+
227
+ Regression contract:
228
+ * ``flushed_prefix_messages`` value at request entry equals
229
+ value at request exit — retrieval is pure-read for this
230
+ field.
231
+ * The retriever was invoked with ``post_compaction=True``
232
+ despite ``flushed == 0`` (the bug-shape input).
233
+ """
234
+ assembler, retriever = _make_assembler(
235
+ compacted_prefix_messages=958,
236
+ flushed_prefix_messages=0,
237
+ )
238
+ before = assembler._engine_state.flushed_prefix_messages
239
+
240
+ assembler.on_message_inbound(message="what topics?", conversation_history=[])
241
+
242
+ after = assembler._engine_state.flushed_prefix_messages
243
+ assert after == before == 0, (
244
+ "Retrieval must not mutate flushed_prefix_messages; that field "
245
+ "is the proxy's prepare_payload watermark and a session-scoped "
246
+ "deferred-payload signal owned by a different code path."
247
+ )
248
+
249
+ call_kwargs = retriever.retrieve.call_args.kwargs
250
+ assert call_kwargs["post_compaction"] is True
@@ -14,7 +14,7 @@ from .types import (
14
14
  VirtualContextConfig,
15
15
  )
16
16
 
17
- __version__ = "0.4.4"
17
+ __version__ = "0.4.5"
18
18
 
19
19
  __all__ = [
20
20
  "VirtualContextEngine",
@@ -143,10 +143,21 @@ class RetrievalAssembler:
143
143
 
144
144
  # Determine active tags from recent tag results
145
145
  # Post-compaction: don't suppress retrieval -- stored summaries are needed
146
- # since raw turns have been compacted away
146
+ # since raw turns have been compacted away.
147
+ #
148
+ # The post-compaction gate consults ``compacted_prefix_messages``
149
+ # (durable, re-derived from canonical_turns on every hydration) NOT
150
+ # ``flushed_prefix_messages`` (session-scoped, lags compacted by
151
+ # design for deferred-payload-mutation deployments and stays at the
152
+ # loaded value until the next ``prepare_payload`` flush gate runs).
153
+ # The retriever's binary "has compaction happened" signal must reflect
154
+ # durable content progress, not per-session payload mutation progress.
147
155
  _active_stage = time.monotonic()
148
156
  _ft = self._engine_state.flushed_prefix_messages
149
- if _ft > 0:
157
+ _post_compaction = int(
158
+ getattr(self._engine_state, "compacted_prefix_messages", 0) or 0
159
+ ) > 0
160
+ if _post_compaction:
150
161
  active_tags = []
151
162
  else:
152
163
  active_tags = self._get_active_tags(conversation_history)
@@ -182,7 +193,7 @@ class RetrievalAssembler:
182
193
  message=message,
183
194
  current_active_tags=active_tags,
184
195
  current_utilization=utilization,
185
- post_compaction=(_ft > 0),
196
+ post_compaction=_post_compaction,
186
197
  context_turns=context,
187
198
  )
188
199
  _note("retrieve_primary", _retrieve_stage)
@@ -254,7 +265,7 @@ class RetrievalAssembler:
254
265
  message=message,
255
266
  current_active_tags=active_tags,
256
267
  current_utilization=utilization,
257
- post_compaction=(_ft > 0),
268
+ post_compaction=_post_compaction,
258
269
  context_turns=expanded,
259
270
  )
260
271
  _note("retrieve_retry_general", _retry_retrieve_stage)
File without changes