debtmap 0.16.3

Code complexity and technical debt analyzer
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
# Coverage Integration

Coverage integration is one of Debtmap's most powerful capabilities, enabling **risk-based prioritization** by correlating complexity metrics with test coverage. This helps you identify truly risky code—functions that are both complex and untested—rather than just highlighting complex but well-tested functions.

## Why Coverage Matters

Without coverage data, complexity analysis shows you *what's complex*, but not *what's risky*. A complex function with 100% test coverage poses far less risk than a simple function with 0% coverage on a critical path.

Coverage integration transforms Debtmap from a complexity analyzer into a **risk assessment tool**:

- **Prioritize testing efforts**: Focus on high-complexity functions with low coverage
- **Validate refactoring safety**: See which complex code is already protected by tests
- **Risk-based sprint planning**: Surface truly risky code ahead of well-tested complexity
- **Quantify risk reduction**: Measure how coverage improvements reduce project risk

## LCOV Format: The Universal Standard

Debtmap uses the **LCOV format** for coverage data. LCOV is a language-agnostic standard supported by virtually all coverage tools across all major languages.

### Why LCOV?

- **Universal compatibility**: Works with Rust, Python, JavaScript, TypeScript, Go, and more
- **Tool independence**: Not tied to any specific test framework
- **Simple text format**: Easy to inspect and debug
- **Widely supported**: Generated by most modern coverage tools

### LCOV File Structure

An LCOV file contains line-by-line coverage information:

```lcov
SF:src/analyzer.rs
FN:42,calculate_complexity
FNDA:15,calculate_complexity
DA:42,15
DA:43,15
DA:44,12
DA:45,0
LH:3
LF:4
end_of_record
```

- `SF:` - Source file path
- `FN:` - Function name and starting line
- `FNDA:` - Function execution count
- `DA:` - Line execution data (line number, hit count)
- `LH:` - Lines hit
- `LF:` - Lines found (total)

### Rust Name Demangling

For Rust projects, Debtmap includes sophisticated name demangling to correlate LCOV coverage with analyzed functions. The demangling system handles:

**Mangling Schemes**:
- **v0 scheme**: Starts with `_RNv` (modern Rust, default since 1.38)
- **Legacy scheme**: Starts with `_ZN` (older Rust versions)

**Normalization Process** (see `src/risk/lcov/demangle.rs:demangle_function_name` and `src/risk/lcov/normalize.rs:normalize_demangled_name`):

1. **Demangle**: Convert mangled symbols to human-readable names
2. **Strip crate hashes**: Remove build-specific hash IDs (e.g., `debtmap[71f4b4990cdcf1ab]` → `debtmap`)
3. **Strip generic parameters**: Remove type parameters (e.g., `HashMap<K,V>::insert` → `HashMap::insert`)
4. **Extract method names**: Store both full path and method name for flexible matching

**Examples**:

| Original (in LCOV) | After Demangling | Normalized Full Path | Method Name |
|-------------------|------------------|---------------------|-------------|
| `_RNvXs0_14debtmap...visit_expr` | `<debtmap[hash]::Type>::visit_expr` | `debtmap::Type::visit_expr` | `visit_expr` |
| `Type::method::<T>` | `Type::method::<T>` | `Type::method` | `method` |
| `std::vec::Vec<T>::push` | `std::vec::Vec<T>::push` | `std::vec::Vec::push` | `push` |

This normalization enables Debtmap to match coverage data even when:
- Crate hashes change between builds
- Multiple monomorphizations of generic functions exist
- LCOV stores simplified names while Debtmap uses qualified names

## Generating Coverage Data

### Rust: cargo-tarpaulin

**Installation:**
```bash
cargo install cargo-tarpaulin
```

**Generate LCOV:**
```bash
cargo tarpaulin --out lcov --output-dir target/coverage
```

**Analyze with Debtmap:**
```bash
debtmap analyze . --lcov target/coverage/lcov.info
```

**Common Issues:**
- Ensure tests compile before running tarpaulin
- Use `--ignore-tests` if tests themselves show up in coverage
- Check paths match your project structure (relative to project root)

### JavaScript/TypeScript: Jest

**Configuration (package.json or jest.config.js):**
```json
{
  "jest": {
    "coverageReporters": ["lcov", "text"]
  }
}
```

**Generate Coverage:**
```bash
npm test -- --coverage
```

**Analyze with Debtmap:**
```bash
debtmap analyze . --lcov coverage/lcov.info
```

### Python: pytest-cov

**Installation:**
```bash
pip install pytest-cov
```

**Generate LCOV:**
```bash
pytest --cov=src --cov-report=lcov
```

**Analyze with Debtmap:**
```bash
debtmap analyze . --lcov coverage.lcov
```

### Go: go test with gcov2lcov

**Install gcov2lcov:**
```bash
go install github.com/jandelgado/gcov2lcov@latest
```

**Generate Coverage:**
```bash
# Generate Go coverage profile
go test -coverprofile=coverage.out ./...

# Convert to LCOV format
gcov2lcov -infile=coverage.out -outfile=coverage.lcov
```

**Analyze with Debtmap:**
```bash
debtmap analyze . --lcov coverage.lcov --languages go
```

**Note**: Go's native coverage format requires conversion to LCOV. The `gcov2lcov` tool provides direct conversion without intermediate formats.

## Role-Based Coverage Expectations

Not all functions need the same level of test coverage. Debtmap uses a **role-based coverage expectation system** to adjust scoring based on function purpose (see `src/priority/scoring/coverage_expectations.rs` and `src/risk/evidence/coverage_analyzer.rs`).

### Function Roles and Coverage Targets

| Role | Coverage Range | Rationale | Role Weight |
|------|---------------|-----------|-------------|
| **PureLogic** | 90-95% | Business logic requires comprehensive testing | 1.0 |
| **EntryPoint** | 70-80% | Better tested with integration tests | 0.9 |
| **Orchestrator** | 60-80% | Coordinates other functions, moderate complexity | 0.6 |
| **IOWrapper** | 40-60% | Thin I/O layer, often integration-tested | 0.4 |
| **PatternMatch** | 50-70% | Simple pattern matching, lower complexity | 0.3 |
| **Debug** | 20-30% | Diagnostic functions, low priority | 0.2 |
| **Unknown** | 70-90% | Default for unclassified functions | 0.8 |

**Source**: See `src/priority/semantic_classifier/mod.rs:25-32` for role definitions and `src/risk/evidence/coverage_analyzer.rs:63-73` for role weight calculation.

### Coverage Gap Severity Classification

Debtmap classifies coverage gaps into 4 severity levels (see `src/priority/scoring/coverage_expectations.rs:GapSeverity`):

| Severity | Condition | Impact on Score | Visual |
|----------|-----------|----------------|--------|
| **None** | Coverage ≥ target | No penalty | 🟢 |
| **Minor** | Coverage between min and target | Small penalty | 🟡 |
| **Moderate** | Coverage between 50% of min and min | Medium penalty | 🟠 |
| **Critical** | Coverage < 50% of min | High penalty | 🔴 |

**Example**: For `PureLogic` (target: 95%, min: 90%):
- 96% coverage → None (🟢)
- 92% coverage → Minor (🟡)
- 75% coverage → Moderate (🟠)
- 40% coverage → Critical (🔴)

### Test Quality Classification

Coverage is classified into quality tiers based on both percentage and complexity (see `src/risk/evidence/coverage_analyzer.rs:44-52`):

```rust
fn classify_test_quality(coverage: f64, complexity: u32) -> TestQuality {
    match () {
        _ if coverage >= 90.0 && complexity <= 5 => TestQuality::Excellent,
        _ if coverage >= 80.0 => TestQuality::Good,
        _ if coverage >= 60.0 => TestQuality::Adequate,
        _ if coverage > 0.0 => TestQuality::Poor,
        _ => TestQuality::Missing,
    }
}
```

**Quality Levels**:
- **Excellent**: ≥90% coverage AND complexity ≤5 (simple, well-tested)
- **Good**: ≥80% coverage (comprehensive testing)
- **Adequate**: ≥60% coverage (basic testing)
- **Poor**: >0% but <60% coverage (incomplete testing)
- **Missing**: 0% coverage (no tests)

### How Roles Affect Scoring

Role weights adjust the coverage penalty applied to functions (see `src/risk/evidence/coverage_analyzer.rs:63-73`):

**Example**: A function with 50% coverage:
- **PureLogic** (weight: 1.0): Full penalty, high urgency
- **Orchestrator** (weight: 0.6): 60% of full penalty
- **Debug** (weight: 0.2): Only 20% of full penalty, low urgency

This ensures that:
1. Business logic functions are prioritized for testing
2. Entry points rely more on integration tests
3. Diagnostic/debug functions don't create noise

## How Coverage Affects Scoring

Coverage data fundamentally changes how Debtmap calculates debt scores. The scoring system operates in **two different modes** depending on whether coverage data is available.

### Scoring Modes

**Mode 1: With Coverage Data (Dampening Multiplier)**

When you provide an LCOV file with `--lcov`, coverage acts as a **dampening multiplier** that reduces scores for well-tested code:

```
Base Score = (Complexity Factor × 0.50) + (Dependency Factor × 0.25)
Coverage Multiplier = 1.0 - coverage_percentage
Final Score = Base Score × Coverage Multiplier
```

This is the **current implementation** as of spec 122. Coverage dampens the base score rather than contributing as an additive component.

**Mode 2: Without Coverage Data (Weighted Sum)**

When no coverage data is available, Debtmap falls back to a weighted sum model:

```
Final Score = (Coverage × 0.50) + (Complexity × 0.35) + (Dependency × 0.15)
```

In this mode, coverage is assumed to be 0% (worst case), giving it a weight of 50% in the total score. See `src/priority/scoring/calculation.rs:119-129` for the implementation.

### Coverage Dampening Multiplier

When coverage data is provided, it acts as a **multiplier** that dampens the base score:

```
Coverage Multiplier = 1.0 - coverage_percentage
Final Score = Base Score × Coverage Multiplier
```

**Examples:**

| Base Score | Coverage | Multiplier | Final Score | Priority |
|-----------|----------|------------|-------------|----------|
| 8.5 | 100% | 0.0 | 0.0 | Minimal (well-tested) |
| 8.5 | 50% | 0.5 | 4.25 | Medium |
| 8.5 | 0% | 1.0 | 8.5 | High (untested) |

**Key Insight**: Complex but well-tested code automatically drops in priority, while untested complex code rises to the top.

**Special Cases:**
- **Test functions**: Coverage multiplier = 0.0 (tests get near-zero scores regardless of complexity)
- **Entry points**: Handled through semantic classification (FunctionRole) system with role multipliers, not coverage-specific weighting

**Invariant**: Total debt score with coverage ≤ total debt score without coverage.

**Implementation**: See `src/priority/scoring/calculation.rs:68-82` for the coverage dampening calculation.

## Transitive Coverage Propagation

Debtmap doesn't just look at *direct* coverage—it propagates coverage through the **call graph** using transitive analysis.

### How It Works

A function's effective coverage considers:
1. **Direct coverage**: Lines executed by tests
2. **Caller coverage**: Coverage of functions that call this function

```
Transitive Coverage = Direct Coverage + Σ(Caller Coverage × Weight)
```

### Algorithm Parameters

The transitive coverage propagation uses carefully tuned parameters to balance accuracy and performance:

- **Well-Tested Threshold**: 80% - Only functions with ≥80% direct coverage contribute to indirect coverage, ensuring high confidence
- **Distance Discount**: 70% per hop - Each level of indirection reduces contribution by 30%, reflecting decreased confidence
- **Maximum Distance**: 3 hops - Limits recursion depth to prevent exponential complexity (after 3 hops, contribution drops to ~34%)

These parameters ensure that indirect coverage signals are meaningful while preventing false confidence from distant call relationships. See `src/priority/coverage_propagation.rs:38-46` for the implementation.

### Why It Matters

A function with 0% direct coverage might have high transitive coverage if it's only called by well-tested functions:

```rust
// direct_coverage = 0%
// But called only by `process_request` (100% coverage)
// → transitive_coverage = 85%
fn validate_input(data: &str) -> bool {
    data.len() > 0
}

// direct_coverage = 100%
fn process_request(input: String) -> Result<()> {
    if !validate_input(&input) {
        return Err("Invalid");
    }
    // ...
}
```

**Effect**: `validate_input` has reduced urgency because it's only reachable through well-tested code paths.

### Generic Function Coverage (Monomorphization)

**Challenge**: Generic functions in Rust get monomorphized into multiple versions, each appearing as a separate function in LCOV with different coverage.

For example, `execute::<T>()` might appear as:
- `execute::<WorkflowExecutor>` - 70% coverage, uncovered: [10, 20, 30]
- `execute::<MockExecutor>` - 80% coverage, uncovered: [20, 40]

**Debtmap's Solution** (see `src/risk/coverage_index.rs:merge_coverage`):

1. **Base Function Index**: Maps base names to all monomorphized versions
   - `(file, "execute")` → `["execute::<WorkflowExecutor>", "execute::<MockExecutor>"]`

2. **Intersection Merge Strategy**: A line is uncovered ONLY if ALL versions leave it uncovered
   - Coverage percentage: Average across all versions (75% in example)
   - Uncovered lines: Intersection of uncovered sets ([20] in example)

3. **Conservative Approach**: Ensures we don't claim coverage that doesn't exist in all code paths

**Example Aggregation**:

| Version | Coverage | Uncovered Lines |
|---------|----------|----------------|
| `execute::<WorkflowExecutor>` | 70% | [10, 20, 30] |
| `execute::<MockExecutor>` | 80% | [20, 40] |
| **Aggregated Result** | **75%** | **[20]** |

Line 20 is uncovered in BOTH versions, so it's risky. Lines 10, 30, 40 are covered in at least one version, so they're considered safer.

**Implementation**: See `src/risk/coverage_index.rs:AggregateCoverage` and `merge_coverage` (lines 50-139).

### Trait Method Coverage Matching

**Challenge**: LCOV files may store trait method implementations with simplified names while Debtmap tracks fully qualified names.

**Example Mismatch**:
- **LCOV stores**: `visit_expr` (demangled method name)
- **Debtmap queries**: `RecursiveMatchDetector::visit_expr` (fully qualified)

**Debtmap's Solution** (see `src/risk/coverage_index.rs:generate_name_variants` and `method_name_index`):

1. **Name Variant Generation**: Extract method name from qualified paths
   - `RecursiveMatchDetector::visit_expr` → generates variant `visit_expr`

2. **Method Name Index**: O(1) lookup from method name to all implementations
   - `(file, "visit_expr")` → `["RecursiveMatchDetector::visit_expr", "_RNvXs0_...visit_expr"]`

3. **Multi-Strategy Matching**: Try variants if exact match fails
   - First: Exact qualified name match
   - Second: Method name variant match
   - Third: Line-based fallback

**Implementation**: See `src/risk/coverage_index.rs:192` (method_name_index) and `generate_name_variants` (lines 12-48).

## Performance Characteristics

Coverage integration is highly optimized for large codebases using a multi-strategy lookup system.

### Coverage Index Structure

The coverage index uses nested HashMaps plus supporting indexes for O(1) lookups (see `src/risk/coverage_index.rs:172-196`):

1. **by_file**: `HashMap<PathBuf, HashMap<String, FunctionCoverage>>` - Primary nested index
2. **by_line**: `HashMap<PathBuf, BTreeMap<usize, FunctionCoverage>>` - Line-based range queries
3. **base_function_index**: Maps base names to monomorphized versions (generic handling)
4. **method_name_index**: Maps method names to full qualified names (trait methods)

### Lookup Strategy Waterfall

Debtmap tries 5 strategies in order, stopping at the first match (see `src/risk/coverage_index.rs:get_function_coverage_with_line`):

| Strategy | Complexity | When It Matches | Typical Latency |
|----------|-----------|----------------|-----------------|
| **1. Exact Match** | O(1) | File path and function name exactly match LCOV | ~0.5μs |
| **2. Suffix Matching** | O(files) | Query path ends with LCOV file path, then O(1) function lookup | ~5-8μs |
| **3. Reverse Suffix** | O(files) | LCOV file path ends with query path, then O(1) function lookup | ~5-8μs |
| **4. Normalized Equality** | O(files) | Paths equal after normalizing `./` prefix, then O(1) function lookup | ~5-8μs |
| **5. Line-Based Fallback** | O(log n) | Match by line number ±2 tolerance using BTreeMap range query | ~10-15μs |

**Strategy Optimizations**:
- Path strategies iterate over FILES (typically ~375) not functions (~1,500+), providing 4x-50x speedup
- Each path strategy tries 3 name matching techniques per file:
  1. Exact name match
  2. Function name suffix match (handles qualified vs short names)
  3. Method name match (handles trait implementations)

### Performance Benchmarks

- **Index Build**: O(n), ~20-30ms for 5,000 functions
- **Exact Lookup**: O(1), ~0.5μs per lookup
- **Path Strategy Fallback**: O(files) × O(1), ~5-8μs when exact match fails
- **Line-Based Fallback**: O(log n), ~10-15μs when all path strategies fail
- **Memory Usage**: ~200 bytes per record (~2MB for 5,000 functions)
- **Thread Safety**: Lock-free parallel access via `Arc<CoverageIndex>`
- **Analysis Overhead**: ~2.5x baseline (target: ≤3x)

**Result**: Coverage integration adds minimal overhead even on projects with thousands of functions.

### Debugging Lookup Performance

The coverage index tracks detailed statistics for performance analysis (see `src/risk/coverage_index.rs:CoverageIndexStats`):

```rust
pub struct CoverageIndexStats {
    pub total_files: usize,
    pub total_records: usize,
    pub index_build_time: Duration,
    pub estimated_memory_bytes: usize,
}
```

Enable verbose logging to see which strategy matched:
```bash
debtmap analyze . --lcov coverage.info -vv
```

Output shows strategy attempts:
```
Looking up coverage for function 'visit_expr' in file 'src/detector.rs'
Strategy 1: Suffix matching...
  Found path match: 'src/detector.rs'
  ✓ Matched method name 'visit_expr' -> 'RecursiveMatchDetector::visit_expr': 85%
```

## CLI Options Reference

### Primary Coverage Options

```bash
# Provide LCOV coverage file
debtmap analyze . --coverage-file path/to/lcov.info

# Shorthand alias
debtmap analyze . --lcov path/to/lcov.info
```

### Context Providers

Coverage can be combined with other context providers for nuanced risk assessment:

```bash
# Enable all context providers (includes coverage propagation)
debtmap analyze . --lcov coverage.info --enable-context

# Specify specific providers
debtmap analyze . --lcov coverage.info \
  --context-providers critical_path,dependency,git_history

# Disable specific providers
debtmap analyze . --lcov coverage.info \
  --disable-context git_history
```

**Available Context Providers**:
- `critical_path`: Identifies functions on critical execution paths
- `dependency`: Analyzes dependency relationships and impact
- `git_history`: Uses change frequency from version control

See [Scoring Strategies](scoring-strategies.md) for details on how these combine.

### Validate Command Support

The `validate` command also supports coverage integration for risk-based quality gates:

```bash
# Fail CI builds if untested complex code exceeds thresholds
debtmap validate . --lcov coverage.info --max-debt-density 50
```

See [CLI Reference](cli-reference.md) for complete validation options.

## Troubleshooting Coverage Integration

### Coverage Not Correlating with Functions

**Symptoms**:
- Debtmap shows 0% coverage for all functions
- Warning: "No coverage data correlated with analyzed functions"

**Solutions**:

1. **Verify LCOV Format**:
```bash
head coverage.info
# Should show: SF:, FN:, DA: lines
```

2. **Check Path Matching**:
Coverage file paths must be relative to project root:
```bash
# Good: SF:src/analyzer.rs
# Bad:  SF:/home/user/project/src/analyzer.rs
```

3. **Use explain-coverage Command**:
```bash
debtmap explain-coverage . --lcov coverage.info \
  --function validate_input \
  --file src/validator.rs \
  --format json
```

The `explain-coverage` command provides detailed diagnostics:

**JSON Output Structure** (see `src/commands/explain_coverage.rs:ExplainCoverageResult`):
```json
{
  "function_name": "validate_input",
  "file_path": "src/validator.rs",
  "coverage_found": true,
  "coverage_percentage": 85.0,
  "matched_by_strategy": "Suffix Matching",
  "attempts": [
    {
      "strategy": "Exact Match",
      "success": false,
      "matched_function": null,
      "coverage_percentage": null
    },
    {
      "strategy": "Suffix Matching",
      "success": true,
      "matched_function": "validator::validate_input",
      "matched_file": "src/validator.rs",
      "coverage_percentage": 85.0
    }
  ],
  "available_functions": [
    "src/validator.rs::validate_input",
    "src/processor.rs::process_request"
  ],
  "available_files": [
    "src/validator.rs",
    "src/processor.rs"
  ]
}
```

**Key Fields**:
- `attempts[]`: Shows all 5 strategies tried and which succeeded
- `available_functions[]`: All functions found in LCOV (helps identify naming mismatches)
- `available_files[]`: All files in LCOV (helps debug path issues)

4. **Enable Verbose Logging**:
```bash
debtmap analyze . --lcov coverage.info -vv
```
This shows coverage lookup details for each function during analysis.

5. **Verify Coverage Tool Output**:
```bash
# Ensure your coverage tool generated line data (DA: records)
grep "^DA:" coverage.info | head
```

### Functions Still Show Up Despite 100% Coverage

**This is expected behavior** when:
- Function has high complexity (cyclomatic > 10)
- Function has other debt issues (duplication, nesting, etc.)
- You're viewing function-level output (coverage dampens but doesn't eliminate)

**Coverage reduces priority but doesn't hide issues**. Use filters to focus:
```bash
# Show only critical and high priority items
debtmap analyze . --lcov coverage.info --min-priority high

# Show top 10 most urgent items
debtmap analyze . --lcov coverage.info --top 10
```

### Coverage File Path Issues

**Problem**: Can't find coverage file

**Solutions**:
```bash
# Use absolute path
debtmap analyze . --lcov /absolute/path/to/coverage.info

# Or ensure relative path is from project root
debtmap analyze . --lcov ./target/coverage/lcov.info
```

### LCOV Format Errors

**Problem**: "Invalid LCOV format" error

**Causes**:
- Non-LCOV format (Cobertura XML, JaCoCo, etc.)
- Corrupted file
- Wrong file encoding

**Solutions**:
- Verify your coverage tool is configured for LCOV output
- Check for binary/encoding issues: `file coverage.info`
- Regenerate coverage with explicit LCOV format flag

See [Troubleshooting](troubleshooting.md) for more debugging tips.

## Best Practices

### Analysis Workflow

1. **Generate Coverage Before Analysis**:
   ```bash
   # Rust example
   cargo tarpaulin --out lcov --output-dir target/coverage
   debtmap analyze . --lcov target/coverage/lcov.info
   ```

2. **Use Coverage for Sprint Planning**:
   ```bash
   # Focus on untested complex code
   debtmap analyze . --lcov coverage.info --top 20
   ```

3. **Combine with Tiered Prioritization**:
   Coverage automatically feeds into [Tiered Prioritization](tiered-prioritization.md):
   - **Tier 1**: Architectural issues (less affected by coverage)
   - **Tier 2**: Complex untested code (coverage < 50%, complexity > 15)
   - **Tier 3**: Testing gaps (coverage < 80%, complexity 10-15)

4. **Validate Refactoring Impact**:
   ```bash
   # Before refactoring
   debtmap analyze . --lcov coverage-before.info -o before.json

   # After refactoring
   debtmap analyze . --lcov coverage-after.info -o after.json

   # Compare
   debtmap compare --before before.json --after after.json
   ```

### Testing Strategy

**Prioritize testing based on risk**:

1. **High Complexity + Low Coverage = Highest Priority**:
   ```bash
   debtmap analyze . --lcov coverage.info \
     --filter Risk --min-priority high
   ```

2. **Focus on Business Logic**:
   Entry points and infrastructure code have natural coverage patterns. Focus unit tests on business logic functions.

3. **Use Dependency Analysis**:
   ```bash
   debtmap analyze . --lcov coverage.info \
     --context-providers dependency -vv
   ```
   Tests high-dependency functions first—they have the most impact.

4. **Don't Over-Test Entry Points**:
   Entry points (main, handlers) are better tested with integration tests, not unit tests. Debtmap applies role multipliers through its semantic classification system (FunctionRole) to adjust scoring for different function types. See `src/priority/unified_scorer.rs:149` and `src/priority/scoring/classification.rs` for the classification system.

### Configuration

In `.debtmap.toml`:

```toml
[scoring]
# Default weights for scoring WITHOUT coverage data
# When coverage data IS provided, it acts as a dampening multiplier instead
coverage = 0.50  # Default: 50% (only used when no LCOV provided)
complexity = 0.35  # Default: 35%
dependency = 0.15  # Default: 15%

[thresholds]
# Set minimum risk score to filter low-priority items
minimum_risk_score = 15.0

# Skip simple functions even if uncovered
minimum_cyclomatic_complexity = 5
```

**Important**: These weights are from the deprecated additive scoring model. The current implementation (spec 122) calculates a base score from complexity (50%) and dependency (25%) factors, then applies coverage as a dampening multiplier: `Final Score = Base Score × (1.0 - coverage_pct)`. These weights only apply when coverage data is **not** available. See `src/priority/scoring/calculation.rs:68-82` for the coverage dampening calculation and `src/priority/scoring/calculation.rs:119-129` for the fallback weighted sum mode.

See [Configuration](configuration.md) for complete options.

### CI Integration

**Example GitHub Actions Workflow**:

```yaml
- name: Generate Coverage
  run: cargo tarpaulin --out lcov --output-dir target/coverage

- name: Analyze with Debtmap
  run: |
    debtmap analyze . \
      --lcov target/coverage/lcov.info \
      --format json \
      --output debtmap-report.json

- name: Validate Quality Gates
  run: |
    debtmap validate . \
      --lcov target/coverage/lcov.info \
      --max-debt-density 50
```

**Quality Gate Strategy**:
- Fail builds on new critical debt (Tier 1 architectural issues)
- Warn on new high-priority untested code (Tier 2)
- Track coverage trends over time with `compare` command

## Complete Language Examples

### Rust End-to-End

```bash
# 1. Generate coverage
cargo tarpaulin --out lcov --output-dir target/coverage

# 2. Verify LCOV output
head target/coverage/lcov.info

# 3. Run Debtmap with coverage
debtmap analyze . --lcov target/coverage/lcov.info

# 4. Interpret results (look for [UNTESTED] markers on high-complexity functions)
```

### JavaScript/TypeScript End-to-End

```bash
# 1. Configure Jest for LCOV (in package.json or jest.config.js)
# "coverageReporters": ["lcov", "text"]

# 2. Generate coverage
npm test -- --coverage

# 3. Verify LCOV output
head coverage/lcov.info

# 4. Run Debtmap
debtmap analyze . --lcov coverage/lcov.info --languages javascript,typescript
```

### Python End-to-End

```bash
# 1. Install pytest-cov
pip install pytest-cov

# 2. Generate LCOV coverage
pytest --cov=src --cov-report=lcov

# 3. Verify output
head coverage.lcov

# 4. Run Debtmap
debtmap analyze . --lcov coverage.lcov --languages python
```

### Go End-to-End

```bash
# 1. Install gcov2lcov (one-time setup)
go install github.com/jandelgado/gcov2lcov@latest

# 2. Generate coverage
go test -coverprofile=coverage.out ./...

# 3. Convert to LCOV
gcov2lcov -infile=coverage.out -outfile=coverage.lcov

# 4. Verify LCOV output
head coverage.lcov

# 5. Run Debtmap
debtmap analyze . --lcov coverage.lcov --languages go
```

## FAQ

### Why does my 100% covered function still show up?

Coverage dampens debt scores but doesn't eliminate debt. A function with cyclomatic complexity 25 and 100% coverage still represents technical debt—it's just lower priority than untested complex code.

**Use filters to focus on high-priority items**:
```bash
debtmap analyze . --lcov coverage.info --top 10
```

### What's the difference between direct and transitive coverage?

- **Direct coverage**: Lines executed directly by tests
- **Transitive coverage**: Coverage considering call graph (functions called by well-tested code)

Transitive coverage reduces urgency for functions only reachable through well-tested paths.

### Should I test everything to 100% coverage?

**No.** Use Debtmap's risk scores to prioritize:
1. Test high-complexity, low-coverage functions first
2. Entry points are better tested with integration tests
3. Simple utility functions (complexity < 5) may not need dedicated unit tests

Debtmap helps you achieve **optimal coverage**, not maximal coverage.

### How do I debug coverage correlation issues?

Use verbose logging:
```bash
debtmap analyze . --lcov coverage.info -vv
```

This shows:
- Coverage file parsing details
- Function-to-coverage correlation attempts
- Path matching diagnostics

### Can I use coverage with validate command?

Yes! The `validate` command supports `--lcov` for risk-based quality gates:
```bash
debtmap validate . --lcov coverage.info --max-debt-density 50
```

See [CLI Reference](cli-reference.md#validate-command) for details.

## Further Reading

- [Scoring Strategies](scoring-strategies.md) - Deep dive into how coverage affects unified scoring
- [Tiered Prioritization](tiered-prioritization.md) - How coverage fits into tiered priority levels
- [CLI Reference](cli-reference.md) - Complete coverage option documentation
- [Configuration](configuration.md) - Customizing coverage scoring weights
- [Troubleshooting](troubleshooting.md) - More debugging tips for coverage issues