fix(ui): stabilize company chat result topology
This commit is contained in:
@@ -37,6 +37,7 @@ from opc.layer2_organization.work_item_identity import (
|
||||
migrate_work_item_projection_metadata,
|
||||
projection_id_for_work_item,
|
||||
rework_projection_id_for_gate,
|
||||
result_delivery_identity_payload_for_task,
|
||||
target_projection_id_for_decision,
|
||||
target_projection_ids_for_decision,
|
||||
work_item_identity_payload,
|
||||
@@ -217,6 +218,52 @@ class WorkItemProjectionIdentityTests(unittest.TestCase):
|
||||
self.assertEqual(payload[WORK_ITEM_PROJECTION_ID_KEY], "task-proj")
|
||||
self.assertEqual(payload[WORK_ITEM_TURN_TYPE_KEY], "report")
|
||||
|
||||
def test_result_delivery_identity_uses_canonical_turn_and_retry_attempt(self) -> None:
|
||||
task = SimpleNamespace(
|
||||
id="task-1",
|
||||
retry_count=2,
|
||||
metadata={"runtime_v2_current_turn_id": "canonical-turn-1"},
|
||||
)
|
||||
|
||||
payload = result_delivery_identity_payload_for_task(task)
|
||||
|
||||
self.assertEqual(
|
||||
payload["result_delivery_id"],
|
||||
"result:task:task-1:turn:canonical-turn-1:attempt:2",
|
||||
)
|
||||
self.assertEqual(payload["source_task_id"], "task-1")
|
||||
self.assertEqual(payload["canonical_turn_id"], "canonical-turn-1")
|
||||
|
||||
def test_result_delivery_identity_does_not_collide_for_parallel_tasks(self) -> None:
|
||||
first = SimpleNamespace(id="task-1", retry_count=0, metadata={})
|
||||
second = SimpleNamespace(id="task-2", retry_count=0, metadata={})
|
||||
|
||||
first_payload = result_delivery_identity_payload_for_task(
|
||||
first,
|
||||
canonical_turn_id="shared-parent-turn",
|
||||
)
|
||||
second_payload = result_delivery_identity_payload_for_task(
|
||||
second,
|
||||
canonical_turn_id="shared-parent-turn",
|
||||
)
|
||||
|
||||
self.assertNotEqual(
|
||||
first_payload["result_delivery_id"],
|
||||
second_payload["result_delivery_id"],
|
||||
)
|
||||
self.assertIn(":task-1:", first_payload["result_delivery_id"])
|
||||
self.assertIn(":task-2:", second_payload["result_delivery_id"])
|
||||
|
||||
def test_result_delivery_identity_requires_an_execution_scope(self) -> None:
|
||||
task = SimpleNamespace(id="reused-task", retry_count=0, metadata={})
|
||||
|
||||
self.assertEqual(result_delivery_identity_payload_for_task(task), {
|
||||
"source_task_id": "reused-task",
|
||||
})
|
||||
first = result_delivery_identity_payload_for_task(task, execution_id="execution-1")
|
||||
second = result_delivery_identity_payload_for_task(task, execution_id="execution-2")
|
||||
self.assertNotEqual(first["result_delivery_id"], second["result_delivery_id"])
|
||||
|
||||
def test_migrate_projection_metadata_backfills_from_fallbacks_without_overwriting(self) -> None:
|
||||
migrated, changed = migrate_work_item_projection_metadata(
|
||||
{},
|
||||
|
||||
@@ -67,8 +67,95 @@ class MemoryManagerCompactionTests(unittest.IsolatedAsyncioTestCase):
|
||||
|
||||
compactor.maybe_compact_after_message.assert_not_awaited()
|
||||
|
||||
async def test_parent_child_result_preserves_structured_source_lineage(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
store = _MemoryStoreStub()
|
||||
memory = MemoryManager(Path(tmpdir), project_id="0009", store=store)
|
||||
task = Task(
|
||||
id="task-cto-result",
|
||||
title="CTO Result",
|
||||
assigned_to="cto",
|
||||
project_id="0009",
|
||||
session_id="child-session",
|
||||
parent_session_id="parent-session",
|
||||
metadata={"work_item_projection_id": "cto::analysis"},
|
||||
)
|
||||
|
||||
await memory.record_child_session_result(
|
||||
"parent-session",
|
||||
"child-session",
|
||||
task=task,
|
||||
result_content="done",
|
||||
result_delivery_id=(
|
||||
"result:task:task-cto-result:turn:canonical-cto-turn:attempt:0"
|
||||
),
|
||||
source_result_message_id="source-result-message",
|
||||
canonical_turn_id="canonical-cto-turn",
|
||||
)
|
||||
|
||||
metadata = store.session_messages[-1].metadata
|
||||
self.assertEqual(
|
||||
metadata["result_delivery_id"],
|
||||
"result:task:task-cto-result:turn:canonical-cto-turn:attempt:0",
|
||||
)
|
||||
self.assertEqual(metadata["source_result_message_id"], "source-result-message")
|
||||
self.assertEqual(metadata["source_task_id"], "task-cto-result")
|
||||
self.assertEqual(metadata["child_session_id"], "child-session")
|
||||
self.assertEqual(metadata["canonical_turn_id"], "canonical-cto-turn")
|
||||
|
||||
|
||||
class SharedRoleSessionExecutionTests(unittest.IsolatedAsyncioTestCase):
|
||||
def test_fallback_delivery_identity_is_per_result_not_per_provider_session(self) -> None:
|
||||
task = Task(
|
||||
id="shared-role-task",
|
||||
title="Shared role",
|
||||
assigned_to="cto",
|
||||
retry_count=0,
|
||||
)
|
||||
first = TaskResult(
|
||||
status=TaskStatus.AWAITING_HUMAN,
|
||||
content="first pause",
|
||||
artifacts={"provider_session_id": "provider-session-reused"},
|
||||
)
|
||||
second = TaskResult(
|
||||
status=TaskStatus.DONE,
|
||||
content="second result",
|
||||
artifacts={"provider_session_id": "provider-session-reused"},
|
||||
)
|
||||
|
||||
first_identity = OPCEngine._ensure_result_delivery_identity_for_commit(task, first)
|
||||
second_identity = OPCEngine._ensure_result_delivery_identity_for_commit(task, second)
|
||||
|
||||
self.assertNotEqual(
|
||||
first_identity["result_delivery_id"],
|
||||
second_identity["result_delivery_id"],
|
||||
)
|
||||
self.assertNotEqual(
|
||||
first.artifacts["result_execution_id"],
|
||||
second.artifacts["result_execution_id"],
|
||||
)
|
||||
self.assertNotIn("provider-session-reused", first_identity["result_delivery_id"])
|
||||
|
||||
def test_fallback_delivery_identity_is_stable_after_result_persistence(self) -> None:
|
||||
task = Task(id="external-task", title="External", assigned_to="cto")
|
||||
result = TaskResult(
|
||||
status=TaskStatus.DONE,
|
||||
content="done",
|
||||
artifacts={"runtime_session_id": "runtime-session-reused"},
|
||||
)
|
||||
first_identity = OPCEngine._ensure_result_delivery_identity_for_commit(task, result)
|
||||
persisted_artifacts = dict(result.artifacts)
|
||||
reloaded = TaskResult(
|
||||
status=TaskStatus.DONE,
|
||||
content="done",
|
||||
artifacts=persisted_artifacts,
|
||||
)
|
||||
|
||||
replay_identity = OPCEngine._ensure_result_delivery_identity_for_commit(task, reloaded)
|
||||
|
||||
self.assertEqual(replay_identity, first_identity)
|
||||
self.assertEqual(reloaded.artifacts, persisted_artifacts)
|
||||
|
||||
async def test_company_shared_role_session_keeps_results_local(self) -> None:
|
||||
engine = OPCEngine()
|
||||
engine.store = SimpleNamespace(
|
||||
@@ -81,7 +168,11 @@ class SharedRoleSessionExecutionTests(unittest.IsolatedAsyncioTestCase):
|
||||
record_task_completion_async=AsyncMock(),
|
||||
)
|
||||
engine._run_task_once = AsyncMock(
|
||||
return_value=TaskResult(status=TaskStatus.DONE, content="done", artifacts={})
|
||||
return_value=TaskResult(
|
||||
status=TaskStatus.DONE,
|
||||
content="done",
|
||||
artifacts={"result_delivery_id": "delivery-shared-role"},
|
||||
)
|
||||
)
|
||||
engine._apply_runtime_state_to_task = lambda task, result: None
|
||||
|
||||
@@ -105,3 +196,64 @@ class SharedRoleSessionExecutionTests(unittest.IsolatedAsyncioTestCase):
|
||||
|
||||
engine.memory.record_assistant_turn.assert_awaited_once()
|
||||
engine.memory.record_child_session_result.assert_not_awaited()
|
||||
metadata = engine.memory.record_assistant_turn.await_args.kwargs["metadata"]
|
||||
self.assertEqual(metadata["result_delivery_id"], "delivery-shared-role")
|
||||
self.assertEqual(metadata["source_task_id"], "task-cmo-review")
|
||||
self.assertEqual(metadata["child_session_id"], "app14:role:cmo")
|
||||
|
||||
async def test_child_result_and_parent_mirror_share_delivery_identity(self) -> None:
|
||||
engine = OPCEngine()
|
||||
engine.store = SimpleNamespace(
|
||||
get_task=AsyncMock(return_value=None),
|
||||
save_task=AsyncMock(),
|
||||
)
|
||||
engine.memory = SimpleNamespace(
|
||||
record_assistant_turn=AsyncMock(
|
||||
return_value=SimpleNamespace(message_id="source-result-message")
|
||||
),
|
||||
record_child_session_result=AsyncMock(),
|
||||
record_task_completion_async=AsyncMock(),
|
||||
)
|
||||
engine._run_task_once = AsyncMock(
|
||||
return_value=TaskResult(
|
||||
status=TaskStatus.DONE,
|
||||
content="done",
|
||||
artifacts={
|
||||
"canonical_turn_id": "runtime-generated-turn",
|
||||
"result_delivery_id": (
|
||||
"result:task:task-cto-result:turn:runtime-generated-turn:attempt:0"
|
||||
),
|
||||
"runtime_session_id": "runtime-session-1",
|
||||
},
|
||||
)
|
||||
)
|
||||
engine._apply_runtime_state_to_task = lambda task, result: None
|
||||
|
||||
task = Task(
|
||||
id="task-cto-result",
|
||||
title="CTO Result",
|
||||
assigned_to="cto",
|
||||
status=TaskStatus.PENDING,
|
||||
project_id="0009",
|
||||
session_id="child-session",
|
||||
parent_session_id="parent-session",
|
||||
metadata={
|
||||
"execution_mode": "company_mode",
|
||||
"work_item_projection_id": "cto::analysis",
|
||||
},
|
||||
)
|
||||
|
||||
await engine._execute_task(task)
|
||||
|
||||
child_metadata = engine.memory.record_assistant_turn.await_args.kwargs["metadata"]
|
||||
parent_call = engine.memory.record_child_session_result.await_args.kwargs
|
||||
self.assertEqual(
|
||||
child_metadata["result_delivery_id"],
|
||||
"result:task:task-cto-result:turn:runtime-generated-turn:attempt:0",
|
||||
)
|
||||
self.assertEqual(
|
||||
parent_call["result_delivery_id"],
|
||||
child_metadata["result_delivery_id"],
|
||||
)
|
||||
self.assertEqual(parent_call["source_result_message_id"], "source-result-message")
|
||||
self.assertEqual(parent_call["canonical_turn_id"], "runtime-generated-turn")
|
||||
|
||||
@@ -414,6 +414,13 @@ class NativeRuntimeV2Tests(unittest.IsolatedAsyncioTestCase):
|
||||
# cannot swallow it into the frozen shared-iteration row.
|
||||
self.assertTrue(metadata["company_final_turn"])
|
||||
self.assertEqual(metadata["ui_message_id"], "runtime-v2-company-assistant-final:ui-turn:company")
|
||||
self.assertEqual(
|
||||
metadata["result_delivery_id"],
|
||||
"result:task:company-role-task:turn:ui-turn:company:attempt:0",
|
||||
)
|
||||
self.assertEqual(metadata["source_task_id"], "company-role-task")
|
||||
self.assertEqual(metadata["child_session_id"], "sess-company")
|
||||
self.assertEqual(metadata["work_item_projection_id"], "chao::intake")
|
||||
self.assertNotIn("visible_speaker", metadata)
|
||||
|
||||
await runtime._persist_assistant_turn(
|
||||
@@ -429,6 +436,7 @@ class NativeRuntimeV2Tests(unittest.IsolatedAsyncioTestCase):
|
||||
intermediate_metadata = memory.appended_messages[-1]["kwargs"]["metadata"]
|
||||
self.assertEqual(intermediate_metadata["kind"], "runtime_v2_company_assistant")
|
||||
self.assertNotIn("company_final_turn", intermediate_metadata)
|
||||
self.assertNotIn("result_delivery_id", intermediate_metadata)
|
||||
self.assertEqual(
|
||||
intermediate_metadata["ui_message_id"],
|
||||
"runtime-v2-company-assistant:ui-turn:company",
|
||||
|
||||
@@ -16,10 +16,34 @@ from opc.plugins.office_ui.chat_store import (
|
||||
_MessageMatchIndex,
|
||||
_MessageMatchState,
|
||||
)
|
||||
from opc.plugins.office_ui.snapshot_builder import build_transcript_ui_messages
|
||||
from opc.plugins.office_ui.snapshot_builder import (
|
||||
build_transcript_ui_messages,
|
||||
collapse_adjacent_transcript_duplicates,
|
||||
)
|
||||
from opc.plugins.office_ui.ws_handler import WSHandler
|
||||
|
||||
|
||||
_WORK_ITEM_RESULT = """Both work items have been successfully dispatched and can execute in parallel.
|
||||
|
||||
**Dispatch Summary**
|
||||
|
||||
**Work Item 1: OpenOPC Source Code Architecture Deep-Dive Analysis**
|
||||
- ID: `1ed5f5f1-ac41-49a1-b1fa-23bbc9adab82`
|
||||
- Owner: senior_engineer
|
||||
- Scope: `openopc-source-analysis`
|
||||
- Output: `/workspace/openopc-architecture-analysis.md`
|
||||
- Covers: Layered architecture, work-item state machines, collaboration policy, and seat executors.
|
||||
|
||||
**Work Item 2: External Multi-Agent Frameworks Architecture Research**
|
||||
- ID: `d0307208-6b95-44c1-9b51-6bf073bbdcef`
|
||||
- Owner: senior_engineer
|
||||
- Scope: `external-frameworks-research`
|
||||
- Output: `/workspace/external-frameworks-analysis.md`
|
||||
- Covers: Architecture models, coordination, communication, extensibility, and implementation details.
|
||||
|
||||
Both are independent and can execute in parallel."""
|
||||
|
||||
|
||||
class TranscriptStorePaginationTests(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_summary_page_filters_full_detail_rows_before_limit(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
@@ -216,6 +240,43 @@ class TranscriptStorePaginationTests(unittest.IsolatedAsyncioTestCase):
|
||||
detail_level="summary",
|
||||
))
|
||||
|
||||
def test_renderer_preserves_structured_result_lineage(self) -> None:
|
||||
lineage = {
|
||||
"canonical_turn_id": "turn-canonical",
|
||||
"turn_id": "turn-execution",
|
||||
"result_delivery_id": "delivery-1",
|
||||
"source_result_message_id": "source-message-1",
|
||||
"source_task_id": "source-task-1",
|
||||
"child_session_id": "child-session-1",
|
||||
"conversation_turn_id": "conversation-turn-1",
|
||||
"execution_turn_id": "execution-turn-1",
|
||||
"work_item_projection_id": "architecture",
|
||||
"work_item_turn_type": "delivery",
|
||||
"runtime_session_id": "runtime-session-1",
|
||||
}
|
||||
rendered = build_transcript_ui_messages(
|
||||
[{
|
||||
"message": SimpleNamespace(
|
||||
message_id="result-message-1",
|
||||
role="assistant",
|
||||
agent_id="cto",
|
||||
created_at=datetime(2026, 7, 14, 10, 0, 0),
|
||||
summary_flag=False,
|
||||
metadata={"kind": "child_result", **lineage},
|
||||
),
|
||||
"parts": [SimpleNamespace(
|
||||
part_type="text",
|
||||
payload={"text": "Completed architecture analysis."},
|
||||
)],
|
||||
}],
|
||||
channel_id="session:parent-task",
|
||||
task_id="parent-task",
|
||||
)
|
||||
|
||||
self.assertEqual(len(rendered), 1)
|
||||
for key, value in lineage.items():
|
||||
self.assertEqual(rendered[0]["metadata"].get(key), value)
|
||||
|
||||
|
||||
class ChatStorePaginationTests(unittest.TestCase):
|
||||
@staticmethod
|
||||
@@ -293,6 +354,129 @@ class ChatStorePaginationTests(unittest.TestCase):
|
||||
actual = store._dedupe_messages(messages)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_work_item_colons_are_not_treated_as_narrative_wrappers(self) -> None:
|
||||
normalized = ChatStore._normalize_duplicate_content(_WORK_ITEM_RESULT)
|
||||
self.assertEqual(normalized, _WORK_ITEM_RESULT)
|
||||
self.assertEqual(ChatStore._normalize_duplicate_content(normalized), normalized)
|
||||
|
||||
def test_duplicate_merge_keeps_work_item_display_content_across_replays(self) -> None:
|
||||
store = ChatStore(None) # type: ignore[arg-type]
|
||||
current = {
|
||||
"message_id": "runtime-final",
|
||||
"channel_id": "session:cto",
|
||||
"sender": "assistant",
|
||||
"sender_name": "CTO",
|
||||
"content": _WORK_ITEM_RESULT,
|
||||
"created_at": 1.0,
|
||||
"reply_to_id": None,
|
||||
"mentions": [],
|
||||
"metadata": {
|
||||
"source": "engine",
|
||||
"transcript_kind": "runtime_v2_company_assistant",
|
||||
},
|
||||
}
|
||||
canonical = {
|
||||
**current,
|
||||
"message_id": "child-task-result",
|
||||
"created_at": 2.0,
|
||||
"metadata": {
|
||||
"source": "engine",
|
||||
"transcript_kind": "child_task_result",
|
||||
},
|
||||
}
|
||||
|
||||
for _ in range(6):
|
||||
current = store._merge_duplicate_messages(current, canonical)
|
||||
self.assertEqual(current["content"], _WORK_ITEM_RESULT)
|
||||
|
||||
def test_duplicate_merge_reuses_an_original_unwrapped_surface(self) -> None:
|
||||
store = ChatStore(None) # type: ignore[arg-type]
|
||||
body = "Canonical answer " + ("with implementation details. " * 8)
|
||||
wrapped = {
|
||||
"message_id": "runtime-final",
|
||||
"channel_id": "session:answer",
|
||||
"sender": "assistant",
|
||||
"sender_name": "OPC",
|
||||
"content": f"**Top level answer**: {body}",
|
||||
"created_at": 1.0,
|
||||
"metadata": {
|
||||
"source": "engine",
|
||||
"transcript_kind": "runtime_v2_assistant",
|
||||
},
|
||||
}
|
||||
unwrapped = {
|
||||
**wrapped,
|
||||
"message_id": "top-level-reply",
|
||||
"content": body,
|
||||
"created_at": 2.0,
|
||||
"metadata": {
|
||||
"source": "engine",
|
||||
"transcript_kind": "top_level_reply",
|
||||
},
|
||||
}
|
||||
|
||||
merged = store._merge_duplicate_messages(wrapped, unwrapped)
|
||||
self.assertEqual(merged["content"], unwrapped["content"])
|
||||
self.assertIn(merged["content"], (wrapped["content"], unwrapped["content"]))
|
||||
|
||||
def test_result_delivery_identity_is_namespaced_without_canonical_turn_fallback(self) -> None:
|
||||
store = ChatStore(None) # type: ignore[arg-type]
|
||||
existing = {
|
||||
"message_id": "raw-final",
|
||||
"channel_id": "session:result",
|
||||
"sender": "assistant",
|
||||
"content": "runtime wording",
|
||||
"created_at": 1.0,
|
||||
"metadata": {
|
||||
"result_delivery_id": "delivery-1",
|
||||
"canonical_turn_id": "turn-shared",
|
||||
},
|
||||
}
|
||||
delivered = {
|
||||
**existing,
|
||||
"message_id": "child-task-result",
|
||||
"content": "canonical result wording",
|
||||
"metadata": {
|
||||
"result_delivery_id": "delivery-1",
|
||||
"canonical_turn_id": "turn-shared",
|
||||
},
|
||||
}
|
||||
unrelated_user = {
|
||||
**existing,
|
||||
"message_id": "user-turn",
|
||||
"sender": "user",
|
||||
"content": "different user text",
|
||||
"metadata": {"canonical_turn_id": "turn-shared"},
|
||||
}
|
||||
|
||||
self.assertIn("result_delivery:delivery-1", store._message_identity_keys(existing))
|
||||
self.assertTrue(store._messages_semantically_match(existing, delivered))
|
||||
self.assertFalse(store._messages_semantically_match(existing, unrelated_user))
|
||||
|
||||
def test_transcript_collapse_keeps_work_item_display_content_across_replays(self) -> None:
|
||||
runtime = {
|
||||
"message_id": "runtime-final",
|
||||
"sender": "assistant",
|
||||
"sender_name": "CTO",
|
||||
"content": _WORK_ITEM_RESULT,
|
||||
"created_at": 1.0,
|
||||
"metadata": {"transcript_kind": "runtime_v2_company_assistant"},
|
||||
}
|
||||
canonical = {
|
||||
**runtime,
|
||||
"message_id": "child-task-result",
|
||||
"created_at": 2.0,
|
||||
"metadata": {"transcript_kind": "child_task_result"},
|
||||
}
|
||||
|
||||
collapsed = collapse_adjacent_transcript_duplicates([runtime, canonical])
|
||||
self.assertEqual(len(collapsed), 1)
|
||||
self.assertEqual(collapsed[0]["content"], _WORK_ITEM_RESULT)
|
||||
|
||||
replayed = collapse_adjacent_transcript_duplicates([runtime, collapsed[0]])
|
||||
self.assertEqual(len(replayed), 1)
|
||||
self.assertEqual(replayed[0]["content"], _WORK_ITEM_RESULT)
|
||||
|
||||
def test_indexed_dedupe_normalizes_long_content_once_per_row(self) -> None:
|
||||
class CountingChatStore(ChatStore):
|
||||
normalize_calls = 0
|
||||
@@ -501,6 +685,136 @@ class ChatStorePaginationTests(unittest.TestCase):
|
||||
await db.close()
|
||||
tmpdir.cleanup()
|
||||
|
||||
def test_backfill_same_id_repairs_destructively_normalized_content(self) -> None:
|
||||
asyncio.run(self._exercise_backfill_same_id_repairs_content())
|
||||
|
||||
async def _exercise_backfill_same_id_repairs_content(self) -> None:
|
||||
tmpdir = tempfile.TemporaryDirectory()
|
||||
db = _SQLiteConnectionAdapter(str(Path(tmpdir.name) / "ui-state.db"))
|
||||
store = ChatStore(db) # type: ignore[arg-type]
|
||||
await store.initialize()
|
||||
channel_id = "session:work-item-repair"
|
||||
project_id = "test-project"
|
||||
damaged_content = _WORK_ITEM_RESULT[_WORK_ITEM_RESULT.index("OpenOPC Source"):]
|
||||
metadata = {
|
||||
"source": "engine",
|
||||
"transcript_kind": "child_result",
|
||||
"legacy_cache_marker": True,
|
||||
}
|
||||
authoritative = {
|
||||
"message_id": "result-message-1",
|
||||
"sender": "assistant",
|
||||
"sender_name": "CTO",
|
||||
"content": _WORK_ITEM_RESULT,
|
||||
"created_at": 1.0,
|
||||
"metadata": {
|
||||
"source": "engine",
|
||||
"transcript_kind": "child_result",
|
||||
},
|
||||
}
|
||||
try:
|
||||
await store.insert_message(
|
||||
channel_id,
|
||||
"assistant",
|
||||
"CTO",
|
||||
damaged_content,
|
||||
metadata=metadata,
|
||||
message_id="result-message-1",
|
||||
project_id=project_id,
|
||||
created_at=1.0,
|
||||
)
|
||||
|
||||
repaired = await store.backfill_messages(
|
||||
channel_id,
|
||||
[authoritative],
|
||||
project_id=project_id,
|
||||
)
|
||||
replayed = await store.backfill_messages(
|
||||
channel_id,
|
||||
[authoritative],
|
||||
project_id=project_id,
|
||||
)
|
||||
rows = await store.get_channel_messages(
|
||||
channel_id,
|
||||
limit=20,
|
||||
project_id=project_id,
|
||||
)
|
||||
|
||||
self.assertEqual([message["message_id"] for message in repaired], ["result-message-1"])
|
||||
self.assertEqual(replayed, [])
|
||||
self.assertEqual(len(rows), 1)
|
||||
self.assertEqual(rows[0]["content"], _WORK_ITEM_RESULT)
|
||||
self.assertTrue(rows[0]["metadata"].get("legacy_cache_marker"))
|
||||
finally:
|
||||
await db.close()
|
||||
tmpdir.cleanup()
|
||||
|
||||
def test_backfill_semantic_duplicate_upgrades_existing_row_in_place(self) -> None:
|
||||
asyncio.run(self._exercise_backfill_semantic_duplicate_upgrade())
|
||||
|
||||
async def _exercise_backfill_semantic_duplicate_upgrade(self) -> None:
|
||||
tmpdir = tempfile.TemporaryDirectory()
|
||||
db = _SQLiteConnectionAdapter(str(Path(tmpdir.name) / "ui-state.db"))
|
||||
store = ChatStore(db) # type: ignore[arg-type]
|
||||
await store.initialize()
|
||||
channel_id = "session:semantic-result-repair"
|
||||
project_id = "test-project"
|
||||
authoritative_content = _WORK_ITEM_RESULT
|
||||
authoritative = {
|
||||
"message_id": "source-result-message",
|
||||
"sender": "cto",
|
||||
"sender_name": "CTO",
|
||||
"content": authoritative_content,
|
||||
"created_at": 2.0,
|
||||
"metadata": {
|
||||
"source": "engine",
|
||||
"transcript_kind": "child_task_result",
|
||||
},
|
||||
}
|
||||
try:
|
||||
await store.insert_message(
|
||||
channel_id,
|
||||
"assistant",
|
||||
"CTO",
|
||||
f"**Legacy result**: {_WORK_ITEM_RESULT}",
|
||||
metadata={
|
||||
"source": "engine",
|
||||
"transcript_kind": "runtime_v2_company_assistant",
|
||||
"legacy_cache_marker": True,
|
||||
},
|
||||
message_id="mounted-cache-row",
|
||||
project_id=project_id,
|
||||
created_at=1.0,
|
||||
)
|
||||
|
||||
upgraded = await store.backfill_messages(
|
||||
channel_id,
|
||||
[authoritative],
|
||||
project_id=project_id,
|
||||
)
|
||||
replayed = await store.backfill_messages(
|
||||
channel_id,
|
||||
[authoritative],
|
||||
project_id=project_id,
|
||||
)
|
||||
rows = await store.get_channel_messages(
|
||||
channel_id,
|
||||
limit=20,
|
||||
project_id=project_id,
|
||||
)
|
||||
|
||||
self.assertEqual([message["message_id"] for message in upgraded], ["mounted-cache-row"])
|
||||
self.assertEqual(replayed, [])
|
||||
self.assertEqual(len(rows), 1)
|
||||
self.assertEqual(rows[0]["message_id"], "mounted-cache-row")
|
||||
self.assertEqual(rows[0]["created_at"], 1.0)
|
||||
self.assertEqual(rows[0]["content"], authoritative_content)
|
||||
self.assertEqual(rows[0]["metadata"].get("transcript_kind"), "child_task_result")
|
||||
self.assertTrue(rows[0]["metadata"].get("legacy_cache_marker"))
|
||||
finally:
|
||||
await db.close()
|
||||
tmpdir.cleanup()
|
||||
|
||||
def test_summary_cache_page_filters_before_raw_fetch_limit(self) -> None:
|
||||
asyncio.run(self._exercise_summary_cache_page())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user