@@ -453,6 +453,62 @@ def test_reflection_handles_non_json_response(
453453 assert result ["reflection_passed" ] is True
454454 assert result ["reflection_iterations" ] == 1
455455
456+ def test_reflection_handles_json_in_code_fence (
457+ self , sample_review_state_with_roadmap : ReviewState
458+ ):
459+ """Test that reflection correctly parses JSON wrapped in markdown code fences."""
460+ mock_response = MagicMock ()
461+ # This is the format the LLM often returns - JSON wrapped in code fences
462+ mock_response .content = '```json\n {"passed": true, "notes": "Self-review: looks good"}\n ```'
463+
464+ mock_chain = MagicMock ()
465+ mock_chain .invoke .return_value = mock_response
466+
467+ mock_llm = MagicMock ()
468+ mock_llm .__or__ = MagicMock (return_value = mock_chain )
469+
470+ with patch ("review_roadmap.agent.nodes._get_llm_instance" , return_value = mock_llm ):
471+ with patch ("review_roadmap.agent.nodes.ChatPromptTemplate" ) as mock_template :
472+ mock_prompt = MagicMock ()
473+ mock_prompt .__or__ = MagicMock (return_value = mock_chain )
474+ mock_template .from_messages .return_value = mock_prompt
475+
476+ from review_roadmap .agent .nodes import reflect_on_roadmap
477+
478+ result = reflect_on_roadmap (sample_review_state_with_roadmap )
479+
480+ # Should correctly parse the JSON from within code fences
481+ assert result ["reflection_passed" ] is True
482+ assert result ["reflection_iterations" ] == 1
483+
484+ def test_reflection_handles_truncated_code_fence (
485+ self , sample_review_state_with_roadmap : ReviewState
486+ ):
487+ """Test that reflection handles truncated code fences (missing closing ```)."""
488+ mock_response = MagicMock ()
489+ # Truncated response - missing closing ```
490+ mock_response .content = '```json\n {"passed": true, "notes": "Self-review: good"}'
491+
492+ mock_chain = MagicMock ()
493+ mock_chain .invoke .return_value = mock_response
494+
495+ mock_llm = MagicMock ()
496+ mock_llm .__or__ = MagicMock (return_value = mock_chain )
497+
498+ with patch ("review_roadmap.agent.nodes._get_llm_instance" , return_value = mock_llm ):
499+ with patch ("review_roadmap.agent.nodes.ChatPromptTemplate" ) as mock_template :
500+ mock_prompt = MagicMock ()
501+ mock_prompt .__or__ = MagicMock (return_value = mock_chain )
502+ mock_template .from_messages .return_value = mock_prompt
503+
504+ from review_roadmap .agent .nodes import reflect_on_roadmap
505+
506+ result = reflect_on_roadmap (sample_review_state_with_roadmap )
507+
508+ # Should correctly parse the JSON even with truncated code fence
509+ assert result ["reflection_passed" ] is True
510+ assert result ["reflection_iterations" ] == 1
511+
456512 def test_reflection_increments_iteration_count (
457513 self , sample_review_state_with_roadmap : ReviewState
458514 ):
0 commit comments