Skill: athola/nm-conserve-bloat-detector (version 1.0.2)

--- name: bloat-detector description: | Detect codebase bloat via progressive analysis: dead code, duplication, complexity, and doc bloat version: 1.9.5 triggers: - bloat - cleanup - static-analysis - technical-debt - optimization metadata: {"openclaw": {"homepage": "https://github.com/athola/claude-night-market/tree/master/plugins/conserve", "emoji": "\ud83e\udd9e"}} source: claude-night-market source_plugin: conserve --- > **Night Market Skill** — ported from [claude-night-market/conserve](https://github.com/athola/claude-night-market/tree/master/plugins/conserve). For the full experience with agents, hooks, and commands, install the Claude Code plugin. ## Table of Contents - [Bloat Categories](#bloat-categories) - [Quick Start](#quick-start) - [When to Use](#when-to-use) - [Confidence Levels](#confidence-levels) - [Prioritization](#prioritization) - [Module Architecture](#module-architecture) - [Safety](#safety) # Bloat Detector Systematically detect and eliminate codebase bloat through progressive analysis tiers. ## Bloat Categories | Category | Examples | |----------|----------| | **Code** | Dead code, God classes, Lava flow, duplication | | **AI-Generated** | Tab-completion bloat, vibe coding, hallucinated deps | | **Documentation** | Redundancy, verbosity, stale content, slop | | **Dependencies** | Unused imports, dependency bloat, phantom packages | | **Git History** | Stale files, low-churn code, massive single commits | ## Quick Start ### Tier 1: Quick Scan (2-5 min, no tools) ```bash /bloat-scan ``` Detects: Large files, stale code, old TODOs, commented blocks, basic duplication ### Tier 2: Targeted Analysis (10-20 min, optional tools) ```bash /bloat-scan --level 2 --focus code # or docs, deps ``` Adds: Static analysis (Vulture/Knip), git churn hotspots, doc similarity ### Tier 3: Deep Audit (30-60 min, full tooling) ```bash /bloat-scan --level 3 --report audit.md ``` Adds: Cross-file redundancy, dependency graphs, readability metrics ## When To Use | Do | Don't | |----|-------| | Context usage > 30% | Active feature development | | Quarterly maintenance | Time-sensitive bugs | | Pre-release cleanup | Codebase < 1000 lines | | Before major refactoring | Tools unavailable (Tier 2/3) | ## When NOT To Use - Active feature development - Time-sensitive bugs - Codebase < 1000 lines ## Confidence Levels | Level | Confidence | Action | |-------|------------|--------| | HIGH | 90-100% | Safe to remove | | MEDIUM | 70-89% | Review first | | LOW | 50-69% | Investigate | ## Prioritization ``` Priority = (Token_Savings × 0.4) + (Maintenance × 0.3) + (Confidence × 0.2) + (Ease × 0.1) ``` ## Module Architecture **Tier 1** (always available): - See `modules/quick-scan.md` - Heuristics, no tools - See `modules/git-history-analysis.md` - Staleness, churn, vibe coding signatures - See `modules/growth-analysis.md` - Growth velocity, forecasts, threshold alerts **Tier 2** (optional tools): - See `modules/code-bloat-patterns.md` - Anti-patterns (God class, Lava flow) - See `modules/ai-generated-bloat.md` - AI-specific patterns (Tab bloat, hallucinations) - See `modules/documentation-bloat.md` - Redundancy, readability, slop detection - See `modules/static-analysis-integration.md` - Vulture, Knip **Shared**: - See `modules/remediation-types.md` - DELETE, REFACTOR, CONSOLIDATE, ARCHIVE ## Auto-Exclusions Always excludes: `.venv`, `__pycache__`, `.git`, `node_modules`, `dist`, `build`, `vendor` Also respects: `.gitignore`, `.bloat-ignore` ## Safety - **Never auto-delete** - all changes require approval - **Dry-run support** - `--dry-run` for previews - **Backup branches** - created before bulk changes ## Related - `bloat-auditor` agent - Executes scans - `unbloat-remediator` agent - Safe remediation - `context-optimization` skill - MECW principles

path: modules/ai-generated-bloat.md
content: ---
module: ai-generated-bloat
category: tier-2
dependencies: [Bash, Grep, Read]
estimated_tokens: 200
---

# AI-Generated Bloat Detection Module

Detect bloat patterns specific to AI-assisted coding: vibe coding artifacts, slop patterns, and agent psychosis indicators.

## Why This Module Exists

AI coding has created qualitatively different bloat than traditional development:
- **2024**: First year copy/pasted lines exceeded refactored lines (GitClear)
- **Refactoring**: Dropped from 25% (2021) to <10% (2024), predicted 3% (2025)
- **Duplication**: 8x increase in 5+ line code blocks

## AI Bloat Patterns

### 1. Tab-Completion Bloat (Repetitive Logic)

**Definition**: Same pattern repeated 3+ times instead of abstracted into shared function.

```bash
# Detect similar code blocks (built-in, no external deps)
python3 plugins/conserve/scripts/detect_duplicates.py . --min-lines 5

# JSON output for CI integration
python3 plugins/conserve/scripts/detect_duplicates.py . --format json --threshold 15

# Heuristic: functions with near-identical signatures
grep -rn "^def " --include="*.py" . | cut -d: -f2 | sort | uniq -c | sort -rn | head -10
```

**Confidence**: HIGH (85%)
**Action**: REFACTOR - extract to shared utility
**Rationale**: AI suggests new implementations rather than reusing existing code

### 2. Massive Single Commits (Vibe Coding Signature)

**Definition**: Commits with >500 insertions, especially without proportional tests.

```bash
# Find vibe coding commits
git log --oneline --shortstat | grep -E "[0-9]{3,} insertion" | head -20

# Commits with high insertion:deletion ratio (adding without cleanup)
git log --shortstat --pretty=format:"%h %s" | awk '/insertion|deletion/ {
  ins=$4; del=$6;
  if (ins > 200 && (del == "" || ins/del > 10)) print prev, ins, del
} {prev=$0}'
```

**Confidence**: MEDIUM (70%)
**Action**: INVESTIGATE - review for understanding gaps
**Rationale**: Large additions without refactoring indicate Tab-driven development

### 3. Hallucinated Dependencies

**Definition**: Imports referencing non-existent packages (AI hallucination).

```bash
# Python: Check for uninstallable packages
pip freeze > /tmp/installed.txt
grep -rh "^import \|^from " --include="*.py" . | \
  sed 's/^import //;s/^from //;s/ import.*//' | \
  sort -u | while read pkg; do
    root=$(echo $pkg | cut -d. -f1)
    grep -q "^$root" /tmp/installed.txt || echo "HALLUCINATED?: $pkg"
  done

# JavaScript: Check for phantom packages
jq -r '.dependencies // {} | keys[]' package.json | while read pkg; do
  npm view $pkg version 2>/dev/null || echo "HALLUCINATED?: $pkg"
done
```

**Confidence**: HIGH (95%)
**Action**: DELETE or REPLACE
**Rationale**: AI invents plausible-sounding packages (slopsquatting risk)

### 4. Happy Path Only (Test Coverage Gap)

**Definition**: Code >200 lines with no corresponding tests, or tests without error assertions.

```bash
# Files without test coverage
find . -name "*.py" ! -path "*/test*" \
  -not -path "*/.venv/*" -not -path "*/__pycache__/*" \
  -not -path "*/node_modules/*" -not -path "*/.git/*" \
  -exec sh -c '
  lines=$(wc -l < "$1")
  if [ $lines -gt 200 ]; then
    base=$(basename "$1" .py)
    test_exists=$(find . -name "test_${base}.py" -o -name "${base}_test.py" \
      -not -path "*/.venv/*" -not -path "*/__pycache__/*" \
      -not -path "*/node_modules/*" -not -path "*/.git/*" | head -1)
    [ -z "$test_exists" ] && echo "UNTESTED ($lines lines): $1"
  fi
' _ {} \;

# Tests without error/exception assertions
grep -rL "assert.*Error\|assert.*Exception\|pytest.raises\|with self.assertRaises" \
  --include="test_*.py" .
```

**Confidence**: HIGH (90%)
**Action**: AUGMENT_TESTS before adding more code
**Rationale**: AI generates happy path; errors require human insight

### 5. Premature Abstraction

**Definition**: Base classes/interfaces with only 1-2 implementations.

```bash
# Python: Abstract classes with single inheritor
grep -rn "class.*ABC\|@abstractmethod" --include="*.py" . | cut -d: -f1 | sort -u | while read f; do
  class=$(grep -oP "class \K\w+" "$f" | head -1)
  inheritors=$(grep -rn "($class)" --include="*.py" . | wc -l)
  [ $inheritors -lt 2 ] && echo "PREMATURE: $class in $f (${inheritors} inheritors)"
done
```

**Confidence**: HIGH (85%)
**Action**: INLINE - remove abstraction until 3rd use case
**Rationale**: AI suggests "scalable" patterns for simple problems

### 6. Enterprise Cosplay

**Definition**: Microservices, Kubernetes, complex architecture for simple applications.

```bash
# Docker complexity for simple apps
if [ -f docker-compose.yml ]; then
  services=$(grep -c "^  [a-z].*:$" docker-compose.yml)
  code_lines=$(find . \( -name "*.py" -o -name "*.js" \) \
    -not -path "*/.venv/*" -not -path "*/__pycache__/*" \
    -not -path "*/node_modules/*" -not -path "*/.git/*" | xargs wc -l 2>/dev/null | tail -1 | awk '{print $1}')
  ratio=$((code_lines / services))
  [ $ratio -lt 500 ] && echo "ENTERPRISE_COSPLAY: $services services for $code_lines lines"
fi

# Kubernetes for CRUD
[ -d k8s ] && [ $(find . -name "*.py" -not -path "*/.venv/*" -not -path "*/__pycache__/*" -not -path "*/node_modules/*" -not -path "*/.git/*" | xargs wc -l | tail -1 | awk '{print $1}') -lt 5000 ] && \
  echo "ENTERPRISE_COSPLAY: Kubernetes for <5000 lines"
```

**Confidence**: MEDIUM (70%)
**Action**: SIMPLIFY - evaluate if complexity is justified
**Rationale**: AI defaults to "production-ready" patterns without context

### 7. Documentation Slop

**Definition**: AI-generated docs with excessive hedging, formulaic structure, surface insights.

```bash
# Hedge word density (AI slop indicators)
hedge_words="worth noting|arguably|to some extent|it's important|consider that|generally speaking"
for f in $(find . -name "*.md" -not -path "*/.venv/*" -not -path "*/node_modules/*" -not -path "*/.git/*"); do
  total=$(wc -w < "$f")
  hedges=$(grep -oiE "$hedge_words" "$f" | wc -l)
  if [ $total -gt 100 ]; then
    density=$((hedges * 1000 / total))
    [ $density -gt 20 ] && echo "DOC_SLOP ($density/1000): $f"
  fi
done
```

**Confidence**: MEDIUM (65%)
**Action**: REWRITE with concrete specifics
**Rationale**: AI safety training creates artificial hedging

## Scoring

```python
AI_BLOAT_SCORES = {
    'tab_completion_bloat': 25,
    'massive_single_commit': 15,
    'hallucinated_dependency': 35,
    'happy_path_only': 30,
    'premature_abstraction': 20,
    'enterprise_cosplay': 25,
    'documentation_slop': 10,
}

def ai_bloat_score(detected_patterns):
    return min(100, sum(AI_BLOAT_SCORES.get(p, 0) for p in detected_patterns))
```

## Integration with Existing Tiers

**Tier 1 (Quick Scan)**: Massive single commits, hedge word density
**Tier 2 (Targeted)**: Duplication ratio, test coverage gaps, premature abstraction
**Tier 3 (Deep Audit)**: Hallucinated dependencies, enterprise cosplay analysis

## Output Format

```yaml
file: src/services/user_manager.py
ai_bloat_patterns:
  - tab_completion_bloat
  - happy_path_only
ai_bloat_score: 55/100
indicators:
  similar_blocks: 4
  test_coverage: 0%
  commit_size: 847 lines
confidence: HIGH
action: REFACTOR + ADD_TESTS
rationale: "Vibe coding signature - large addition without tests or abstraction"
```

## Prevention Recommendations

When AI bloat is detected, recommend:

1. **Refactoring Budget**: Add 25 lines of refactoring for every 100 lines added
2. **Test Requirement**: No merge without proportional test coverage
3. **Understanding Gate**: Require explanation of non-trivial changes
4. **24-Hour Rule**: Sleep before adopting new AI-suggested patterns

## Related

- `code-bloat-patterns` - Traditional anti-patterns (God class, Lava flow)
- `documentation-bloat` - Readability metrics
- `imbue:anti-cargo-cult` - Understanding verification protocol
- Knowledge corpus: `agent-psychosis-codebase-hygiene.md`


path: modules/code-bloat-patterns.md
content: ---
module: code-bloat-patterns
category: tier-2
dependencies: [Bash, Grep, Read]
estimated_tokens: 150
---

# Code Bloat Patterns Module

Detect anti-patterns using pattern recognition and heuristics. Works without external tools.

> **Tool Preference (Claude Code 2.1.31+)**: The bash snippets in this module are reference implementations for external script execution or CI pipelines. When performing these analyses directly within Claude Code, prefer native tools: use Grep instead of `grep`, Glob instead of `find`, and Read instead of `cat`/`sed`.

## Anti-Patterns

### 1. God Class
**Definition:** Single class with > 500 lines, > 10 methods, multiple responsibilities.

```bash
# Quick detection
find . -name "*.py" \
  -not -path "*/.venv/*" -not -path "*/__pycache__/*" \
  -not -path "*/node_modules/*" -not -path "*/.git/*" \
  -exec sh -c 'lines=$(wc -l < "$1"); [ $lines -gt 500 ] && echo "GOD_CLASS: $1 - $lines lines"' _ {} \;
```
**Confidence:** HIGH (85%) | **Action:** REFACTOR into focused modules

### 2. Lava Flow
**Definition:** Ancient untouched code - commented blocks, old TODOs.

```bash
# Find files with >20% commented code
grep -rn "^#\|^//" --include="*.py" . | cut -d: -f1 | sort | uniq -c | sort -rn | head -10
```
**Confidence:** HIGH (90%) | **Action:** DELETE commented code

### 3. Dead Code
**Detection:** Use static analysis (Vulture/Knip) or fallback heuristic:
```bash
# Heuristic: find functions with 0 calls
grep -rn "^def " --include="*.py" . | while read line; do
  func=$(echo $line | awk '{print $2}' | cut -d'(' -f1)
  [ $(git grep -c "$func(" 2>/dev/null || echo 0) -eq 1 ] && echo "DEAD: $func"
done
```
**Confidence:** MEDIUM (70%) heuristic, HIGH (90%) with tools | **Action:** DELETE

### 4. Import Bloat
```bash
# Star imports (block tree-shaking)
grep -rn "^from .* import \*" --include="*.py" .

# Unused imports (requires autoflake)
autoflake --check --remove-all-unused-imports -r .
```
**Confidence:** HIGH (95%) | **Action:** Fix imports

### 5. Duplication
**Intra-file:** Hash-based block detection (5+ line matches)
**Cross-file:** Function signature matching
**Semantic:** AST comparison (80%+ similarity)

**Confidence:** HIGH (85%) | **Action:** EXTRACT to shared utility

## Language-Specific

### Python
- Circular imports: Files with 20+ imports
- Deep nesting: > 4 indentation levels

### JavaScript/TypeScript
- Barrel files: `export * from` breaks tree-shaking
- CommonJS in ESM: `module.exports`/`require()` blocks bundler optimization

## AI-Amplified Patterns

These traditional patterns are amplified by AI coding tools:

### 6. Tab-Completion Duplication
**Definition:** AI suggests similar code blocks instead of reusing existing functions.
**2024 Data:** 8x increase in 5+ line duplicated blocks (GitClear)

```bash
# Quick detection: near-identical function signatures
grep -rn "^def " --include="*.py" . | awk -F'def ' '{print $2}' | \
  cut -d'(' -f1 | sort | uniq -c | sort -rn | awk '$1 > 1'
```
**Confidence:** HIGH (85%) | **Action:** EXTRACT shared utility

### 7. Dead Wrapper / Facade Bloat
**Definition:** Modules that wrap existing functionality without adding meaningful logic — thin facades, unused service interfaces, or re-export layers with no consumers.

**Signals:**
- File imports from another internal module and re-exports similar API
- No external imports of the wrapper (0 refs from outside itself)
- Not a proper package (missing `__init__.py` for Python)
- Docstring examples show imports but no actual code uses them
- Functionality already exists in the wrapped module or in `examples/`

```bash
# Find Python files that only re-export from other internal modules
for f in $(find . -name "*.py" -not -path "*/test*" -not -path "*/__pycache__/*" -not -path "*/.venv/*" -not -path "*/node_modules/*" -not -path "*/.git/*"); do
  # Check if file mostly imports and re-calls another module's functions
  imports=$(grep -c "^from \.\." "$f" 2>/dev/null || echo 0)
  total=$(wc -l < "$f" 2>/dev/null || echo 0)
  refs=$(git grep -l "$(basename "$f" .py)" -- "*.py" 2>/dev/null | grep -v "$f" | wc -l)
  if [ "$imports" -gt 2 ] && [ "$refs" -eq 0 ] && [ "$total" -gt 50 ]; then
    echo "DEAD_WRAPPER: $f ($total lines, $imports internal imports, 0 external refs)"
  fi
done
```

**Also check for intra-file dead wrappers:**
```bash
# Find classes/functions that only delegate to another method with no transformation
grep -rn "def .*self" --include="*.py" . | while read line; do
  file=$(echo "$line" | cut -d: -f1)
  lineno=$(echo "$line" | cut -d: -f2)
  # Check if function body is just "return self.other_thing(...)"
  body=$(sed -n "$((lineno+1)),$((lineno+3))p" "$file" 2>/dev/null)
  if echo "$body" | grep -qP '^\s+return self\.\w+\(' && [ $(echo "$body" | wc -l) -le 2 ]; then
    echo "PASSTHROUGH: $file:$lineno - trivial delegation"
  fi
done
```

**Confidence:** HIGH (85%) for whole-file wrappers, MEDIUM (70%) for intra-file passthrough
**Action:** DELETE (whole-file) or INLINE (intra-file passthrough)

### 8. Premature Abstraction
**Definition:** Base classes/interfaces with <3 implementations (YAGNI violation).
**AI Cause:** AI defaults to "scalable" patterns without context.

```bash
# Find abstract classes with few inheritors
grep -rln "ABC\|abstractmethod" --include="*.py" . | while read f; do
  class=$(grep -oP "class \K\w+" "$f" | head -1)
  [ $(grep -rc "($class)" --include="*.py" . 2>/dev/null) -lt 3 ] && echo "PREMATURE: $class"
done
```
**Confidence:** HIGH (80%) | **Action:** INLINE until 3rd use case

### 9. Happy Path Bias
**Definition:** Tests verify success paths only; no error handling tested.
**AI Cause:** AI optimizes for "works" demonstrations.

```bash
# Tests without error assertions
grep -rL "Error\|Exception\|raises\|fail\|invalid" --include="test_*.py" .
```
**Confidence:** MEDIUM (70%) | **Action:** ADD error path tests

For comprehensive AI-specific patterns, see: `@module:ai-generated-bloat`

## Scoring

```python
PATTERN_SCORES = {
    'god_class': 30, 'lava_flow': 25, 'dead_code': 35,
    'import_bloat': 15, 'duplication': 20, 'dead_wrapper': 30
}
score = min(100, sum(PATTERN_SCORES[p] for p in detected))
```

## Output Format

```yaml
file: src/legacy/manager.py
patterns: [god_class, lava_flow, import_bloat]
bloat_score: 85/100
confidence: HIGH
token_estimate: ~3,400
action: REFACTOR
```

All actions require user approval.


path: modules/documentation-bloat.md
content: ---
module: documentation-bloat
category: tier-2
dependencies: [Bash, Grep, Read]
estimated_tokens: 120
---

# Documentation Bloat Module

Detect documentation redundancy, verbosity, and poor readability.

## Detection Categories

### 1. Duplicate Documentation

#### Cross-File (Jaccard Similarity)
```bash
# Quick similarity check between two files
words1=$(tr '[:space:]' '\n' < file1.md | sort -u)
words2=$(tr '[:space:]' '\n' < file2.md | sort -u)
# > 70% overlap = potential duplication
```

| Similarity | Confidence | Action |
|------------|------------|--------|
| > 90% | HIGH (95%) | DELETE one, keep recent |
| 70-90% | MEDIUM (80%) | MERGE, preserve unique |
| 50-70% | LOW (60%) | CROSS-LINK |

#### Intra-File (Section Hashing)
Hash each `##` section's normalized content. Duplicates = repeated sections.

**Confidence:** HIGH (85%)

### 2. Excessive Verbosity

| Metric | Threshold | Action |
|--------|-----------|--------|
| Word count | > 500 words/section | Condense |
| Sentence length | > 25 words avg | Simplify |
| Passive voice | > 30% | Rewrite active |
| Readability | Flesch < 40 | Simplify |

```bash
# Quick verbosity check
wc -w file.md  # Total words
rg -c '\.' file.md  # Approximate sentences (or grep -c)
```

### 3. Stale Documentation

| Signal | Confidence | Action |
|--------|------------|--------|
| Unchanged 12+ months | HIGH (85%) | Review/Archive |
| References deleted code | HIGH (90%) | Update/Delete |
| No git activity | MEDIUM (75%) | Investigate |

```bash
# Find stale docs
git log -1 --format="%ar" -- docs/*.md | rg -E "year|months"
# fallback: grep -E "year|months"
```

### 4. Missing/Outdated References

- Broken internal links: `rg -oP '\[.*?\]\((?!http).*?\)' *.md` (or `grep -oP`)
- References to deleted files
- Outdated API examples

**Confidence:** HIGH (90%) for broken links

## Scoring

```python
def doc_bloat_score(metrics):
    score = 0
    if metrics['duplicate_ratio'] > 0.3: score += 30
    if metrics['avg_words_per_section'] > 500: score += 20
    if metrics['readability'] < 40: score += 15
    if metrics['stale_months'] > 12: score += 25
    return min(100, score)
```

## Output Format

```yaml
file: docs/old-guide.md
bloat_type: [duplicate, verbose, stale]
bloat_score: 72/100
confidence: HIGH
token_estimate: ~1,200
similar_to: docs/guide.md (87%)
action: MERGE
```

## Related
- `quick-scan` - Tier 1 stale detection
- `git-history-analysis` - Activity signals


path: modules/git-history-analysis.md
content: ---
module: git-history-analysis
category: tier-1
dependencies: [Bash, Grep]
estimated_tokens: 250
---

# Git History Analysis Module

Detect bloat using git history: staleness, churn metrics, and reference counting.

## Core Techniques

### 1. Staleness Detection

**Command:**
```bash
# Files not modified in last 6 months
git log --since="6 months ago" --name-only --pretty=format: | sort -u > recent.txt
comm -13 recent.txt <(git ls-files | sort) > stale_files.txt
```

**Staleness Scoring:**
```python
def staleness_score(months_since_change):
    if months_since_change > 24:
        return 95  # Almost certainly abandoned
    elif months_since_change > 12:
        return 85  # Likely abandoned
    elif months_since_change > 6:
        return 65  # Possibly stale
    else:
        return 20  # Active
```

**Confidence Modifiers:**
- File type: Config files -20%, code files +0%
- Last author: If single author who left project +15%
- Dependencies: If no imports found +25%

### 2. Reference Counting

**Detect unused files:**
```bash
# For each file, count references in codebase
git ls-files | while read file; do
  filename=$(basename "$file")
  refs=$(git grep -l "$filename" | wc -l)
  if [ $refs -eq 1 ]; then  # Only self-reference
    echo "0 $file"
  else
    echo "$((refs - 1)) $file"  # Subtract self
  fi
done | grep "^0 "
```

**Confidence:** HIGH (90%) if zero refs + stale

**False Positives:**
- Entry points (main.py, index.js)
- Configuration files
- Documentation

### 3. Code Churn Metrics

**Churn formula:**
```bash
# Lines added + deleted per file
git log --numstat --pretty="%H" -- $file | \
  awk '{added+=$1; deleted+=$2} END {print added+deleted}'
```

**Churn Categories:**
- **High churn (>1000 changes/year)**: Active development
- **Low churn (<50 changes/year)**: Stable or abandoned
- **Zero churn + old**: Strong bloat signal

**Hotspot Detection:**
```python
def is_hotspot(churn, complexity):
    """
    Hotspot = High churn × High complexity
    Indicates technical debt accumulation
    """
    churn_score = normalize_churn(churn)
    complexity_score = cyclomatic_complexity(file)
    return churn_score * complexity_score > threshold
```

### 4. Ownership Analysis

**Detect abandoned code:**
```bash
# Find files where primary author has no recent commits
git log --format="%an" --since="6 months ago" | sort -u > active_authors.txt

git ls-files | while read file; do
  primary_author=$(git log --format="%an" -- "$file" | sort | uniq -c | sort -rn | head -1 | awk '{$1=""; print $0}' | sed 's/^ //')
  if ! grep -qF "$primary_author" active_authors.txt; then
    echo "$file - Primary author inactive: $primary_author"
  fi
done
```

**Confidence:** MEDIUM (70%) - Ownership transfer is possible

### 5. Branch Analysis

**Detect orphaned feature branches:**
```bash
# Branches not merged in 6+ months
git for-each-ref --sort=-committerdate refs/heads/ --format='%(committerdate:short) %(refname:short)' | \
  while read date branch; do
    age_days=$(( ($(date +%s) - $(date -d "$date" +%s)) / 86400 ))
    if [ $age_days -gt 180 ]; then
      echo "$branch - ${age_days} days old"
    fi
  done
```

**Action:** Suggest cleanup or archival

## Integrated Analysis

### Multi-Signal Validation

Combine signals for higher confidence:

```python
def calculate_bloat_confidence(file):
    signals = []

    # Staleness
    months = months_since_last_change(file)
    if months > 12:
        signals.append(('stale', 85, months))

    # No references
    refs = count_references(file)
    if refs == 0:
        signals.append(('unused', 90, refs))

    # Low churn
    churn = calculate_churn(file)
    if churn < 50:  # < 50 changes/year
        signals.append(('low_churn', 70, churn))

    # Inactive owner
    if is_owner_inactive(file):
        signals.append(('inactive_owner', 65, None))

    # Combined confidence
    if len(signals) >= 3:
        return 'HIGH', signals
    elif len(signals) == 2:
        return 'MEDIUM', signals
    else:
        return 'LOW', signals
```

### Example Output

```yaml
file: src/deprecated/old_api.py
confidence: HIGH
signals:
  - type: stale
    score: 85
    detail: 18 months since last change
  - type: unused
    score: 90
    detail: Zero references found
  - type: low_churn
    score: 70
    detail: 12 changes in last year
combined_score: 82
recommendation: DELETE
rationale: |
  Multiple strong signals indicate abandonment:
  - No changes in 18 months
  - No code references
  - Minimal historical activity
  Safe to remove with archival backup.
```

## AskGit Integration (Optional)

If AskGit is available, use SQL for advanced queries:

```sql
-- Find files with high churn but low recent activity
SELECT
  file_path,
  SUM(additions + deletions) as total_churn,
  MAX(author_when) as last_change
FROM commits
WHERE author_when < date('now', '-6 months')
GROUP BY file_path
HAVING total_churn > 1000
ORDER BY total_churn DESC;
```

## Performance Optimization

**Caching Strategy:**
```bash
# Cache git log results for reuse
git log --all --numstat --pretty=format:'%H|%an|%ai' > /tmp/git_cache.txt

# Query cache instead of running git log repeatedly
grep "path/to/file" /tmp/git_cache.txt
```

**Incremental Updates:**
- Store previous scan results
- Only analyze changed files
- Delta reporting

## Safety Checks

Before flagging for deletion:

1. **Test Files**: Exclude `test_*.py`, `*.spec.js`
2. **Migrations**: Database migrations must never auto-delete
3. **CI/CD**: Files in `.github/`, `.gitlab-ci.yml`
4. **Documentation**: User-facing docs need manual review

**Whitelist Patterns:**
```yaml
safe_paths:
  - tests/
  - migrations/
  - .github/
  - docs/api/  # API docs are references, not code

excluded_from_bloat_analysis:
  # Cache directories (always exclude from counts)
  - .venv/
  - venv/
  - __pycache__/
  - .pytest_cache/
  - .mypy_cache/
  - .ruff_cache/
  - .tox/
  - .git/
  # Dependencies and build artifacts
  - node_modules/
  - vendor/
  - dist/
  - build/
```

## Integration with Quick Scan

Git analysis validates quick scan findings:

```python
def validate_quick_scan_finding(finding):
    # Quick scan says file is bloated
    # Git analysis confirms or refutes
    git_score = analyze_git_history(finding.file)

    if quick_scan.score > 80 and git_score > 80:
        return 'HIGH_CONFIDENCE'
    elif quick_scan.score > 60 and git_score > 60:
        return 'MEDIUM_CONFIDENCE'
    else:
        return 'LOW_CONFIDENCE'  # Conflicting signals
```

## Next Steps

Based on git analysis:
- **HIGH confidence**: Create cleanup PR
- **MEDIUM confidence**: Run static analysis (Tier 2)
- **LOW confidence**: Manual code review


path: modules/growth-analysis.md
content: ---
module: growth-analysis
category: tier-1
dependencies: [Bash, Grep, Glob]
estimated_tokens: 1500
---

# Growth Analysis Module

Track codebase growth velocity using git history.
Forecast future size, predict threshold crossings,
and rank directories by urgency.

This module replaces the former standalone
`/analyze-growth` command (removed in v1.6.0).
It runs as part of `/bloat-scan --growth`.

## When to Load

Load this module when:

- Running `/bloat-scan --growth`
- Investigating rapid file or line count increases
- Planning capacity for skill files approaching token limits
- Preparing quarterly growth reports

## Core Metrics

### 1. File Count Velocity

Track how fast new files appear in a directory tree.

```bash
# File count per week for the last 8 weeks
for i in $(seq 0 7); do
  date=$(date -d "$((i * 7)) days ago" +%Y-%m-%d)
  count=$(git log --until="$date" --diff-filter=A \
    --name-only --pretty=format: -- "$TARGET_DIR" | \
    sort -u | wc -l)
  echo "$date $count"
done | sort
```

**Output columns:** date, cumulative file count

### 2. Line Count Velocity

Measure net line growth over recent commits.

```bash
# Net lines added per week for last 8 weeks
for i in $(seq 0 7); do
  start=$(date -d "$(( (i+1) * 7 )) days ago" +%Y-%m-%d)
  end=$(date -d "$((i * 7)) days ago" +%Y-%m-%d)
  git log --since="$start" --until="$end" \
    --numstat --pretty=format: -- "$TARGET_DIR" | \
    awk '{added+=$1; deleted+=$2}
      END {print added - deleted}'
done
```

**Negative values** indicate shrinkage (good after cleanup).

### 3. Commit Frequency

Count commits touching a path over rolling windows.

```bash
# Commits per week for last 8 weeks
for i in $(seq 0 7); do
  start=$(date -d "$(( (i+1) * 7 )) days ago" +%Y-%m-%d)
  end=$(date -d "$((i * 7)) days ago" +%Y-%m-%d)
  count=$(git log --since="$start" --until="$end" \
    --oneline -- "$TARGET_DIR" | wc -l)
  echo "week-$i: $count commits"
done
```

### 4. Size Snapshot

Current state measurement for the target path.

```bash
# Total lines in tracked files (exclude cache dirs)
git ls-files -- "$TARGET_DIR" | \
  grep -v -E '(\.venv|__pycache__|node_modules|\.git)' | \
  xargs wc -l 2>/dev/null | tail -1
```

## 30-Day Forecast

Use simple linear regression on the last 8 weekly
data points to project 30 days forward.

### Algorithm

```python
def forecast_30d(weekly_counts):
    """
    Linear least-squares fit on weekly data.
    Returns projected value 4.3 weeks from now.
    """
    n = len(weekly_counts)
    if n < 3:
        return None  # Not enough data

    xs = list(range(n))
    x_mean = sum(xs) / n
    y_mean = sum(weekly_counts) / n

    numerator = sum(
        (x - x_mean) * (y - y_mean)
        for x, y in zip(xs, weekly_counts)
    )
    denominator = sum((x - x_mean) ** 2 for x in xs)

    if denominator == 0:
        return y_mean  # Flat line

    slope = numerator / denominator
    intercept = y_mean - slope * x_mean

    # 30 days = ~4.3 weeks beyond last data point
    future_x = (n - 1) + 4.3
    return slope * future_x + intercept
```

### Interpreting Forecasts

- **Slope > 0**: Growing. Report weekly rate.
- **Slope ~ 0**: Stable. No action needed.
- **Slope < 0**: Shrinking. Recent cleanup likely working.

Report the R-squared value when possible.
Low R-squared (< 0.5) means the trend is noisy
and the forecast is unreliable.

## Threshold Crossing Predictions

Given a target limit (e.g., 500-line skill file limit),
calculate when the current growth rate will cross it.

### Algorithm

```python
def weeks_until_threshold(current_size, weekly_rate, limit):
    """
    Returns weeks until current_size reaches limit
    at the given weekly_rate.
    Returns None if rate <= 0 (will never cross).
    """
    if weekly_rate <= 0:
        return None
    remaining = limit - current_size
    if remaining <= 0:
        return 0  # Already exceeded
    return remaining / weekly_rate
```

### Default Thresholds

| Target | Limit | Rationale |
|--------|-------|-----------|
| Skill file | 500 lines | Progressive loading boundary |
| Module file | 300 lines | Single-responsibility cap |
| Python source | 500 lines | God class indicator |
| Markdown doc | 300 lines | Reader attention limit |

Override thresholds with `--threshold <lines>`.

## Urgency Rankings

Rank directories or files by how soon they will
need attention.

### Scoring Formula

```
urgency = growth_rate * (current_size / threshold) * recency_weight
```

Where:

- `growth_rate`: Lines per week (normalized 0-1)
- `current_size / threshold`: How close to the limit (0-1+)
- `recency_weight`: 1.5 if accelerating, 1.0 if steady,
  0.5 if decelerating

### Urgency Categories

| Category | Score Range | Action |
|----------|------------|--------|
| Critical | > 0.8 | Modularize or split now |
| High | 0.5 - 0.8 | Plan optimization this sprint |
| Medium | 0.2 - 0.5 | Add to backlog |
| Low | < 0.2 | No action needed |

### Acceleration Detection

Compare the growth rate of the last 4 weeks against
the preceding 4 weeks.

```python
def detect_acceleration(weekly_rates):
    if len(weekly_rates) < 8:
        return "insufficient_data"
    recent = sum(weekly_rates[-4:]) / 4
    earlier = sum(weekly_rates[-8:-4]) / 4
    if earlier == 0:
        return "new_growth" if recent > 0 else "stable"
    ratio = recent / earlier
    if ratio > 1.5:
        return "accelerating"
    elif ratio < 0.5:
        return "decelerating"
    return "steady"
```

## Output Format

### Terminal Report

```
=== Growth Analysis: plugins/conserve/skills/ ===

Current State:
  Files:  47
  Lines:  8,234
  Avg:    175 lines/file

30-Day Forecast:
  Files:  +5  (52 projected)
  Lines:  +820 (9,054 projected)
  Rate:   ~205 lines/week

Threshold Alerts:
  bloat-detector/SKILL.md    412/500 lines  ~4 weeks to limit
  context-optimization.md    289/300 lines  ~1 week to limit  [!]

Urgency Rankings:
  [CRITICAL] context-optimization.md   0.92
  [HIGH]     bloat-detector/SKILL.md   0.67
  [MEDIUM]   token-conservation.md     0.34
  [LOW]      performance-monitoring.md 0.11
```

### Machine-Readable Output

```yaml
growth_analysis:
  target: plugins/conserve/skills/
  snapshot:
    files: 47
    lines: 8234
    date: "2026-03-10"
  forecast_30d:
    files: 52
    lines: 9054
    confidence: 0.78
  weekly_rate:
    files: 1.2
    lines: 205
  threshold_alerts:
    - path: context-optimization.md
      current: 289
      limit: 300
      weeks_remaining: 1
      urgency: critical
    - path: bloat-detector/SKILL.md
      current: 412
      limit: 500
      weeks_remaining: 4
      urgency: high
  rankings:
    - path: context-optimization.md
      urgency: 0.92
      category: critical
      acceleration: accelerating
    - path: bloat-detector/SKILL.md
      urgency: 0.67
      category: high
      acceleration: steady
```

## Integration with Bloat Scan

Growth analysis feeds into the bloat detection pipeline:

- **Fast-growing files** get flagged for proactive review
  before they become bloated
- **Threshold alerts** trigger modularization suggestions
  from the `remediation-types` module
- **Urgency rankings** prioritize the bloat scan report's
  findings list

### Coordination with Other Modules

- `quick-scan`: Growth data adds time dimension to
  size-based findings
- `git-history-analysis`: Shares git log data;
  growth-analysis focuses on trends while
  git-history focuses on staleness and churn
- `remediation-types`: Growth-triggered items map to
  REFACTOR (split) or ARCHIVE (stabilize) actions

## Limitations

- Requires at least 3 weeks of git history for
  meaningful forecasts
- Linear projection does not capture seasonal patterns
  or burst development cycles
- Merge commits can skew line counts; use `--no-merges`
  when possible
- Renamed files appear as delete + add, inflating
  apparent growth


path: modules/quick-scan.md
content: ---
module: quick-scan
category: tier-1
dependencies: [Bash, Grep, Glob]
estimated_tokens: 200
---

# Quick Scan Module

Fast heuristic-based bloat detection without external tools. Completes in < 5 minutes.

## Detection Patterns

### 1. Large Files (God Class Candidates)

```bash
# Find files > 500 lines (excluding cache and dependency directories)
find . -type f \( -name "*.py" -o -name "*.js" -o -name "*.ts" \) \
  -not -path "*/.venv/*" \
  -not -path "*/venv/*" \
  -not -path "*/__pycache__/*" \
  -not -path "*/.pytest_cache/*" \
  -not -path "*/node_modules/*" \
  -not -path "*/.git/*" \
  -not -path "*/dist/*" \
  -not -path "*/build/*" \
  -not -path "*/.tox/*" \
  -not -path "*/.mypy_cache/*" \
  -not -path "*/.ruff_cache/*" | \
while read f; do
  lines=$(wc -l < "$f")
  if [ $lines -gt 500 ]; then
    echo "$lines $f"
  fi
done | sort -rn
```

**Thresholds:**
- Python: > 500 lines (God class likely)
- JavaScript/TypeScript: > 400 lines
- Markdown: > 300 lines (bloated docs)

**Confidence:** MEDIUM (70%) - Large size suggests but doesn't confirm bloat

### 2. Stale Files (Lava Flow)

```bash
# Files unchanged in 6+ months
git log --since="6 months ago" --name-only --pretty=format: | \
  sort -u > recent_files.txt

git ls-files | while read f; do
  if ! grep -qxF "$f" recent_files.txt; then
    last_modified=$(git log -1 --format="%ai" -- "$f")
    echo "$last_modified $f"
  fi
done | sort

rm recent_files.txt
```

**Thresholds:**
- > 12 months: HIGH confidence (95%)
- 6-12 months: MEDIUM confidence (75%)
- 3-6 months: LOW confidence (50%)

**False Positives:** Stable libraries, configuration files (check `.bloat-ignore`)

### 3. Commented Code Blocks

```bash
# Find large commented code blocks (Python)
grep -rn "^#.*def \|^#.*class \|^#.*import " --include="*.py" . | \
  awk '{print $1}' | uniq -c | sort -rn

# JavaScript/TypeScript
grep -rn "^//.*function \|^//.*class \|^//.*import " --include="*.js" --include="*.ts" . | \
  awk '{print $1}' | uniq -c | sort -rn
```

**Confidence:** HIGH (90%) - Commented code is rarely needed

### 4. Old TODOs/FIXMEs

```bash
# Find TODOs with dates > 3 months old
grep -rn "TODO\|FIXME\|HACK" --include="*.py" --include="*.js" --include="*.ts" --include="*.md" . | \
  grep -E "[0-9]{4}-[0-9]{2}" | \
  while read line; do
    # Extract date and compare (simplified - actual implementation would parse dates)
    echo "$line"
  done
```

**Thresholds:**
- > 12 months: Remove or convert to issue
- 6-12 months: Review for relevance
- 3-6 months: Monitor

**Confidence:** MEDIUM (70%) - Context-dependent

### 5. Duplicate Patterns

```bash
# Find potential duplicate files by name similarity (excluding cache directories)
find . -type f \( -name "*.py" -o -name "*.js" -o -name "*.ts" \) \
  -not -path "*/.venv/*" \
  -not -path "*/venv/*" \
  -not -path "*/__pycache__/*" \
  -not -path "*/.pytest_cache/*" \
  -not -path "*/node_modules/*" \
  -not -path "*/.git/*" | \
  sed 's/.*\///' | sort | uniq -d

# Find duplicate files by content hash (excluding cache directories)
find . -type f -name "*.py" \
  -not -path "*/.venv/*" \
  -not -path "*/venv/*" \
  -not -path "*/__pycache__/*" \
  -not -path "*/.pytest_cache/*" \
  -not -path "*/.git/*" \
  -exec md5sum {} \; | \
  sort | uniq -w32 -D | cut -d' ' -f3-
```

**Confidence:** LOW (60%) - Needs manual review, may be intentional

## Scoring Algorithm

```python
def calculate_quick_scan_score(file_path, metrics):
    score = 0

    # Size penalty
    if metrics['lines'] > 500:
        score += (metrics['lines'] - 500) / 100 * 10

    # Staleness penalty
    months_unchanged = metrics['months_since_change']
    if months_unchanged > 12:
        score += 30  # High penalty
    elif months_unchanged > 6:
        score += 15  # Medium penalty

    # Commented code penalty
    commented_lines = metrics['commented_code_lines']
    score += commented_lines * 0.5

    # Old TODOs
    old_todos = metrics['todos_older_than_6mo']
    score += old_todos * 2

    # Normalize to 0-100
    return min(score, 100)
```

## Output Format

```yaml
file: path/to/bloated_file.py
bloat_score: 85
confidence: MEDIUM
signals:
  - large_file: 847 lines (threshold: 500)
  - stale: 18 months unchanged
  - commented_code: 23 lines
  - old_todos: 3 (oldest: 14 months)
token_estimate: ~3,200 tokens
recommendations:
  - action: DELETE
    rationale: No recent usage, high bloat score
    safety: Check for external references first
  - action: ARCHIVE
    rationale: Preserve history without active maintenance
    location: archive/legacy/
```

## Integration with Git Analysis

Quick scan coordinates with `git-history-analysis` module:
- Quick scan identifies candidates
- Git analysis validates with reference counting
- Combined confidence: HIGHER than either alone

## Performance

- **Target**: < 5 minutes for 10,000 files
- **Method**: Parallel grep, minimal disk I/O
- **Optimization**: Cache git log results, reuse across scans

## False Positive Handling

Respect `.bloat-ignore` patterns:

```gitignore
# .bloat-ignore - Patterns to exclude from bloat detection

# Cache directories (should always be excluded)
.venv/
venv/
__pycache__/
.pytest_cache/
.mypy_cache/
.ruff_cache/
.tox/
.git/

# Build and distribution
dist/
build/
*.egg-info/

# Dependencies
node_modules/
vendor/

# IDE and editor
.vscode/
.idea/

# Test fixtures and templates
tests/fixtures/*
config/*.template

# Auto-generated code
generated/*
*_pb2.py
```

**Default Exclusions**: The scan tools should automatically exclude common cache directories even without a `.bloat-ignore` file.

## Next Steps After Quick Scan

Based on findings:
- **High-confidence**: Proceed with cleanup
- **Medium-confidence**: Run Tier 2 for validation
- **Low-confidence**: Manual review required


path: modules/remediation-types.md
content: ---
module: remediation-types
category: remediation
dependencies: []
estimated_tokens: 150
---

# Remediation Types

Shared definitions for bloat remediation actions used by unbloat command and unbloat-remediator agent.

## DELETE (Dead Code Removal)

Remove files with high confidence they're unused:
- 0 references (git grep, static analysis)
- Stale (> 6 months unchanged)
- High confidence (> 90%)
- Non-core files

**Risk Assessment:**
| Risk | Criteria |
|------|----------|
| LOW | deprecated/*, test files, archive/*, 0 refs, 95%+ confidence |
| MEDIUM | 1-2 refs, 85-94% confidence |
| HIGH | >2 refs, <85% confidence, core infrastructure |

## REFACTOR (Split God Classes)

Break large, low-cohesion files into focused modules:
- Large files (> 500 lines)
- Multiple responsibilities (low cohesion)
- High cyclomatic complexity
- Active usage (recent changes)

**Risk Assessment:**
| Risk | Criteria |
|------|----------|
| LOW | Utilities, helpers, pure functions, < 3 import sites |
| MEDIUM | Services, handlers, 3-10 import sites |
| HIGH | Core modules, frameworks, > 10 import sites |

## CONSOLIDATE (Merge Duplicates)

Merge duplicate or redundant content:
- Documentation with > 85% similarity
- Duplicate code patterns
- Multiple versions of same concept

**Risk Assessment:**
| Risk | Criteria |
|------|----------|
| LOW | Docs, examples, pure duplication |
| MEDIUM | Utilities with slight variations |
| HIGH | Business logic, different contexts |

## ARCHIVE (Move to Archive)

Move stale but historically valuable content:
- Old tutorials, examples
- Deprecated but referenced
- Historical documentation

**Risk Assessment:**
| Risk | Criteria |
|------|----------|
| LOW | Examples, tutorials, < 5 refs |
| MEDIUM | Guides, how-tos, 5-10 refs |
| HIGH | Core docs, > 10 refs |

## INLINE (Remove Dead Wrappers)

Replace thin facades and passthrough functions with direct usage of the underlying implementation:
- Whole-file wrappers with 0 external consumers → DELETE
- Intra-file passthrough methods that only delegate → INLINE callers to use wrapped method directly
- Re-export layers where examples/ already demonstrates the same API

**Risk Assessment:**
| Risk | Criteria |
|------|----------|
| LOW | 0 external refs, wrapper adds no logic, underlying module is stable |
| MEDIUM | 1-2 refs, wrapper adds minor convenience (default args, error handling) |
| HIGH | >2 refs, wrapper provides meaningful abstraction or cross-cutting concerns |

**Detection Signals:**
- File imports internal module and re-exports similar API surface
- No `__init__.py` (not a proper package)
- Function bodies are single `return self.other_method(...)` calls
- Duplicate capability exists in `examples/` or `skills/` directories

## Auto-Approval Levels

| Level | Criteria |
|-------|----------|
| `low` | Confidence >= 90%, Risk = LOW, 0 refs, deprecated/test/archive files only |
| `medium` | Confidence >= 80%, Risk <= MEDIUM, <= 2 refs, non-core |
| `none` | Prompts for every change (default, safest) |

**Note:** All levels still show preview before execution.


path: modules/static-analysis-integration.md
content: ---
module: static-analysis-integration
category: tier-2
dependencies: [Bash, Read]
estimated_tokens: 150
---

# Static Analysis Integration Module

Bridge Tier 1 heuristics with Tier 2 programmatic analysis. Auto-detects tools and falls back gracefully.

## Tool Detection

```bash
# Auto-detect available tools
TOOLS=()
command -v vulture &>/dev/null && TOOLS+=("vulture")
command -v deadcode &>/dev/null && TOOLS+=("deadcode")
command -v autoflake &>/dev/null && TOOLS+=("autoflake")
command -v knip &>/dev/null && TOOLS+=("knip")
command -v sonar-scanner &>/dev/null && TOOLS+=("sonarqube")

[ ${#TOOLS[@]} -gt 0 ] && echo "Tier 2 capable" || echo "Tier 1 only"
```

## Python Tools

| Tool | Strength | Confidence | Command |
|------|----------|------------|---------|
| **vulture** | Dead code detection | 80-95% | `vulture . --min-confidence 80` |
| **deadcode** | Fast, auto-fix | 85% | `deadcode --dry` |
| **autoflake** | Import cleanup | 95% | `autoflake --check -r .` |

### Vulture (Recommended)
```bash
vulture . --min-confidence 80 --exclude=.venv,__pycache__,.git,node_modules
```
- 90-100%: Safe to remove
- 80-89%: Review first
- <80%: Investigate

### autoflake (Imports)
```bash
autoflake --check --remove-all-unused-imports --expand-star-imports -r .
# Fix: add --in-place
```
**Impact:** 40-70% startup time reduction

## JavaScript/TypeScript

| Tool | Strength | Confidence | Command |
|------|----------|------------|---------|
| **knip** | Files, exports, deps | 95% | `knip --include files,exports` |

```bash
knip --include files,exports,dependencies --reporter json > knip-report.json
```

**Tree-shaking prereqs:**
- `"type": "module"` in package.json
- Avoid `export * from` barrel patterns

## Multi-Language

**SonarQube** (enterprise): Duplication, complexity, code smells
```bash
sonar-scanner -Dsonar.sources=. -Dsonar.exclusions="**/node_modules/**"
```

## Tool Selection

```python
PRIORITY = {'python': ['vulture', 'deadcode'], 'javascript': ['knip']}
tool = next((t for t in PRIORITY.get(lang, []) if t in available), 'heuristic')
```

## Confidence Boosting

When heuristic + tool agree: boost confidence by 15% (max 95%)

```yaml
# Output format
file: src/utils/helpers.py
type: function
name: calculate_legacy
confidence: 95%
sources: [heuristic, vulture]
action: DELETE
```

## Graceful Degradation

No tools? Fall back to `@module:code-bloat-patterns` heuristics.

## Related
- `code-bloat-patterns` - Heuristic fallbacks
- `bloat-auditor` - Orchestrates tool execution


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)