Feature: Context analysis graph coverage As a maintainer I want uncovered code paths in the context analysis graph exercised So that regression risk is minimised Background: Given the context analysis graph module is importable And I have a fake LLM configured for context analysis graph tests @coverage Scenario: Agent initialises with an explicitly provided LLM When I create a ContextAnalysisAgent with a custom LLM Then the agent should use the provided LLM instance And the agent should be initialised successfully @coverage Scenario: Load files discovers missing file paths Given I have a ContextAnalysisAgent for graph coverage When I call load_files with a nonexistent file path Then the returned documents list should be empty And the returned error should contain "File not found" @coverage Scenario: Load files rejects directory paths Given I have a ContextAnalysisAgent for graph coverage And I have a temporary directory called "not_a_file" When I call load_files with the directory path Then the returned documents list should be empty And the returned error should contain "Not a file" @coverage Scenario: Load files reads a real file from disk Given I have a ContextAnalysisAgent for graph coverage And I have a temporary file "real.py" containing "print('hello')" When I call load_files with that file path Then the returned documents list should have 1 entry And the returned error should be empty @coverage Scenario: Load files combines missing and directory errors Given I have a ContextAnalysisAgent for graph coverage And I have a temporary directory called "adir" When I call load_files with both a missing file and the directory path Then the returned documents list should be empty And the returned error should contain "File not found" And the returned error should contain "Not a file" @coverage Scenario: Chunking splits documents exceeding chunk size Given I have a ContextAnalysisAgent for graph coverage with chunk_size 50 and chunk_overlap 10 And I have a state with a single document of 140 characters When I call chunk_documents on the state Then the resulting chunks list should have at least 3 entries And every chunk should carry a chunk_index in its metadata @coverage Scenario: Relevance scoring skips duplicate file chunks Given I have a ContextAnalysisAgent for graph coverage And I have a state with two chunks from the same source file "dup.py" When I call score_relevance on the state Then the relevance scores dictionary should contain exactly 1 entry @coverage Scenario: Relevance parser returns 0.3 for low keyword Given I have a ContextAnalysisAgent for graph coverage When I parse relevance from the text "low confidence in result" Then the parsed relevance score should be 0.3 @coverage Scenario: Relevance parser returns 0.5 for unknown text Given I have a ContextAnalysisAgent for graph coverage When I parse relevance from the text "undecided outcome" Then the parsed relevance score should be 0.5 @coverage Scenario: Async invocation completes the full workflow Given I have a ContextAnalysisAgent for graph coverage And I have a temporary file "async_test.py" containing "x = 1" When I run the workflow asynchronously via ainvoke Then the async result should contain a summary And the async result should contain documents @coverage Scenario: Sync streaming produces node-level events Given I have a ContextAnalysisAgent for graph coverage And I have a temporary file "stream_test.py" containing "y = 2" When I stream the workflow synchronously Then I should receive at least 1 stream event And each stream event should be a dictionary with a node key @coverage Scenario: Async streaming produces node-level events Given I have a ContextAnalysisAgent for graph coverage And I have a temporary file "astream_test.py" containing "z = 3" When I stream the workflow asynchronously Then I should receive at least 1 async stream event And each async stream event should be a dictionary with a node key @coverage Scenario: Agent initialises with default FakeListLLM when no LLM provided When I create a ContextAnalysisAgent without providing an LLM Then the agent should be initialised successfully And the agent LLM should be a FakeListLLM @coverage Scenario: Sync invoke runs the complete workflow end to end Given I have a ContextAnalysisAgent for graph coverage And I have a temporary file "invoke_test.py" containing "val = 42" When I invoke the workflow synchronously Then the sync result should contain a summary And the sync result should contain documents @coverage Scenario: Load files returns preloaded documents unchanged Given I have a ContextAnalysisAgent for graph coverage And I have a state with preloaded documents When I call load_files on the preloaded state Then the returned documents should equal the preloaded documents