From f79623174482a5f4da9d11036b9fb24dfcd02823 Mon Sep 17 00:00:00 2001 From: ComBba Date: Tue, 10 Feb 2026 09:02:02 +0900 Subject: [PATCH 1/2] fix(#267): emit evaluation_complete event in full_techniques mode - Import event_channel and create_sommelier_event in finalize.py - Emit quality_gate_complete event with final scores - Emit evaluation_complete event for frontend completion detection Closes #267 --- .../nodes/technique_categories/finalize.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/backend/app/graph/nodes/technique_categories/finalize.py b/backend/app/graph/nodes/technique_categories/finalize.py index 7718cf9..91f6978 100644 --- a/backend/app/graph/nodes/technique_categories/finalize.py +++ b/backend/app/graph/nodes/technique_categories/finalize.py @@ -5,6 +5,7 @@ from app.criteria.bmad_items import list_items, get_category, get_category_max from app.constants import get_quality_gate from app.models.graph import ItemScore +from app.services.event_channel import create_sommelier_event, get_event_channel async def finalize( @@ -52,6 +53,32 @@ async def finalize( quality_gate = get_quality_gate(normalized, coverage) + evaluation_id = state.get("evaluation_id", "") + if evaluation_id: + event_channel = get_event_channel() + event_channel.emit_sync( + evaluation_id, + create_sommelier_event( + evaluation_id=evaluation_id, + sommelier="finalize", + event_type="quality_gate_complete", + progress_percent=95, + message=f"Quality gate: {quality_gate}", + total_score=round(normalized, 2), + quality_gate=quality_gate, + ), + ) + event_channel.emit_sync( + evaluation_id, + create_sommelier_event( + evaluation_id=evaluation_id, + sommelier="system", + event_type="evaluation_complete", + progress_percent=100, + message="Evaluation complete!", + ), + ) + return { "trace_metadata": { "finalize": { From aa9a80215ac01bcd634f65876d49925b8504518a Mon Sep 17 00:00:00 2001 From: ComBba Date: Tue, 10 Feb 2026 09:08:26 +0900 Subject: [PATCH 2/2] fix: remove invalid kwargs and add error handling Address review feedback: - Remove total_score and quality_gate kwargs from create_sommelier_event - Include score in message string instead - Wrap event emission in try/except to prevent node failure --- .../nodes/technique_categories/finalize.py | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/backend/app/graph/nodes/technique_categories/finalize.py b/backend/app/graph/nodes/technique_categories/finalize.py index 91f6978..4dfb5b2 100644 --- a/backend/app/graph/nodes/technique_categories/finalize.py +++ b/backend/app/graph/nodes/technique_categories/finalize.py @@ -1,3 +1,4 @@ +import logging from datetime import datetime, timezone from typing import Any, Dict, List, Optional from langchain_core.runnables import RunnableConfig @@ -7,6 +8,8 @@ from app.models.graph import ItemScore from app.services.event_channel import create_sommelier_event, get_event_channel +logger = logging.getLogger(__name__) + async def finalize( state: EvaluationState, config: Optional[RunnableConfig] = None @@ -55,29 +58,32 @@ async def finalize( evaluation_id = state.get("evaluation_id", "") if evaluation_id: - event_channel = get_event_channel() - event_channel.emit_sync( - evaluation_id, - create_sommelier_event( - evaluation_id=evaluation_id, - sommelier="finalize", - event_type="quality_gate_complete", - progress_percent=95, - message=f"Quality gate: {quality_gate}", - total_score=round(normalized, 2), - quality_gate=quality_gate, - ), - ) - event_channel.emit_sync( - evaluation_id, - create_sommelier_event( - evaluation_id=evaluation_id, - sommelier="system", - event_type="evaluation_complete", - progress_percent=100, - message="Evaluation complete!", - ), - ) + try: + event_channel = get_event_channel() + event_channel.emit_sync( + evaluation_id, + create_sommelier_event( + evaluation_id=evaluation_id, + sommelier="finalize", + event_type="quality_gate_complete", + progress_percent=95, + message=f"Quality gate: {quality_gate}, score: {round(normalized, 2)}", + ), + ) + event_channel.emit_sync( + evaluation_id, + create_sommelier_event( + evaluation_id=evaluation_id, + sommelier="system", + event_type="evaluation_complete", + progress_percent=100, + message="Evaluation complete!", + ), + ) + except Exception: + logger.warning( + "Failed to emit finalize events for %s", evaluation_id, exc_info=True + ) return { "trace_metadata": {