Skip to content

Commit 72c932e

Browse files
Merge branch '044-coverage-aware-analysis' into main
2 parents 7c09e30 + 5167c70 commit 72c932e

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)