Find Real Issues
Don't wait for someone to file an issue. find real problems in the code. This skill analyzes a codebase for actual issues that maintainers would appreciate being fixed: missing tests, inconsistent patterns, silent failures, documentation gaps. You evaluate whether they're worth filing. the LLM just finds them.
Purpose
The best contributions aren't always in the issue tracker. Experienced contributors earn maintainer trust by finding and fixing problems nobody asked about. but that everyone benefits from. This skill teaches you to read code critically, spot patterns that are off, and evaluate whether a fix would be welcome.
Prerequisites
- A repo cloned locally
- Basic understanding of the codebase (from
oss-prep-to-contributeor your own exploration) - Check that the repo accepts unsolicited PRs (some don't. verify in CONTRIBUTING.md)
Process
1. Check if unsolicited contributions are welcome
Before analyzing anything:
# Read contribution guidelines
gh api repos/{owner}/{repo}/contents/CONTRIBUTING.md --jq '.content' | base64 -d 2>/dev/null
# Check if unsolicited PRs have been merged before
gh pr list -R {owner}/{repo} --state merged --limit 20 \
--json title,labels,authorAssociation | \
jq '[.[] | select(.authorAssociation != "MEMBER" and .authorAssociation != "OWNER")]'
Look for:
- "Please file an issue before submitting a PR": if present, you should file an issue first, not just submit a fix
- "We welcome contributions": green light
- No external PRs merged. yellow flag, ask in their communication channel first
Inform the user about the repo's stance on unsolicited contributions.
2. Systematic code analysis
Use Explore agents to analyze the codebase across multiple dimensions. For each dimension, look for concrete, specific problems. not vague "could be better" observations.
Dimension 1: Test coverage gaps
# Find source files without corresponding test files
find src/ lib/ -name "*.{ts,py,go,rs}" | while read f; do
test_file=$(echo "$f" | sed 's/src/test/' | sed 's/\.ts/.test.ts/' | sed 's/\.py/test_&/')
[ ! -f "$test_file" ] && echo "No test: $f"
done
# Find exported functions that aren't tested
# {language-specific analysis}
Dimension 2: Error handling gaps
# Find try/catch or error handling patterns and look for inconsistencies
grep -rn "catch\|except\|Error\|panic\|unwrap" src/ --include="*.ts" --include="*.py" --include="*.go" --include="*.rs" | head -30
# Find functions that call external services/APIs without error handling
# {trace external calls}
Dimension 3: Inconsistent patterns
# Compare naming conventions across modules
grep -rn "function\|def \|fn \|func " src/ --include="*.ts" --include="*.py" --include="*.go" --include="*.rs" | head -30
# Look for: camelCase vs snake_case mixing, inconsistent prefixes, different error types for the same kind of failure
# Find multiple approaches to the same problem
# Example: some modules use callbacks, others use promises, others use async/await
grep -rn "callback\|\.then(\|async " src/ --include="*.ts" --include="*.py" --include="*.go" --include="*.rs" | head -20
# Check for deprecated API usage
grep -rn "deprecated\|@deprecated\|DEPRECATED" src/ --include="*.ts" --include="*.py" --include="*.go" --include="*.rs"
Dimension 4: Documentation gaps
# Find README references to files that don't exist
grep -oP '\[.*?\]\(((?!http).*?)\)' README.md 2>/dev/null | while read link; do
file=$(echo "$link" | grep -oP '\(.*?\)' | tr -d '()')
[ ! -f "$file" ] && echo "Broken link: $link -> $file"
done
# Check if setup/install commands in README actually work
# Read the "Getting Started" section and verify each command
# Find public functions/classes without docstrings (Python example)
grep -rn "def \|class " src/ --include="*.py" -A1 | grep -B1 -v '"""' | grep "def \|class "
Dimension 5: Dependency issues
# Language-specific vulnerability checks
npm audit 2>/dev/null # Node.js
pip audit 2>/dev/null # Python (requires pip-audit)
cargo audit 2>/dev/null # Rust
go list -m -json all 2>/dev/null | grep -i "deprecated" # Go
3. Filter for actionable findings
Not every code smell is worth filing. Filter each finding:
| Keep | Discard |
|---|---|
| Missing error handling that could cause silent failures | Style preferences ("I'd do it differently") |
| Untested critical code paths | Test coverage for trivial code |
| Documented behavior that doesn't match implementation | Minor doc typos (unless they cause confusion) |
| Security-relevant issues (input validation, auth checks) | Performance "optimizations" without benchmarks |
| Broken examples in docs | Cosmetic issues |
| Deprecated dependency with known vulnerabilities | Version bumps for non-critical deps |
4. Present findings to the user
For each finding, present:
## Finding #{n}: {one-line summary}
**Category**: {test gap / error handling / inconsistency / docs / security / dependency}
**Severity**: {high. could cause bugs or security issues / medium. code quality / low. cosmetic}
**Location**: `{file}:{line}`
**What's wrong**: {specific description with code reference}
**Impact**: {what could go wrong because of this}
**Suggested approach**: {high-level. not a code fix, just the direction}
**Would a PR be welcome?**: {yes. clearly a bug / maybe. discuss first / probably not. too opinionated}
5. Thinking gate: user evaluates each finding
For each finding, ask the user:
"Look at finding #{n}. I showed you the location and impact above.
- Do you agree this is a real problem? (Look at the code at the location I cited)
- If you were a maintainer, would you merge a PR fixing this?
- What could go wrong if this stays unfixed? (Check the 'Impact' section above)"
This is the most important part. The skill isn't just about finding issues. it's about teaching the user to evaluate code critically. Their judgment matters more than the LLM's analysis.
If the user says "yes, fix it" without articulating WHY:
"Before we proceed. explain why this is a problem. What could go wrong if it stays as-is? A maintainer will ask this in the PR review."
If the user disagrees with a finding:
"Good. that's a valid call. Can you explain why you think it's not an issue? Understanding why something ISN'T a problem is just as valuable."
6. Fetch issue templates
Before filing, check if the repo has issue templates:
# Check for issue template directory (multiple templates)
gh api "repos/{owner}/{repo}/contents/.github/ISSUE_TEMPLATE" \
--jq '[.[] | select(.name != "config.yml") | .name]' 2>/dev/null
# Check for single-file issue template
gh api "repos/{owner}/{repo}/contents/ISSUE_TEMPLATE.md" --jq '.content' 2>/dev/null | base64 -d 2>/dev/null
gh api "repos/{owner}/{repo}/contents/.github/ISSUE_TEMPLATE.md" --jq '.content' 2>/dev/null | base64 -d 2>/dev/null
If a template directory exists: fetch each template file (skip config.yml: it's not a template). Templates can be .md (with YAML frontmatter) or .yml (issue forms). For .md templates, parse the YAML frontmatter (name, description, labels). For .yml issue forms, parse the top-level name, description, and labels fields directly. Present the available templates:
Available issue templates:
1. Bug Report: Report a bug (labels: bug)
2. Feature Request: Suggest an enhancement (labels: enhancement)
3. Documentation: Report a docs issue (labels: documentation)
Ask the user: "Which template matches the issue you're filing?" Fetch the selected template and enforce its structure.
If a single template exists: use it as the required format.
If no templates exist: use the freeform issue format below.
7. File issues or proceed to fix
For findings the user validates:
Option A: File an issue first (recommended for medium+ ch