> Orchestrate dead code removal and architecture violation fixes with a shared convergence loop. Catches cross-concern cascades that individual skills miss.
Installs into .claude/skills of the current project.
Are you the author of Harness Codebase Cleanup?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/intense-visions-harness-codebase-cleanup)
# Harness Codebase Cleanup
> Orchestrate dead code removal and architecture violation fixes with a shared convergence loop. Catches cross-concern cascades that individual skills miss.
## When to Use
- After a major refactoring or feature removal when both dead code and architecture violations are likely
- As a periodic comprehensive codebase hygiene task
- When `cleanup-dead-code` or `enforce-architecture` individually are not catching cascading issues
- When you want hotspot-aware safety classification
- NOT for quick single-concern checks -- use `cleanup-dead-code` or `enforce-architecture` directly
- NOT when tests are failing -- fix tests first
- NOT during active feature development
## Flags
| Flag | Effect |
| --------------------- | ----------------------------------------------------------------- |
| `--fix` | Enable convergence-based auto-fix (default: detect + report only) |
| `--dead-code-only` | Skip architecture checks |
| `--architecture-only` | Skip dead code checks |
| `--dry-run` | Show what would be fixed without applying |
| `--ci` | Non-interactive: apply safe fixes only, report everything else |
## Process
### Phase 1: CONTEXT -- Build Hotspot Map
1. **Run hotspot detection** via git log analysis:
```bash
git log --format=format: --name-only --since="6 months ago" | sort | uniq -c | sort -rn | head -50
```
2. **Build churn map.** Parse output into a `file -> commit count` mapping.
3. **Compute top 10% threshold.** Sort all files by commit count. The file at the 90th percentile defines the threshold. Files above this threshold are "high churn."
4. **Store as HotspotContext** for use in Phase 3 (CLASSIFY).
Run `detect_stale_constraints` to find architectural constraints referencing removed or restructured code. Run `detect_anomalies` to identify structural irregularities that should be addressed during cleanup.
### Phase 2: DETECT -- Run Both Concerns in Parallel
1. **Dead code detection** (skip if `--architecture-only`):
- Run `harness cleanup --type dead-code --json`
- Captures: dead files, dead exports, unused imports, dead internals, commented-out code blocks, orphaned dependencies
2. **Architecture detection** (skip if `--dead-code-only`):
- Run `harness check-deps --json`
- Captures: layer violations, forbidden imports, circular dependencies, import ordering issues
3. **Merge findings.** Convert all raw findings into `CleanupFinding` objects using `classifyFinding()`. This normalizes both concerns into a shared schema.
### Phase 3: CLASSIFY -- Safety Classification and Dedup
1. **Apply safety classification.** Each `CleanupFinding` already has a safety level from `classifyFinding()`. Review the classification rules:
**Dead code safety:**
| Finding | Safety | Condition |
| ------------------------- | ------------- | ------------------------------------------- |
| Dead files | Safe | Not entry point, no side effects |
| Unused imports | Safe | Zero references |
| Dead exports (non-public) | Safe | Zero importers, not in package entry point |
| Dead exports (public API) | Unsafe | In package entry point or published package |
| Commented-out code | Safe | Always (code is in git history) |
| Orphaned npm deps | Probably safe | Needs install + test verification |
| Dead internals | Unsafe | Cannot reliably determine all callers |
**Architecture safety:**
| Violation | Safety | Condition |
| ----------------------------------- | ------------- | -------------------------- |
| Import ordering | Safe | Mechanical reorder |
| Forbidden import (with alternative) | Probably safe | 1:1 replacement configured |
| Forbidden import (no alternative) | Unsafe | Requires restructuring |
| Design token (unambiguous) | Probably safe | Single token match |
| Design token (ambiguous) | Unsafe | Multiple candidates |
| Upward dependency | Unsafe | Always |
| Skip-layer dependency | Unsafe | Always |
| Circular dependency | Unsafe | Always |
2. **Apply hotspot downgrade.** For each finding, check if the file is in the top 10% by churn (from Phase 1 HotspotContext). If so, downgrade `safe` to `probably-safe`. Do not downgrade `unsafe` findings.
3. **Cross-concern dedup.** Call `deduplicateFindings()` to merge overlapping findings:
- A dead import from a forbidden layer = one finding (dead-code concern, noting architecture overlap)
- A dead file that has architecture violations = one finding (dead-code, noting violations resolved by deletion)
### Phase 4: FIX -- Convergence Loop
**Only runs when `--fix` flag is set.** Without `--fix`, skip to Phase 5 (REPORT).
```
findings = classified findings from Phase 3
previousCount = findings.length
iteration = 0
while iteration < 5:
iteration++
# Batch 1: Apply safe fixes silently
safeFixes = findings.filter(f => f.safety === 'safe')
apply(safeFixes)
# Batch 2: Present probably-safe fixes
if --ci mode:
skip probably-safe fixes (report only)
else:
probablySafeFixes = findings.filter(f => f.safety === 'probably-safe')
presentAsDiffs(probablySafeFixes)
apply(approved fixes)
# Verify: lint + typecheck + test
verifyResult = run("pnpm lint && pnpm tsc --noEmit && pnpm test")
if verifyResult.failed:
revertBatch()
reclassify failed fixes as unsafe
continue
# Re-detect both concerns
newFindings = runDetection() # Phase 2 again
newFindings = classify(newFindings) # Phase 3 again
if newFindings.length >= previousCount:
break # No progress, stop
previousCount = newFindings.length
findings = newFindings
```
**Verification gate:** Every fix batch must pass lint + typecheck + test. If verification fails:
1. Revert the entire batch (use git: `git checkout -- .`)
2. Reclassify all findings in the batch as `unsafe`
3. Continue the loop with remaining findings
**Cross-concern cascade examples:**
- Dead import from forbidden layer: removing the dead import also resolves the architecture violation. Single fix, both resolved.
- Architecture fix creates dead code: replacing a forbidden import makes the old module's export dead. Next detect cycle catches it.
- Dead file resolves multiple violations: deleting a dead file that imports from wrong layers resolves those violations too.
### Phase 5: REPORT -- Actionable Output
Generate a structured report with two sections:
**1. Fixes Applied:**
For each fix that was applied:
- File and line
- What was fixed (finding type and description)
- What action was taken (delete, replace, reorder)
- Verification status (pass/fail)
**2. Remaining Findings (requires human action):**
For each unsafe finding that was not auto-fixed:
- **What is wrong:** The finding type, file, line, and description
- **Why it cannot be auto-fixed:** The safety reason and classification logic
- **Suggested approach:** Concrete next steps for manual resolution
Example report output:
```
=== HARNESS CODEBASE CLEANUP REPORT ===
Fixes applied: 12
- 5 unused imports removed (safe)
- 3 dead exports de-exported (safe)
- 2 commented-out code blocks deleted (safe)
- 1 forbidden import replaced (probably-safe, approved)
- 1 orphaned dependency removed (probably-safe, approved)
Convergence: 3 iterations, 12 → 8 → 3 → 3 (stopped)
Remaining findings: 3 (require human action)
1. UNSAFE: Circular dependency
File: src/services/order-service.ts <-> src/services/inventory-service.ts
Why: Circular dependencies require structural refactoring
Suggested: Extract shared logic into src/services/stock-calculator.ts
2. UNSAFE: Dead internal function
File: src/utils/legacy.ts:45 — processLegacyFormat()
Why: Cannot reliably determine all callers (possible dynamic usage)
Suggested: Search for string references, check config files, then delete if confirmed unused
3. UNSAFE: Public API dead export
File: packages/core/src/index.ts — legacyHelper
Why: Export is in package entry point; external consumers may depend on it
Suggested: Deprecate with @deprecated JSDoc tag, remove in next major version
```
## Rationalizations to Reject
These are common rationalizations that sound reasonable but lead to incorrect results. When you catch yourself thinking any of these, stop and follow the documented process instead.
| Rationalization | Why It Is Wrong |
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| "This dead export is in a high-churn file but the removal is clearly safe" | High-churn files have more hidden consumers. Safe findings in the top 10% by churn are downgraded to probably-safe, requiring explicit approval. |
| "The convergence loop is not reducing findings quickly enough, so I will apply unsafe fixes to make progress" | Unsafe findings are never auto-fixed, regardless of convergence pressure. Each requires human judgment. |
| "The verification gate failed on a probably-safe fix, but I am confident the fix is correct" | When verification fails after a fix batch, the entire batch must be reverted and all findings reclassified as unsafe. |
| "I will skip the hotspot context phase since it adds time and the churn data is just supplementary" | The hotspot map drives safety classification accuracy. Without it, safe fixes in high-churn areas are not downgraded. |
## Examples
### Example: Post-Refactoring Cleanup
After removing the `legacy-auth` module:
1. **Phase 1 (CONTEXT):** Hotspot analysis shows `src/services/auth.ts` has 42 commits (top 5%).
2. **Phase 2 (DETECT):** Dead code detects 3 dead exports in `src/utils/token.ts` (were only used by legacy-auth). Architecture detects 1 forbidden import in `src/services/session.ts` (still importing from removed module's location).
3. **Phase 3 (CLASSIFY):** Dead exports classified as `safe` but downgraded to `probably-safe` because `token.ts` is in a high-churn file. Forbidden import classified as `unsafe` (no alternative configured).
4. **Phase 4 (FIX):** First iteration removes 3 dead exports (approved as probably-safe). Re-detect finds `token.ts` now has zero exports and becomes a dead file. Second iteration deletes the dead file. Convergence stops -- the forbidden import requires manual restructuring.
5. **Phase 5 (REPORT):** 4 fixes applied (3 dead exports + 1 dead file), 1 remaining finding (forbidden import requiring restructuring).
## Harness Integration
- **`harness cleanup --type dead-code --json`** -- Dead code detection input
- **`harness check-deps --json`** -- Architecture violation detection input
- **`git log` analysis** -- Hotspot context for safety classification (inline command, no skill invocation needed)
- **`harness validate`** -- Final validation after all fixes
- **`harness check-deps`** -- Final architecture check after all fixes
## Success Criteria
- All safe fixes are applied without test failures
- Probably-safe fixes are presented as diffs for approval (or skipped in CI mode)
- Unsafe findings are never auto-fixed
- Convergence loop catches cross-concern cascades
- Report includes actionable guidance for every remaining finding
- `harness validate` passes after cleanup
## Escalation
- **When convergence loop does not converge after 5 iterations:** The codebase has deeply tangled issues. Stop and report all remaining findings. Consider breaking the cleanup into focused sessions.
- **When a safe fix causes test failures:** The classification was wrong. Revert, reclassify as unsafe, and investigate the hidden dependency. Document the false positive for future improvement.
- **When the hotspot detector is unavailable:** Skip the hotspot downgrade. All safety classifications use their base level without churn context.
- **When dead code and architecture fixes conflict:** The convergence loop handles this naturally. If removing dead code creates an architecture issue (rare), the next detection cycle catches it.