fix(engine): sync migration URL and assorted engine fixes

Recovered from the 2026-06-27 snapshot import by classifying the base..snapshot delta at line granularity. Upstream base: d054b884 (2026-04-10).
This commit is contained in:
RCLL 2026-08-23 23:50:03 +03:00
parent c1dd7aa4a3
commit 77dcc6b80b
4 changed files with 32 additions and 5 deletions

View file

@ -1734,11 +1734,13 @@ class MemoryEngine(MemoryEngineInterface):
# Ensure embedding column dimension matches the model's dimension
# This is done after migrations and after embeddings.initialize()
# Use migration URL (sync driver) when available, fallback to main URL
_sync_url = config.migration_database_url or self.db_url
for tenant in tenants:
schema = tenant.schema
if schema:
ensure_embedding_dimension(
self.db_url,
_sync_url,
self.embeddings.dimension,
schema=schema,
vector_extension=config.vector_extension,
@ -1748,14 +1750,14 @@ class MemoryEngine(MemoryEngineInterface):
for tenant in tenants:
schema = tenant.schema
if schema:
ensure_vector_extension(self.db_url, vector_extension=config.vector_extension, schema=schema)
ensure_vector_extension(_sync_url, vector_extension=config.vector_extension, schema=schema)
# Ensure text search columns/indexes match the configured extension
for tenant in tenants:
schema = tenant.schema
if schema:
ensure_text_search_extension(
self.db_url, text_search_extension=config.text_search_extension, schema=schema
_sync_url, text_search_extension=config.text_search_extension, schema=schema
)
logger.info(f"Connecting to PostgreSQL at {mask_network_location(self.db_url)}")

View file

@ -67,6 +67,9 @@ async def insert_facts_batch(
tags_list = []
observation_scopes_list = []
text_signals_list = []
rooms_list = []
halls_list = []
layers_list = []
for fact in facts:
fact_texts.append(_sanitize_text(fact.fact_text))
@ -120,7 +123,8 @@ async def insert_facts_batch(
WITH input_data AS (
SELECT * FROM unnest(
$2::text[], $3::vector[], $4::timestamptz[], $5::timestamptz[], $6::timestamptz[], $7::timestamptz[],
$8::text[], $9::text[], $10::jsonb[], $11::text[], $12::text[], $13::jsonb[], $14::jsonb[], $15::text[]
$8::text[], $9::text[], $10::jsonb[], $11::text[], $12::text[], $13::jsonb[], $14::jsonb[], $15::text[],
$16::text[], $17::text[], $18::text[]
) AS t(text, embedding, event_date, occurred_start, occurred_end, mentioned_at,
context, fact_type, metadata, chunk_id, document_id, tags_json,
observation_scopes_json, text_signals, room, hall, layer)
@ -155,7 +159,8 @@ async def insert_facts_batch(
WITH input_data AS (
SELECT * FROM unnest(
$2::text[], $3::vector[], $4::timestamptz[], $5::timestamptz[], $6::timestamptz[], $7::timestamptz[],
$8::text[], $9::text[], $10::jsonb[], $11::text[], $12::text[], $13::jsonb[], $14::jsonb[], $15::text[]
$8::text[], $9::text[], $10::jsonb[], $11::text[], $12::text[], $13::jsonb[], $14::jsonb[], $15::text[],
$16::text[], $17::text[], $18::text[]
) AS t(text, embedding, event_date, occurred_start, occurred_end, mentioned_at,
context, fact_type, metadata, chunk_id, document_id, tags_json,
observation_scopes_json, text_signals, room, hall, layer)
@ -197,6 +202,9 @@ async def insert_facts_batch(
tags_list,
observation_scopes_list,
text_signals_list,
rooms_list,
halls_list,
layers_list,
)
unit_ids = [str(row["id"]) for row in results]

View file

@ -207,6 +207,9 @@ async def retrieve_semantic_bm25_combined(
f" AND (1 - (embedding <=> $1::vector)) >= 0.3"
f" {tags_clause}"
f" {groups_clause}"
f" {room_clause}"
f" {hall_clause}"
f" {layer_clause}"
f" ORDER BY embedding <=> $1::vector"
f" LIMIT {hnsw_fetch})"
)
@ -247,6 +250,9 @@ async def retrieve_semantic_bm25_combined(
f" {bm25_where_filter}"
f" {tags_clause}"
f" {groups_clause}"
f" {room_clause}"
f" {hall_clause}"
f" {layer_clause}"
f" ORDER BY {bm25_order_by}"
f" LIMIT $3)"
)
@ -260,6 +266,9 @@ async def retrieve_semantic_bm25_combined(
if tags:
params.append(tags)
params.extend(groups_params)
params.extend(room_params)
params.extend(hall_params)
params.extend(layer_params)
rows = await conn.fetch(query, *params)
@ -358,6 +367,9 @@ async def retrieve_temporal_combined(
if tags:
params.append(tags)
params.extend(groups_params)
params.extend(room_params_list)
params.extend(hall_params_list)
params.extend(layer_params_list)
# Two-phase entry point query:
# Phase 1 (date_ranked): rank by date only — no embedding computation — for all units in
@ -389,6 +401,9 @@ async def retrieve_temporal_combined(
)
{tags_clause}
{groups_clause}
{room_clause}
{hall_clause}
{layer_clause}
),
sim_ranked AS (
SELECT mu.id, mu.text, mu.context, mu.event_date, mu.occurred_start, mu.occurred_end, mu.mentioned_at, mu.fact_type, mu.proof_count, mu.document_id, mu.chunk_id, mu.tags, mu.metadata, mu.room, mu.hall, mu.layer,

View file

@ -296,6 +296,8 @@ class Bank(Base):
updated_at: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), server_default=func.now())
__table_args__ = (Index("idx_banks_bank_id", "bank_id"),)
class Tunnel(Base):
"""Cross-bank memory bridges — links between concepts in different banks (ADR-145 RCLL)."""