Skip to content

Commit 5167c70

Browse files
feat: coverage-aware analysis for generate flow (044)
Surface coverage and criteria context in the analysis phase so the Copilot agent can propose tests that close real gaps. Adds CoverageSnapshot builder, context formatter, presenter enrichment, and progress/result plumbing, plus tests covering the new analysis path.
1 parent 7c09e30 commit 5167c70

28 files changed

+1987
-65
lines changed

CLAUDE.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,10 @@ Generated in JSON, Markdown, HTML. Features: test titles from `_index.json`, hum
130130

131131
<!-- MANUAL ADDITIONS START -->
132132
<!-- MANUAL ADDITIONS END -->
133+
134+
## Active Technologies
135+
- C# 12, .NET 8+ + GitHub Copilot SDK, System.CommandLine, Spectre.Console, System.Text.Json, YamlDotNet (044-coverage-aware-analysis)
136+
- File-based (Markdown/YAML/JSON in `test-cases/`, `docs/criteria/`, `_index.json`, `_criteria_index.yaml`) (044-coverage-aware-analysis)
137+
138+
## Recent Changes
139+
- 044-coverage-aware-analysis: Added C# 12, .NET 8+ + GitHub Copilot SDK, System.CommandLine, Spectre.Console, System.Text.Json, YamlDotNet

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
1717

1818
<!-- Versioning -->
19-
<Version>1.49.0</Version>
19+
<Version>1.50.0</Version>
2020
<Authors>Spectra Contributors</Authors>
2121
<Company>Spectra</Company>
2222
<Product>Spectra</Product>

docs/cli-reference.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ techniques (Equivalence Partitioning, Boundary Value Analysis, Decision
134134
Table, State Transition, Error Guessing, Use Case). The analysis output
135135
includes both a category breakdown (`happy_path`, `boundary`, `negative`, …)
136136
and a technique breakdown (`BVA`, `EP`, `DT`, `ST`, `EG`, `UC`) — see spec
137-
037. Supports multiple modes.
137+
037. The analysis step is **coverage-aware** (spec 044): for existing suites,
138+
it considers test coverage from `_index.json`, acceptance criteria, and
139+
doc sections to recommend only gap tests. Supports multiple modes.
138140

139141
**Interactive Session** — four-phase guided session:
140142

docs/coverage.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,20 @@ Scan patterns are templates where `{id}` is replaced with the test ID regex. Exa
170170

171171
If `scan_patterns` is empty, SPECTRA falls back to the legacy `attribute_patterns` regex list.
172172

173+
## Coverage-Aware Generation
174+
175+
When running `spectra ai generate`, the analysis step is coverage-aware for existing suites. Before identifying testable behaviors, the analyzer builds a coverage snapshot from:
176+
177+
- **`_index.json`**: Existing test titles, criteria links, and source refs
178+
- **`.criteria.yaml` files**: All acceptance criteria, cross-referenced against tests
179+
- **`docs/_index.md`**: Documentation sections, cross-referenced against test source refs
180+
181+
The AI receives this coverage context and only recommends tests for genuine gaps — uncovered criteria and undocumented sections. For a mature suite with 231 tests covering 38/41 criteria, the analysis recommends ~8 new tests (the actual gap) instead of 139.
182+
183+
For suites with more than 500 tests, the analyzer switches to summary mode to conserve prompt tokens: only coverage statistics and uncovered items are sent, not the full title list.
184+
185+
New suites with no `_index.json` or criteria files work exactly as before — the coverage context is simply omitted.
186+
173187
## Coverage Configuration
174188

175189
Full coverage settings in `spectra.config.json`:

docs/customization.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ When analyzing documentation, pay special attention to:
109109
- Rate limiting and abuse prevention on public APIs
110110
```
111111

112+
**Coverage-aware analysis**: The `behavior-analysis.md` template includes a
113+
`{{coverage_context}}` placeholder (spec 044). When an existing suite has
114+
coverage data, this resolves to a markdown block listing covered/uncovered
115+
criteria and doc sections, directing the AI to focus on gaps. If your custom
116+
template omits this placeholder, coverage context is simply not injected.
117+
112118
**Safe updates**: `spectra update-skills` refreshes unmodified templates to
113119
the latest version. Modified templates are preserved. Use
114120
`spectra prompts reset {template}` to restore a template to default.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Specification Quality Checklist: Coverage-Aware Behavior Analysis
2+
3+
**Purpose**: Validate specification completeness and quality before proceeding to planning
4+
**Created**: 2026-04-13
5+
**Feature**: [spec.md](../spec.md)
6+
7+
## Content Quality
8+
9+
- [x] No implementation details (languages, frameworks, APIs)
10+
- [x] Focused on user value and business needs
11+
- [x] Written for non-technical stakeholders
12+
- [x] All mandatory sections completed
13+
14+
## Requirement Completeness
15+
16+
- [x] No [NEEDS CLARIFICATION] markers remain
17+
- [x] Requirements are testable and unambiguous
18+
- [x] Success criteria are measurable
19+
- [x] Success criteria are technology-agnostic (no implementation details)
20+
- [x] All acceptance scenarios are defined
21+
- [x] Edge cases are identified
22+
- [x] Scope is clearly bounded
23+
- [x] Dependencies and assumptions identified
24+
25+
## Feature Readiness
26+
27+
- [x] All functional requirements have clear acceptance criteria
28+
- [x] User scenarios cover primary flows
29+
- [x] Feature meets measurable outcomes defined in Success Criteria
30+
- [x] No implementation details leak into specification
31+
32+
## Notes
33+
34+
- All items pass. Spec is ready for `/speckit.plan`.
35+
- The spec references file formats (`_index.json`, `_criteria_index.yaml`) by name since they are domain concepts (not implementation details) — these are the user-facing data files the feature operates on.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Contract: Coverage Context in Analysis Output
2+
3+
**Date**: 2026-04-13 | **Feature**: 044-coverage-aware-analysis
4+
5+
## JSON Output Contract (--output-format json)
6+
7+
When `spectra ai generate --analyze-only --output-format json` runs on a suite with existing tests, the `analysis` object in the result JSON includes coverage fields:
8+
9+
### New fields in `analysis` object
10+
11+
```json
12+
{
13+
"status": "success",
14+
"analysis": {
15+
"total_behaviors": 8,
16+
"already_covered": 233,
17+
"recommended": 8,
18+
"breakdown": { "boundary": 2, "negative": 2, "happy_path": 3, "edge_case": 1 },
19+
"technique_breakdown": { "BVA": 3, "EP": 2, "EG": 1, "UC": 2 },
20+
"existing_test_count": 231,
21+
"total_criteria": 41,
22+
"covered_criteria": 38,
23+
"uncovered_criteria": 3,
24+
"uncovered_criteria_ids": ["AC-039", "AC-040", "AC-041"]
25+
}
26+
}
27+
```
28+
29+
### Backward compatibility
30+
31+
- All new fields have defaults: `existing_test_count: 0`, `total_criteria: 0`, `covered_criteria: 0`, `uncovered_criteria: 0`, `uncovered_criteria_ids: []`
32+
- Old consumers that don't read these fields are unaffected
33+
- When no coverage data is available (new suite), all new fields are 0/empty
34+
35+
## Prompt Template Contract
36+
37+
### New placeholder: `{{coverage_context}}`
38+
39+
Added to `behavior-analysis.md` template. Resolves to a markdown block or empty string.
40+
41+
**Full mode** (tests <= 500): Includes covered criteria IDs, uncovered criteria details, covered/uncovered source refs, and truncated test titles.
42+
43+
**Summary mode** (tests > 500): Includes only coverage statistics and uncovered items. No title list.
44+
45+
**Empty** (no coverage data): Placeholder resolves to empty string. Template behavior is identical to pre-feature.
46+
47+
### User customization
48+
49+
Users can override `behavior-analysis.md` via `.spectra/prompts/behavior-analysis.md`. If their template omits `{{coverage_context}}`, coverage data is simply not injected — no error, no crash.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Data Model: Coverage-Aware Behavior Analysis
2+
3+
**Date**: 2026-04-13 | **Feature**: 044-coverage-aware-analysis
4+
5+
## New Entities
6+
7+
### CoverageSnapshot
8+
9+
Aggregated view of what's already tested in a suite. Built from three independent data sources.
10+
11+
| Field | Type | Source | Description |
12+
|-------|------|--------|-------------|
13+
| ExistingTestCount | int | `_index.json` | Total test cases in the suite |
14+
| ExistingTestTitles | string[] | `_index.json` | Test titles for dedup (truncated to 80 chars) |
15+
| CoveredCriteriaIds | HashSet\<string\> | `_index.json` tests → criteria fields | Criteria IDs with at least one linked test |
16+
| UncoveredCriteria | UncoveredCriterion[] | `_criteria_index.yaml` - CoveredCriteriaIds | Criteria with zero linked tests |
17+
| CoveredSourceRefs | HashSet\<string\> | `_index.json` tests → source_refs fields | Doc sections with at least one linked test |
18+
| UncoveredSourceRefs | string[] | `docs/_index.md` - CoveredSourceRefs | Doc sections with no linked tests |
19+
| TotalCriteriaCount | int | `_criteria_index.yaml` | Total criteria across all sources |
20+
| Mode | Full \| Summary | Computed | Full if tests <= 500, Summary otherwise |
21+
22+
**Lifecycle**: Created per analysis run. Not persisted — derived from committed files.
23+
24+
**Validation**:
25+
- Empty/missing data sources produce zero values (not errors)
26+
- CoveredCriteriaIds uses case-insensitive comparison
27+
- CoveredSourceRefs uses case-insensitive comparison
28+
29+
### UncoveredCriterion
30+
31+
A single acceptance criterion that has no linked tests.
32+
33+
| Field | Type | Source | Description |
34+
|-------|------|--------|-------------|
35+
| Id | string | `.criteria.yaml` | Criterion identifier (e.g., "AC-001") |
36+
| Text | string | `.criteria.yaml` | Full criterion text |
37+
| Source | string? | `.criteria.yaml` | Source document path |
38+
| Priority | string | `.criteria.yaml` | Priority level (high/medium/low) |
39+
40+
## Modified Entities
41+
42+
### GenerateAnalysis (in GenerateResult.cs)
43+
44+
New fields added alongside existing ones:
45+
46+
| Field | Type | Default | Description |
47+
|-------|------|---------|-------------|
48+
| ExistingTestCount | int | 0 | Total tests in suite (from snapshot) |
49+
| TotalCriteria | int | 0 | Total acceptance criteria count |
50+
| CoveredCriteria | int | 0 | Criteria with linked tests |
51+
| UncoveredCriteria | int | 0 | Criteria without linked tests |
52+
| UncoveredCriteriaIds | string[] | [] | IDs of uncovered criteria |
53+
54+
**Backward compatibility**: All new fields default to 0 or empty. Old JSON consumers ignore unknown fields. Old JSON without new fields deserializes with defaults.
55+
56+
### BehaviorAnalysisResult (unchanged schema)
57+
58+
No structural changes. The `AlreadyCovered` field now uses the snapshot count (when available) instead of title-similarity heuristic. `RecommendedCount` derives from `TotalBehaviors - AlreadyCovered` as before.
59+
60+
## Data Flow
61+
62+
```
63+
_index.json ──────┐
64+
65+
.criteria.yaml ────┤──→ CoverageSnapshotBuilder.BuildAsync() ──→ CoverageSnapshot
66+
67+
docs/_index.md ────┘
68+
69+
70+
CoverageContextFormatter.Format(snapshot) ──→ string (markdown block)
71+
72+
73+
PlaceholderResolver.Resolve(template, {coverage_context: block})
74+
75+
76+
BehaviorAnalyzer.AnalyzeAsync() ──→ BehaviorAnalysisResult
77+
78+
79+
GenerateAnalysis (enriched with snapshot stats)
80+
```
81+
82+
## Relationships to Existing Models
83+
84+
- **TestIndexEntry** (`_index.json`): Read `Criteria` (string[]) and `SourceRefs` (string[]) fields
85+
- **AcceptanceCriterion** (`.criteria.yaml`): Read `Id`, `Text`, `Source`/`SourceDoc`, `Priority` fields
86+
- **DocumentIndexEntry** (`docs/_index.md`): Read `Path` and `Sections[].Heading` for source ref matching
87+
- **CriteriaIndex** (`_criteria_index.yaml`): Read `Sources[]` to locate `.criteria.yaml` files
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Implementation Plan: Coverage-Aware Behavior Analysis
2+
3+
**Branch**: `044-coverage-aware-analysis` | **Date**: 2026-04-13 | **Spec**: [spec.md](spec.md)
4+
**Input**: Feature specification from `/specs/044-coverage-aware-analysis/spec.md`
5+
6+
## Summary
7+
8+
The behavior analysis step in `spectra ai generate` currently treats documentation as a blank slate, identifying all testable behaviors and applying a weak title-similarity heuristic for deduplication. For mature suites this produces wildly inaccurate recommendations (139 new tests when 8 are actually needed). This plan adds a coverage snapshot that feeds existing test index, criteria coverage, and doc section coverage into the analysis prompt so the AI only recommends tests for genuine gaps.
9+
10+
## Technical Context
11+
12+
**Language/Version**: C# 12, .NET 8+
13+
**Primary Dependencies**: GitHub Copilot SDK, System.CommandLine, Spectre.Console, System.Text.Json, YamlDotNet
14+
**Storage**: File-based (Markdown/YAML/JSON in `test-cases/`, `docs/criteria/`, `_index.json`, `_criteria_index.yaml`)
15+
**Testing**: xUnit (~1279 tests across 3 test projects)
16+
**Target Platform**: Windows/macOS/Linux CLI
17+
**Project Type**: CLI tool with MCP server
18+
**Performance Goals**: Coverage snapshot computation < 2s for 500 tests
19+
**Constraints**: Prompt token overhead < 5,000 tokens; switch to summary mode > 500 tests
20+
**Scale/Scope**: Suites up to 500+ tests, 50+ criteria, 20+ doc sections
21+
22+
## Constitution Check
23+
24+
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
25+
26+
| Principle | Status | Notes |
27+
|-----------|--------|-------|
28+
| I. GitHub as Source of Truth | PASS | All data read from committed files (`_index.json`, `.criteria.yaml`, `_index.md`) |
29+
| II. Deterministic Execution | PASS | Same coverage data + same docs = same snapshot; no randomness in snapshot building |
30+
| III. Orchestrator-Agnostic Design | PASS | Coverage context is injected into the prompt template, not tied to a specific LLM |
31+
| IV. CLI-First Interface | PASS | Feature is CLI-only; no new UI required; existing flags preserved |
32+
| V. Simplicity (YAGNI) | PASS | One new model + one builder service + prompt template changes. No new abstractions beyond what's needed. Reuses existing `IndexWriter`, `CriteriaFileReader`, `DocumentIndexReader` |
33+
34+
**Quality Gates**: All existing gates preserved. No new validation rules needed.
35+
36+
## Project Structure
37+
38+
### Documentation (this feature)
39+
40+
```text
41+
specs/044-coverage-aware-analysis/
42+
├── plan.md # This file
43+
├── research.md # Phase 0 output
44+
├── data-model.md # Phase 1 output
45+
├── contracts/ # Phase 1 output
46+
│ └── coverage-context-contract.md
47+
├── quickstart.md # Phase 1 output
48+
└── tasks.md # Phase 2 output (/speckit.tasks)
49+
```
50+
51+
### Source Code (repository root)
52+
53+
```text
54+
src/
55+
Spectra.CLI/
56+
Agent/
57+
Analysis/
58+
BehaviorAnalysisResult.cs # Existing
59+
IdentifiedBehavior.cs # Existing
60+
CoverageSnapshot.cs # NEW: model + UncoveredCriterion record
61+
CoverageSnapshotBuilder.cs # NEW: builds snapshot from index/criteria/docs
62+
CoverageContextFormatter.cs # NEW: formats snapshot for prompt injection
63+
Copilot/
64+
BehaviorAnalyzer.cs # MODIFIED: accept snapshot, inject context
65+
Commands/
66+
Generate/
67+
GenerateHandler.cs # MODIFIED: build snapshot before analysis
68+
Output/
69+
AnalysisPresenter.cs # MODIFIED: show coverage summary
70+
Progress/
71+
ProgressPageWriter.cs # MODIFIED: coverage snapshot in HTML
72+
Prompts/
73+
Content/
74+
behavior-analysis.md # MODIFIED: add {{coverage_context}} placeholder
75+
Results/
76+
GenerateResult.cs # MODIFIED: add coverage fields to GenerateAnalysis
77+
78+
Spectra.Core/
79+
# No changes — read existing data via existing readers
80+
81+
tests/
82+
Spectra.CLI.Tests/
83+
Agent/
84+
Analysis/
85+
CoverageSnapshotBuilderTests.cs # NEW: 8 tests
86+
CoverageContextFormatterTests.cs # NEW: 5 tests
87+
Commands/
88+
Generate/
89+
GenerateHandlerCoverageTests.cs # NEW: 2 integration tests
90+
Output/
91+
AnalysisPresenterCoverageTests.cs # NEW: 3 tests
92+
Results/
93+
GenerateAnalysisCoverageTests.cs # NEW: 3 tests
94+
```
95+
96+
**Structure Decision**: All new files go within the existing `Agent/Analysis/` directory (model + builder + formatter). No new project or directory structure needed — follows existing patterns exactly.
97+
98+
## Complexity Tracking
99+
100+
> No violations — all gates pass. No complexity justification needed.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Quickstart: Coverage-Aware Behavior Analysis
2+
3+
**Date**: 2026-04-13 | **Feature**: 044-coverage-aware-analysis
4+
5+
## What changed
6+
7+
The `spectra ai generate` analysis step now considers existing test coverage before recommending new tests. For mature suites, this means accurate gap-only recommendations instead of inflated counts.
8+
9+
## How to verify
10+
11+
### 1. Run analysis on an existing suite
12+
13+
```bash
14+
spectra ai generate --suite my-suite --analyze-only
15+
```
16+
17+
**Expected**: Output shows a coverage snapshot with criteria/doc coverage ratios and recommends only tests for genuine gaps.
18+
19+
### 2. Check JSON output
20+
21+
```bash
22+
spectra ai generate --suite my-suite --analyze-only --output-format json
23+
```
24+
25+
**Expected**: JSON includes `existing_test_count`, `total_criteria`, `covered_criteria`, `uncovered_criteria`, `uncovered_criteria_ids` fields.
26+
27+
### 3. Verify graceful degradation
28+
29+
```bash
30+
spectra ai generate --suite new-suite --analyze-only
31+
```
32+
33+
**Expected**: New suite with no `_index.json` produces standard analysis (no coverage section, no errors).
34+
35+
## Key files to review
36+
37+
| File | Change |
38+
|------|--------|
39+
| `src/Spectra.CLI/Agent/Analysis/CoverageSnapshot.cs` | New model |
40+
| `src/Spectra.CLI/Agent/Analysis/CoverageSnapshotBuilder.cs` | New builder |
41+
| `src/Spectra.CLI/Agent/Analysis/CoverageContextFormatter.cs` | New formatter |
42+
| `src/Spectra.CLI/Agent/Copilot/BehaviorAnalyzer.cs` | Accepts snapshot, injects context |
43+
| `src/Spectra.CLI/Commands/Generate/GenerateHandler.cs` | Builds snapshot before analysis |
44+
| `src/Spectra.CLI/Prompts/Content/behavior-analysis.md` | New `{{coverage_context}}` placeholder |
45+
| `src/Spectra.CLI/Output/AnalysisPresenter.cs` | Coverage summary display |
46+
| `src/Spectra.CLI/Results/GenerateResult.cs` | New fields on GenerateAnalysis |

0 commit comments

Comments
 (0)