Agent skill
quality-detect-orphaned-code
Detects orphaned code (files/functions that exist but are never imported or called in production), preventing "created but not integrated" failures. Use before marking features complete, before moving ADRs to completed, during code reviews, or as part of quality gates. Triggers on "detect orphaned code", "find dead code", "check for unused modules", "verify integration", or proactively before completion. Works with Python modules, functions, classes, and LangGraph nodes. Catches the ADR-013 failure pattern where code exists and tests pass but is never integrated.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/quality-detect-orphaned-code
SKILL.md
Detect Orphaned Code
Quick Start
Run orphan detection before marking any feature complete:
# Quick check for a specific module
grep -r "from.*your_module import\|import.*your_module" src/ --include="*.py" | grep -v test
# If output is EMPTY → Module is orphaned (not imported in production)
# Comprehensive orphan detection (if script exists)
./scripts/verify_integration.sh
# Check specific function usage
grep -r "your_function_name" src/ --include="*.py" | grep -v test | grep -v "^[^:]*:.*def "
# If output is EMPTY → Function is orphaned (never called)
Table of Contents
- When to Use This Skill
- What This Skill Does
- Types of Orphaned Code
- Detection Methods
- Step-by-Step Detection Process
- Automated Detection Scripts
- Integration with Quality Gates
- Supporting Files
- Expected Outcomes
- Requirements
- Red Flags to Avoid
When to Use This Skill
Explicit Triggers
- "Detect orphaned code"
- "Find dead code in the project"
- "Check for unused modules"
- "Verify no orphaned files exist"
- "Find code that's never imported"
- "Check for integration gaps"
Implicit Triggers (PROACTIVE)
- Before marking any feature complete
- Before moving ADR from in_progress to completed
- After creating new Python modules
- After major refactoring
- As part of pre-commit quality gates
- During code review
Debugging Triggers
- "Tests pass but feature doesn't work" (often orphaned code)
- "File exists but nothing happens when I run it"
- "Why isn't my new module being used?"
- "Code review found unused imports"
What This Skill Does
This skill detects code that exists but is never used, preventing the ADR-013 failure mode:
What it detects:
- Orphaned modules - Python files never imported in production code
- Orphaned functions - Functions defined but never called
- Orphaned classes - Classes defined but never instantiated
- Orphaned nodes - LangGraph nodes never added to graph
- Dead code paths - Code wired but conditionals never trigger
What it prevents:
- Marking incomplete features as "done"
- Moving ADRs to completed when code isn't integrated
- Accumulating technical debt (unused code)
- Confusion for future developers (why does this exist?)
Why existing tools miss this:
- vulture - Can be fooled by unit tests that import modules
- mypy - Only checks types, not usage
- pytest - Can pass 100% coverage on orphaned modules
- ruff - Checks style, not integration
This skill complements those tools by checking integration explicitly.
Types of Orphaned Code
Type 1: Orphaned Module (File Never Imported)
Symptom: Python file exists, has tests, but is never imported in production code
Example:
# File: src/myapp/features/new_feature.py (175 lines)
def process_data(data: dict) -> Result:
"""Process data and return result."""
# ... implementation ...
Detection:
$ grep -r "from.*new_feature import\|import.*new_feature" src/ --include="*.py" | grep -v test
(empty) ❌
Root cause: File created but never imported in integration point
Fix: Import in the consuming module
Type 2: Orphaned Function (Defined But Never Called)
Symptom: Function exists in imported module but is never called
Example:
# File: src/myapp/services/utils.py
def helper_function(x: int) -> int: # Orphaned
return x * 2
def another_function(x: int) -> int: # Used
return x + 1
Detection:
$ grep -r "helper_function" src/ --include="*.py" | grep -v test | grep -v "def helper_function"
(empty) ❌ # Only definition, no call-sites
$ grep -r "another_function" src/ --include="*.py" | grep -v test | grep -v "def another_function"
src/myapp/main.py:45: result = another_function(5) ✅ # Has call-site
Root cause: Function created but never invoked
Fix: Call the function where needed, or remove it
Type 3: Orphaned Class (Defined But Never Instantiated)
Symptom: Class exists but is never instantiated or subclassed
Example:
# File: src/myapp/models/new_model.py
class NewModel:
def __init__(self, data: dict) -> None:
self.data = data
Detection:
$ grep -r "NewModel" src/ --include="*.py" | grep -v test | grep -v "class NewModel"
(empty) ❌ # Only definition, no instantiation
Root cause: Class created but never used
Fix: Instantiate where needed, or remove
Type 4: Orphaned LangGraph Node (Node File Exists But Not in Graph)
Symptom: Node factory function exists but is never added to graph
Example:
# File: src/myapp/graph/architecture_nodes.py
async def create_architecture_review_node(agent):
"""Create architecture review node."""
# ... implementation ...
Detection:
$ grep "architecture_nodes" src/myapp/graph/builder.py
(empty) ❌ # Not imported in builder
$ grep "add_node.*architecture_review" src/myapp/graph/builder.py
(empty) ❌ # Not added to graph
Root cause: Node created but never wired into graph
Fix: Import and add to graph in builder.py
Type 5: Dead Code Path (Code Wired But Conditional Never Triggers)
Symptom: Code is integrated but the path to reach it never executes
Example:
# In builder.py
if settings.enable_experimental_features: # Never True in production
graph.add_node("experimental", experimental_node)
Detection:
# Check configuration
$ grep "enable_experimental_features" .env
# Not set (defaults to False)
# Check logs for execution
$ grep "experimental" logs/*.log
(empty) ❌ # Never executes
Root cause: Conditional never true in practice
Fix: Enable the condition or remove the dead path
Detection Methods
Method 1: Manual Grep (Quick Check)
For a specific module:
# Check if module is imported
grep -r "from.*MODULE_NAME import\|import.*MODULE_NAME" src/ --include="*.py" | grep -v test
# Expected: At least one import line from production code
# If empty: Module is orphaned
For a specific function:
# Check if function is called
grep -r "FUNCTION_NAME" src/ --include="*.py" | grep -v test | grep -v "def FUNCTION_NAME"
# Expected: At least one call-site
# If empty: Function is orphaned
For a specific class:
# Check if class is instantiated
grep -r "CLASS_NAME(" src/ --include="*.py" | grep -v test | grep -v "class CLASS_NAME"
# Expected: At least one instantiation
# If empty: Class is orphaned
Method 2: Comprehensive Script (Automated)
Script: scripts/verify_integration.sh
#!/bin/bash
# Detects orphaned modules (created but never imported in production)
set -e
echo "=== Orphan Detection ==="
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
orphaned=0
checked=0
for file in $(find src/ -name "*.py" -type f | sort); do
module=$(basename "$file" .py)
dir=$(dirname "$file")
# Skip special files
[[ "$module" == "__init__" ]] && continue
[[ "$module" == "__main__" ]] && continue
[[ "$module" == "main" ]] && continue
[[ "$module" == *"test"* ]] && continue
checked=$((checked + 1))
# Check if module is imported (excluding self and tests)
imports=$(grep -r -E "import\s+.*\b${module}\b|from\s+.*\b${module}\b\s+import" src/ \
--include="*.py" 2>/dev/null | \
grep -v "$file" | \
grep -v "test_" | \
grep -v "__pycache__" | \
wc -l | tr -d ' ')
if [ "$imports" -eq 0 ]; then
# Check if exported via __init__.py
init_file="$dir/__init__.py"
init_export=0
if [ -f "$init_file" ]; then
init_export=$(grep -c "\b$module\b" "$init_file" 2>/dev/null || echo "0")
fi
if [ "$init_export" -eq 0 ]; then
echo -e "${YELLOW}⚠️ ORPHANED:${NC} $file"
echo " No production imports found"
orphaned=$((orphaned + 1))
fi
fi
done
echo ""
echo "=== Results ==="
echo "Modules checked: $checked"
if [ $orphaned -gt 0 ]; then
echo -e "${RED}❌ ERROR: $orphaned orphaned module(s) found${NC}"
echo ""
echo "These files exist but are never imported in production code."
echo "Either wire them up or remove them."
exit 1
fi
echo -e "${GREEN}✅ All modules are integrated${NC}"
exit 0
Method 3: Integration Test (LangGraph-Specific)
Test: tests/integration/test_graph_completeness.py
"""Verify all expected nodes are in the compiled graph."""
import pytest
from langgraph.checkpoint.memory import MemorySaver
from myapp.graph.builder import create_coordination_graph
# List ALL nodes that should be in the graph
EXPECTED_NODES: list[str] = [
"query_claude",
"analyze_task",
"architecture_review", # Add new nodes here
# ... other nodes
]
@pytest.mark.asyncio
async def test_all_expected_nodes_in_graph() -> None:
"""Verify all expected nodes are wired into the graph."""
graph = await create_coordination_graph(MemorySaver())
actual_nodes = list(graph.get_graph().nodes.keys())
# Filter internal nodes
actual_nodes = [n for n in actual_nodes if not n.startswith("__")]
missing = [n for n in EXPECTED_NODES if n not in actual_nodes]
assert not missing, (
f"Nodes in EXPECTED_NODES but not in graph: {missing}. "
f"Either wire these nodes into builder.py or remove from EXPECTED_NODES."
)
Step-by-Step Detection Process
Step 1: Identify Candidates
List all Python files that could be orphaned:
# Find all .py files (excluding tests and special files)
find src/ -name "*.py" -type f | \
grep -v __pycache__ | \
grep -v test_ | \
grep -v __init__.py | \
sort
Output: List of candidate files to check
Step 2: Check Each Candidate
For each file from Step 1:
# Extract module name
MODULE=$(basename "$file" .py)
# Check for imports
echo "Checking: $MODULE"
grep -r "from.*$MODULE import\|import.*$MODULE" src/ --include="*.py" | grep -v test
# If empty → ORPHANED
# If has lines → Check if they're from production code
Step 3: Categorize Results
Category A: Clearly Integrated
- Multiple imports from production code
- Functions called in multiple places
- Part of critical paths
Category B: Suspicious (Needs Review)
- Only one import (fragile)
- Imported but functions never called
- Only imported in edge cases
Category C: Orphaned
- No imports at all
- Only imported in tests
- Imported but conditional never triggers
Step 4: Generate Report
# Example report
echo "=== Orphan Detection Report ==="
echo ""
echo "ORPHANED (Category C):"
echo " - src/features/architecture_nodes.py (CRITICAL)"
echo " - src/utils/old_helper.py"
echo ""
echo "SUSPICIOUS (Category B):"
echo " - src/features/experimental.py (only 1 import, in disabled code)"
echo ""
echo "INTEGRATED (Category A):"
echo " - src/core/main.py"
echo " - src/services/coordinator.py"
Step 5: Take Action
For Category C (Orphaned):
- If needed: Wire into system (import + call)
- If not needed: Remove file
- Update tests if removed
For Category B (Suspicious):
- Review import locations
- Check if code is actually used
- Consider making integration more robust
For Category A (Integrated):
- No action needed
- Consider adding to integration test
Automated Detection Scripts
Script 1: verify_integration.sh (Complete)
Location: scripts/verify_integration.sh
Usage:
# Check entire project
./scripts/verify_integration.sh
# Expected output:
# === Orphan Detection ===
# ⚠️ ORPHANED: src/features/architecture_nodes.py
# No production imports found
#
# === Results ===
# Modules checked: 45
# ❌ ERROR: 1 orphaned module(s) found
Exit codes:
0- All modules integrated1- Orphaned modules found
See: Full script in Method 2 above
Script 2: check_imports.sh (Focused)
Location: scripts/check_imports.sh
Usage:
# Check specific module
./scripts/check_imports.sh architecture_nodes
# Expected output:
# Checking module: architecture_nodes
# Production imports: 0
# Test imports: 2
# Status: ❌ ORPHANED (only test imports)
Script:
#!/bin/bash
# Check if a specific module is imported in production code
MODULE=$1
if [ -z "$MODULE" ]; then
echo "Usage: $0 <module_name>"
exit 1
fi
echo "Checking module: $MODULE"
# Count production imports
PROD=$(grep -r "from.*$MODULE import\|import.*$MODULE" src/ --include="*.py" | \
grep -v test | wc -l | tr -d ' ')
# Count test imports
TEST=$(grep -r "from.*$MODULE import\|import.*$MODULE" tests/ --include="*.py" | \
wc -l | tr -d ' ')
echo "Production imports: $PROD"
echo "Test imports: $TEST"
if [ "$PROD" -eq 0 ]; then
if [ "$TEST" -gt 0 ]; then
echo "Status: ❌ ORPHANED (only test imports)"
else
echo "Status: ❌ ORPHANED (no imports at all)"
fi
exit 1
else
echo "Status: ✅ INTEGRATED"
exit 0
fi
Script 3: check_callsites.sh (Function-Level)
Location: scripts/check_callsites.sh
Usage:
# Check if function is called
./scripts/check_callsites.sh create_architecture_review_node
# Expected output:
# Checking function: create_architecture_review_node
# Definitions: 1
# Call-sites: 0
# Status: ❌ ORPHANED (defined but never called)
Script:
#!/bin/bash
# Check if a function is called in production code
FUNCTION=$1
if [ -z "$FUNCTION" ]; then
echo "Usage: $0 <function_name>"
exit 1
fi
echo "Checking function: $FUNCTION"
# Count definitions
DEFS=$(grep -r "def $FUNCTION" src/ --include="*.py" | wc -l | tr -d ' ')
# Count call-sites (excluding definitions and tests)
CALLS=$(grep -r "$FUNCTION" src/ --include="*.py" | \
grep -v "def $FUNCTION" | \
grep -v test | \
wc -l | tr -d ' ')
echo "Definitions: $DEFS"
echo "Call-sites: $CALLS"
if [ "$CALLS" -eq 0 ]; then
echo "Status: ❌ ORPHANED (defined but never called)"
exit 1
else
echo "Status: ✅ CALLED ($CALLS call-sites)"
exit 0
fi
Integration with Quality Gates
Add to Pre-Commit Quality Gates
In quality-run-quality-gates skill:
### Gate 6: Integration Verification (MANDATORY for new modules)
When the change involves new files or modules:
```bash
# Detect orphaned modules
./scripts/verify_integration.sh
# For LangGraph changes
uv run pytest tests/integration/test_graph_completeness.py -v
Mandatory when:
- Creating new
.pyfiles - Adding new features
- Modifying integration points (builder.py, main.py, etc.)
Failure means: Code exists but won't execute at runtime.
### Add to ADR Completion Checklist
**In `create-adr-spike` skill:**
```markdown
### Phase 6: Integration Verification
Before moving ADR to completed:
- [ ] Run: `./scripts/verify_integration.sh` (passes)
- [ ] No orphaned modules detected
- [ ] All new modules imported in production code
- [ ] All new functions have call-sites
Add to CI/CD Pipeline
In .github/workflows/quality.yml (or equivalent):
- name: Detect Orphaned Code
run: |
./scripts/verify_integration.sh
Effect: Prevents merging PRs with orphaned code
Supporting Files
References
references/orphan-detection-theory.md- Why orphaned code occursreferences/adr-013-orphan-analysis.md- Case study of ADR-013 orphaned codereferences/vulture-vs-integration-check.md- Why vulture isn't enough
Examples
examples/orphan-module-detection.md- Step-by-step module detectionexamples/orphan-function-detection.md- Step-by-step function detectionexamples/fixing-orphaned-code.md- How to fix orphaned code
Scripts
scripts/verify_integration.sh- Comprehensive orphan detectionscripts/check_imports.sh- Module-specific import checkscripts/check_callsites.sh- Function-specific call-site check
Templates
templates/orphan-detection-report.md- Report format for findings
Expected Outcomes
Successful Detection (No Orphans)
$ ./scripts/verify_integration.sh
=== Orphan Detection ===
Checking for orphaned modules in src/...
=== Results ===
Modules checked: 45
✅ All modules are integrated
Failed Detection (Orphans Found)
$ ./scripts/verify_integration.sh
=== Orphan Detection ===
Checking for orphaned modules in src/...
⚠️ ORPHANED: src/temet_run/coordination/graph/architecture_nodes.py
No production imports found
⚠️ ORPHANED: src/temet_run/coordination/graph/task_provider_nodes.py
No production imports found
=== Results ===
Modules checked: 45
❌ ERROR: 2 orphaned module(s) found
These files exist but are never imported in production code.
To fix, either:
1. Wire them up (add imports and call-sites)
2. Remove them if no longer needed
3. Export via __init__.py if they're part of the public API
Integration Test Failure
$ uv run pytest tests/integration/test_graph_completeness.py -v
FAILED tests/integration/test_graph_completeness.py::test_all_expected_nodes_in_graph
AssertionError: Nodes in EXPECTED_NODES but not in graph: ['architecture_review', 'retrieve_tasks'].
Either wire these nodes into builder.py or remove from EXPECTED_NODES.
Requirements
Tools Required
- Read (to examine source files)
- Grep (to search for imports/calls)
- Bash (to run detection scripts)
- Glob (to find files)
Environment Required
- Project structure with
src/directory - Standard Python project layout
- Ability to execute bash scripts
Knowledge Required
- Understanding of Python import system
- Familiarity with project structure
- Knowledge of integration points (main.py, builder.py, etc.)
Red Flags to Avoid
Do Not
- ❌ Trust unit tests alone (they can import orphaned code)
- ❌ Assume code is integrated because it compiles
- ❌ Skip orphan detection for "small" changes
- ❌ Ignore orphan warnings as "false positives"
- ❌ Rely on vulture alone (can miss test-imported code)
- ❌ Mark features complete without running detection
- ❌ Move ADRs to completed without checking orphans
Do
- ✅ Run orphan detection before marking work complete
- ✅ Add new modules to integration tests immediately
- ✅ Verify imports exist in production code (not just tests)
- ✅ Check both module-level and function-level orphans
- ✅ Fix orphans immediately (wire or remove)
- ✅ Add orphan detection to quality gates
- ✅ Update
EXPECTED_NODESwhen adding nodes - ✅ Treat orphan warnings as failures, not suggestions
Notes
- This skill was created in response to ADR-013 (2025-12-07)
- ADR-013: 313 lines of orphaned code passed all quality gates
- Orphaned code can exist with 100% test coverage
- Unit tests can make orphaned code appear "alive" to dead code tools
- This skill complements vulture but checks integration explicitly
- Pair with
quality-verify-implementation-completefor full coverage - Integrate with
util-manage-todo(Phase 2: Connection verification)
Remember: Code that exists but is never imported is technical debt. Detect and fix orphans before marking work complete.
Didn't find tool you were looking for?