Enforce Definition of Done by running quality gates (type checking, linting, dead code detection, tests)...
Enforce Definition of Done by detecting and running all quality gates (type checking, linting, dead code detection, tests) for Python, JavaScript, Go, Rust, and other ecosystems. Provides actionable feedback for failures and blocks task completion until all gates pass.
Quick Start ā When to Use | What It Does | Simple Example
How to Implement ā Detection Process | Execution Workflow | Outcomes
Automation ā Scripts | Templates | Supporting Files
Help ā Anti-Patterns | Output Format | Integration
Reference ā Tool Reference | Common Failures
MANDATORY in these situations:
User trigger phrases:
Additional detection patterns:
Enforces the Definition of Done by:
Result: ā All gates pass (task truly done) or ā Failures (with specific fixes needed)
User: "I'm done implementing the new feature"
Claude invokes skill:
ā Detects Python project with check_all.sh
ā Runs: ./scripts/check_all.sh
ā Reports results
Output:
ā
All 6 checks passed (pyright, vulture, pytest, ruff, ruff format, ty)
ā
DEFINITION OF DONE: MET
Task is complete and ready for commit.
User: "Run quality gates"
Claude invokes skill:
ā Runs quality gates
ā Detects 3 failures
Output:
ā 3 of 6 checks failed: pyright, pytest, ruff
š pyright failures (3 errors):
src/services/search.py:45 - Type "None" cannot be assigned to "str"
src/utils/helper.py:12 - Argument of type "int" cannot be assigned to "Optional[str]"
š pytest failures (2 errors):
tests/unit/test_search.py::test_search_empty - AssertionError
š ruff failures (1 error):
src/services/search.py:23 - F401 Unused import: logging
Next steps:
1. Fix type errors (make parameters non-optional)
2. Fix test assertions
3. Remove unused imports
4. Re-run quality gates
ā DEFINITION OF DONE: NOT MET
Task is NOT complete until all gates pass.
Running quality gates involves 5 key steps:
See detailed workflow in Execution Workflow section below.
Check for unified script (preferred):
./scripts/check_all.sh (Python projects)npm run check (JavaScript/TypeScript projects)make check (Makefile-based projects)Fallback to individual tools by detecting project type:
Detect via: pyproject.toml, requirements.txt, setup.py
Tools to run:
uv run pyright or mypyuv run ruff check or pylint or flake8uv run vulture src/ --min-confidence 80uv run pytest tests/ -quv run ruff format --check or black --checkDetect via: package.json, tsconfig.json
Tools to run:
npx tsc --noEmitnpx eslint src/npm test or npx jest or npx vitestnpx prettier --check src/Detect via: go.mod
Tools to run:
go build ./...golangci-lint rungo test ./...go fmt ./...Detect via: Cargo.toml
Tools to run:
cargo checkcargo clippycargo testcargo fmt --checkRead project-specific quality gates from:
CLAUDE.md (Definition of Done section)pyproject.toml (Python)package.json (JavaScript/TypeScript).pre-commit-config.yaml (Pre-commit hooks)# Check for unified script
if [ -f ./scripts/check_all.sh ]; then
RUNNER="./scripts/check_all.sh"
elif [ -f package.json ] && grep -q '"check"' package.json; then
RUNNER="npm run check"
elif [ -f Makefile ] && grep -q "^check:" Makefile; then
RUNNER="make check"
else
# Fallback to individual tools (detect project type)
...
fi
# Run unified script or individual tools
$RUNNER
# Capture output and exit code
EXIT_CODE=$?
Extract failures by tool:
error: or error[.py:line:col: or .js:line:col:unused or dead codeFAILED or ERROR collectingFor each failure category, provide:
After user applies fixes:
# Re-run quality gates
$RUNNER
# Verify all pass
if [ $? -eq 0 ]; then
echo "ā
All quality gates passed"
echo "ā
DEFINITION OF DONE: MET"
else
echo "ā Some gates still failing"
# Repeat steps 3-4
fi
User: "I'm done with the feature"
Wrong Response:
ā
Great! The feature is complete.
Correct Response (Invoke Skill):
Let me verify the feature meets Definition of Done by running quality gates...
ā Runs quality gates
ā Reports results (pass/fail)
ā Only declares "done" if all gates pass
User: "Some tests are failing but the main logic works"
Wrong Response:
ā
The core functionality is complete. The test failures are minor.
Correct Response:
ā DEFINITION OF DONE: NOT MET
Quality gates must pass before declaring done:
- 2 tests failing in tests/unit/test_search.py
- 1 type error in src/services/search.py
Let me fix these issues...
[Proceeds to fix each failure]
User: "Let's commit this and fix the lint errors later"
Wrong Response:
ā
Creating commit...
Correct Response:
ā Cannot commit - quality gates failing:
- 3 ruff lint errors
- 1 unused import
Project policy: All gates must pass before commit.
Let me fix these now (takes ~30 seconds)...
User: "I added the feature but didn't write tests yet"
Wrong Response:
ā
Feature added successfully.
Correct Response:
ā ļø DEFINITION OF DONE: INCOMPLETE
Feature implemented but missing:
- Unit tests for new functionality
- Integration tests for end-to-end flow
Project policy: Tests required before declaring done.
Let me add tests now...
User: "I ran ruff check and fixed all linting errors"
Wrong Response:
ā
Code quality verified - all linting issues resolved.
Correct Response:
ā ļø PARTIAL QUALITY CHECK DETECTED
You ran: ruff check ā
(linting passed)
Missing: type checking, tests, dead code detection
Running complete quality gate suite...
ā pyright (type checking)
ā pytest (tests)
ā vulture (dead code)
ā ruff format (formatting)
[Runs all gates and reports results]
Detection signals:
ruff check --fix)check_all.sh or equivalentWhy this matters: Linting alone doesn't verify:
Real-world example:
User ran: ruff check --fix
Missed issues:
- 3 type errors in src/layout_io.py (pyright would catch)
- 1 failing test in tests/test_save.py (pytest would catch)
- 2 unused imports (ruff found but user only ran check, not full suite)
š¦ Quality Check Results
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā
pyright [2s]
ā
vulture [1s]
ā
pytest [3s]
ā
ruff [1s]
ā
ruff format [1s]
ā
ty [2s]
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā
All 6 checks passed
ā
DEFINITION OF DONE: MET
- All type checks passed
- All linting passed
- All tests passed (100% pass rate)
- No dead code detected
- Code formatting correct
Task is complete and ready for commit.
š¦ Quality Check Results
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā pyright [2s]
š pyright failures:
src/services/search.py:45 - error: Type "None" cannot be assigned to type "str"
src/utils/helper.py:12 - error: Argument of type "int" cannot be assigned to parameter of type "Optional[str]"
ā pytest [3s]
š pytest failures:
FAILED tests/unit/test_search.py::test_search_empty - AssertionError: Expected [] but got None
ā ruff [1s]
š ruff failures:
src/services/search.py:23 - F401 [*] `logging` imported but unused
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā 3 of 6 checks failed: pyright, pytest, ruff
ā DEFINITION OF DONE: NOT MET
Required fixes:
1. Type Errors (HIGH priority):
- src/services/search.py:45 - Make return type non-optional or handle None case
- src/utils/helper.py:12 - Convert int to str or change parameter type
2. Test Failures (HIGH priority):
- tests/unit/test_search.py::test_search_empty - Update assertion to handle None case
3. Lint Errors (MEDIUM priority):
- src/services/search.py:23 - Remove unused logging import
Next steps:
1. Fix each issue systematically (start with HIGH priority)
2. Re-run quality gates after each fix
3. Repeat until all gates pass
If project has ./scripts/check_all.sh:
# Skill detects script and uses it directly
./scripts/check_all.sh
# Parses output (already formatted for agent consumption)
# Returns structured results
Skill can be invoked by pre-commit hooks:
# .pre-commit-config.yaml
- repo: local
hooks:
- id: quality-gates
name: Run Quality Gates
entry: claude-skill run-quality-gates
language: system
pass_filenames: false
Before marking todo as completed:
# ā WRONG - Mark completed without validation
TodoWrite([{"content": "Implement search", "status": "completed"}])
# ā
CORRECT - Validate first
run_quality_gates() # Invoke skill
if all_gates_pass:
TodoWrite([{"content": "Implement search", "status": "completed"}])
Agents should invoke this skill before declaring tasks complete:
@implementer completes feature implementation
ā @implementer invokes run-quality-gates skill
ā Skill runs all gates
ā If pass: Mark todo as completed
ā If fail: Fix issues, re-run gates
Projects can define custom quality gates in CLAUDE.md:
## Quality Gates (MANDATORY)
Run before saying "done":
```bash
./scripts/check_all.sh # Runs all checks in parallel
Individual checks if needed:
uv run pyright # Type checking
uv run vulture src/ # Dead code detection
uv run pytest tests/ # Test suite
uv run ruff check src/ # Linting
Non-negotiable: Task is NOT done if quality gates fail. Fix or explain why.
Skill will read this section and use the specified commands.
### Custom Tool Detection
For projects with non-standard setups, create `.claude/quality-gates.json`:
```json
{
"runner": "./custom_check_script.sh",
"tools": {
"type_checker": "uv run pyright",
"linter": "uv run ruff check",
"dead_code": "uv run vulture src/",
"tests": "uv run pytest tests/",
"formatter": "uv run ruff format --check"
},
"required": ["type_checker", "linter", "tests"],
"optional": ["dead_code", "formatter"]
}
ā
All 6 checks passed
ā
DEFINITION OF DONE: MET
Task is complete and ready for commit.
Agent response:
ā 3 of 6 checks failed: pyright, pytest, ruff
ā DEFINITION OF DONE: NOT MET
Agent response:
ā After 3 fix attempts, 1 gate still failing
ā Type error may require architectural change
Agent response:
ā ļø No quality gate tools detected
ā ļø Cannot validate Definition of Done
Agent response:
| Metric | Target | Current |
|---|---|---|
| Gates run before declaring "done" | 100% | TBD |
| False "done" declarations | 0% | TBD |
| Quality gate pass rate | 100% | TBD |
| Time to run gates | <10s | TBD |
| Fix accuracy (first attempt) | >80% | TBD |
# User: "I'm done implementing the feature"
# Skill invocation:
Skill(command: "run-quality-gates")
# Output: All gates pass, ready to commit
ā
All 6 checks passed
ā
DEFINITION OF DONE: MET
# User: "Run quality gates"
# Skill invocation:
Skill(command: "run-quality-gates")
# Output: 3 failures with specific fixes
ā 3 of 6 checks failed
Fix pyright errors, pytest failures, ruff violations
Solution:
# Use optimized check_all.sh (runs in parallel: 8s vs 31s)
./scripts/check_all.sh
# For incremental changes, run only affected checks
uv run pyright --files-changed
uv run ruff check --diff
Solution:
# Add exclusions to pyproject.toml
[tool.vulture]
exclude = ["tests/", "*.pyi"]
min_confidence = 80
Solution:
# Ensure same environment
uv sync
uv run pytest tests/ -v
# Check for environment-specific issues
# - Database connections
# - File paths
# - Network dependencies
See Troubleshooting and Usage Examples sections above for comprehensive guidance including:
run-quality-gates integrates with:
Agents should invoke this skill:
Integration pattern:
# Before marking todo as completed
run_quality_gates() # Invoke skill
if all_gates_pass:
TodoWrite([{"content": "Task", "status": "completed"}])
else:
# Fix issues first
pass
| Metric | Without Quality Gates | With Quality Gates | Improvement |
|---|---|---|---|
| Bugs in production | 15-20 per release | 2-3 per release | 85% reduction |
| Time to fix bugs | 2-4 hours | 15-30 min | 75% faster |
| Code review time | 30-60 min | 10-20 min | 60% faster |
| Test coverage | 60-70% | 85-95% | 30% increase |
| Merge conflicts | 5-10 per week | 1-2 per week | 80% reduction |
| Rework after review | 40-60% of PRs | 5-10% of PRs | 85% reduction |
No external dependencies - Skill adapts to whatever tools are already installed in the project.
Minimum requirements:
Optional:
CLAUDE.md with Definition of Done section (for custom configuration).claude/quality-gates.json (for explicit tool specification)