e801eb1ee8
- Rewrite .forgejo/workflows/ci.yml to route all jobs through nox sessions - Fix coverage_report nox session: serial behave mode replaces broken parallel mode (22% -> 97% accuracy), raise fail-under from 85% to 97% - Pass posargs through format nox session for CI --check support - Add 11 CI workflow validation scenarios (Behave) + Robot smoke test + ASV bench - Add 108 new Behave scenarios covering 6 largest coverage gaps to reach 97%: yaml_template_engine, actor/config, actor/registry, message_router, context_analysis, context_service - Update docs/development/ci-cd.md with nox-based CI docs and 97% threshold - Restore implementation_plan.md verbose style, check off completed CI tasks Verified: 1673 scenarios pass, 97% coverage, lint clean, typecheck clean
107 lines
4.4 KiB
Gherkin
107 lines
4.4 KiB
Gherkin
Feature: Context analysis agent new coverage
|
|
As a developer
|
|
I want the ContextAnalysisAgent workflow thoroughly tested
|
|
So that file loading, dependency analysis, chunking, scoring, and summarization stay stable
|
|
|
|
Scenario: Agent initializes with default FakeListLLM
|
|
When I create a ContextAnalysisAgent without an LLM
|
|
Then the agent should use FakeListLLM
|
|
And the agent should have a compiled graph
|
|
|
|
Scenario: Agent initializes with custom LLM
|
|
When I create a ContextAnalysisAgent with a mock LLM
|
|
Then the agent should use the provided LLM
|
|
|
|
Scenario: _load_files returns preloaded documents when present
|
|
Given a ContextAnalysisAgent instance
|
|
When I invoke _load_files with preloaded documents
|
|
Then the result should return those preloaded documents
|
|
|
|
Scenario: _load_files loads real files from disk
|
|
Given a ContextAnalysisAgent instance
|
|
And a temporary Python file on disk
|
|
When I invoke _load_files with the temp file path
|
|
Then the result should contain loaded documents
|
|
|
|
Scenario: _load_files reports missing files as errors
|
|
Given a ContextAnalysisAgent instance
|
|
When I invoke _load_files with a nonexistent file path
|
|
Then the result error should mention file not found
|
|
|
|
Scenario: _load_files reports non-files as errors
|
|
Given a ContextAnalysisAgent instance
|
|
When I invoke _load_files with a directory path
|
|
Then the result error should mention not a file
|
|
|
|
Scenario: _analyze_dependencies extracts deps from documents
|
|
Given a ContextAnalysisAgent instance
|
|
And a state with one loaded document
|
|
When I invoke _analyze_dependencies
|
|
Then the dependencies dict should have entries
|
|
|
|
Scenario: _parse_dependencies extracts items from LLM output
|
|
Given a ContextAnalysisAgent instance
|
|
When I parse dependencies from "Dependencies: ['os', 'sys', 'pathlib']"
|
|
Then the parsed list should contain os sys pathlib
|
|
|
|
Scenario: _chunk_documents passes small docs through unchanged
|
|
Given a ContextAnalysisAgent instance
|
|
And a state with a small document
|
|
When I invoke _chunk_documents
|
|
Then the chunks should contain the original document
|
|
|
|
Scenario: _chunk_documents splits large docs into overlapping chunks
|
|
Given a ContextAnalysisAgent instance with chunk_size 100
|
|
And a state with a large document of 500 characters
|
|
When I invoke _chunk_documents
|
|
Then the chunks should contain more than one document
|
|
|
|
Scenario: _score_relevance scores each unique file
|
|
Given a ContextAnalysisAgent instance
|
|
And a state with chunks from two files
|
|
When I invoke _score_relevance
|
|
Then relevance scores should exist for both files
|
|
|
|
Scenario: _parse_relevance_score extracts numeric score
|
|
Given a ContextAnalysisAgent instance
|
|
When I parse relevance score from "Score: 0.85 - very relevant"
|
|
Then the parsed score should be approximately 0.85
|
|
|
|
Scenario: _parse_relevance_score returns 0.8 for high keyword
|
|
Given a ContextAnalysisAgent instance
|
|
When I parse relevance score from "This is High relevance"
|
|
Then the parsed score should be approximately 0.8
|
|
|
|
Scenario: _parse_relevance_score returns 0.3 for low keyword
|
|
Given a ContextAnalysisAgent instance
|
|
When I parse relevance score from "This has low relevance"
|
|
Then the parsed score should be approximately 0.3
|
|
|
|
Scenario: _parse_relevance_score returns 0.5 as default
|
|
Given a ContextAnalysisAgent instance
|
|
When I parse relevance score from "No numeric or keyword info"
|
|
Then the parsed score should be approximately 0.5
|
|
|
|
Scenario: _summarize_context generates summary
|
|
Given a ContextAnalysisAgent instance
|
|
And a full analysis state with documents and scores
|
|
When I invoke _summarize_context
|
|
Then the direct summary should be a non-empty string
|
|
|
|
Scenario: invoke runs the full workflow synchronously
|
|
Given a ContextAnalysisAgent instance
|
|
And a temporary Python file on disk
|
|
When I invoke the full workflow with the temp file
|
|
Then the result should contain summary and scores
|
|
|
|
Scenario: stream yields events from the workflow
|
|
Given a ContextAnalysisAgent instance
|
|
And a temporary Python file on disk
|
|
When I stream the workflow with the temp file
|
|
Then at least one analysis event should be yielded
|
|
|
|
Scenario: _with_retry wraps a chain that supports retry
|
|
Given a ContextAnalysisAgent instance
|
|
When I wrap a chain with retry support
|
|
Then the wrapped chain should be returned
|