test-guided-bug-detector — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited test-guided-bug-detector (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Analyze failing tests to detect and explain functional bugs in code.
When tests fail, they provide valuable clues about bugs in the code. This skill analyzes:
The goal is to identify the root cause bug and explain why the test exposes it.
Failing Test Output
↓
Parse Failure Information
↓
Identify Test Expectations
↓
Trace Execution Path
↓
Analyze Discrepancy
↓
Identify Suspicious Code
↓
Explain Bug Mechanism
↓
Suggest FixExtract key information from test output:
What to extract:
Example:
FAILED tests/test_calculator.py::test_divide - AssertionError: assert 0 == 5
Expected: 5
Actual: 0
Stack trace:
File "tests/test_calculator.py", line 15, in test_divide
assert divide(10, 2) == 5
File "src/calculator.py", line 8, in divide
return a // bDetermine what the test is trying to verify:
Questions to answer:
Example:
def test_divide():
# Intent: Verify division returns correct result
result = divide(10, 2)
assert result == 5 # Expects 10 / 2 = 5Follow the code path from test to failure:
Trace elements:
Example trace:
test_divide()
→ divide(10, 2)
→ return a // b (integer division)
→ returns 5
→ assert 5 == 5 ✓ Should pass!Find where expected and actual diverge:
Common discrepancies:
Example:
# Expected: 10 / 2 = 5.0
# Actual: 10 // 2 = 5 (but test got 0?)
# Discrepancy: Something else is wrong!Examine code for bug patterns:
Bug patterns to check:
Example analysis:
def divide(a, b):
result = 0 # BUG: Initialized but never updated!
return a // b # This line is unreachable? No, wait...
# Actually, this returns correctly, but...Describe how the bug causes the failure:
Explanation structure:
Propose concrete fix with explanation:
Fix components:
For detailed bug patterns and detection strategies, see references/bug_patterns.md.
Categories include:
For analyzing different types of test failures, see references/failure_types.md.
Failure types:
Input: Failing test
# Test file: tests/test_list_utils.py
def test_remove_duplicates():
input_list = [1, 2, 2, 3, 3, 3, 4]
result = remove_duplicates(input_list)
assert result == [1, 2, 3, 4]
assert input_list == [1, 2, 2, 3, 3, 3, 4] # Original unchanged
# Test output:
# FAILED - AssertionError: assert [1, 2, 3, 4] == [1, 2, 2, 3, 3, 3, 4]
# The second assertion failed!
# Implementation: src/list_utils.py
def remove_duplicates(lst):
seen = set()
i = 0
while i < len(lst):
if lst[i] in seen:
lst.pop(i) # BUG: Modifies input list!
else:
seen.add(lst[i])
i += 1
return lstOutput: Bug analysis
# Bug Analysis Report
## Test Failure Summary
**Test:** test_remove_duplicates
**Location:** tests/test_list_utils.py:2
**Failure Type:** Assertion failure
**Failed Assertion:** `assert input_list == [1, 2, 2, 3, 3, 3, 4]`
## Expected vs Actual
**Expected:** Original list unchanged: `[1, 2, 2, 3, 3, 3, 4]`
**Actual:** Original list modified: `[1, 2, 3, 4]`
## Root Cause
**Bug Location:** src/list_utils.py:7
**Bug Type:** Unintended side effect (input mutation)
**Problematic Code:**lst.pop(i) # Modifies the input list directly
## Bug Mechanism
1. **What happens:** The function modifies the input list in-place using `lst.pop(i)`
2. **Why it's wrong:** The test expects the original list to remain unchanged
3. **How test exposes it:** Second assertion checks that input_list is unmodified
4. **Why it fails:** Since Python passes lists by reference, modifications to `lst`
affect the original `input_list`
## Execution Trace
test_remove_duplicates() input_list = [1, 2, 2, 3, 3, 3, 4] ↓ remove_duplicates(input_list) # lst points to same list as input_list i=0: lst[0]=1, not in seen, add to seen, i=1 i=1: lst[1]=2, not in seen, add to seen, i=2 i=2: lst[2]=2, in seen, lst.pop(2) # Removes from input_list!
i=2: lst[2]=3, not in seen, add to seen, i=3 i=3: lst[3]=3, in seen, lst.pop(3) # Removes from input_list!
i=3: lst[3]=3, in seen, lst.pop(3) # Removes from input_list!
i=3: lst[3]=4, not in seen, add to seen, i=4 return lst # Returns [1, 2, 3, 4] ↓ result = [1, 2, 3, 4] ✓ First assertion passes input_list = [1, 2, 3, 4] ✗ Second assertion fails!
## Suspicious Code Regions
### Primary Suspect: src/list_utils.py:7lst.pop(i) # Direct mutation of input
**Suspicion Level:** HIGH
**Reason:** Modifies input list, violating immutability expectation
### Secondary Suspect: src/list_utils.py:11return lst # Returns reference to modified input
**Suspicion Level:** MEDIUM
**Reason:** Returns same object as input, not a new list
## Recommended Fix
**Option 1: Create a copy (Recommended)**def remove_duplicates(lst): result = [] # Create new list seen = set() for item in lst: if item not in seen: seen.add(item) result.append(item) return result
**Why this fixes it:**
- Creates new list instead of modifying input
- Original list remains unchanged
- Clearer intent
**Option 2: Explicit copy**def remove_duplicates(lst): lst = lst.copy() # Work on a copy seen = set() i = 0 while i < len(lst): if lst[i] in seen: lst.pop(i) else: seen.add(lst[i]) i += 1 return lst
**Why this fixes it:**
- `lst.copy()` creates a shallow copy
- Modifications don't affect original
- Preserves original algorithm structure
## Verification
To verify the fix:
1. Run the failing test: `pytest tests/test_list_utils.py::test_remove_duplicates`
2. Both assertions should pass
3. Add additional test for immutability:def test_remove_duplicates_immutable(): original = [1, 2, 2, 3] original_copy = original.copy() result = remove_duplicates(original) assert original == original_copy # Verify no mutation
## Related Issues
This bug could affect:
- Any code that assumes `remove_duplicates` doesn't modify input
- Functions that reuse the input list after calling `remove_duplicates`
- Concurrent code where multiple threads access the same listFor detailed analysis strategies by language and framework, see references/analysis_strategies.md.
Strategies include:
Watch for these suspicious patterns:
High-priority red flags:
Medium-priority warnings:
# Bug Analysis Report
## Test Failure Summary
- Test name and location
- Failure type
- Failed assertion/error
## Expected vs Actual
- What should happen
- What actually happened
## Root Cause
- Bug location (file:line)
- Bug type
- Problematic code snippet
## Bug Mechanism
- Step-by-step explanation
- Why it's wrong
- How test exposes it
## Execution Trace
- Detailed trace from test to failure
- Variable values at key points
## Suspicious Code Regions
- Primary suspects with evidence
- Secondary suspects
## Recommended Fix
- Proposed code change
- Explanation of why it fixes the bug
- How to verify
## Related Issues
- Other code that might be affectedFor detailed guidance:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.