python-quality-gate
$
npx mdskill add notque/vexjoy-agent/python-quality-gateEnforce Python code standards with automated linting and testing.
- Executes ruff, pytest, mypy, and bandit sequentially to validate code.
- Reads project configuration files to determine tool settings.
- Generates structured reports with severity levels and auto-fix commands.
- Triggers automatically on code quality requests or pre-commit hooks.
SKILL.md
.github/skills/python-quality-gateView on GitHub ↗
---
name: python-quality-gate
description: "Python quality checks: ruff, pytest, mypy, bandit in deterministic order."
user-invocable: false
allowed-tools:
- Read
- Write
- Bash
- Grep
- Glob
- Edit
- Task
- Skill
agent: python-general-engineer
routing:
force_route: true
triggers:
- "Python quality"
- "ruff check"
- "bandit scan"
- "mypy check"
- "python lint"
- "python quality gate"
- "check python"
- "pre-commit check"
category: code-quality
pairs_with:
- code-linting
- test-driven-development
---
# Python Quality Gate Skill
Run four quality tools in deterministic order -- ruff, pytest, mypy, bandit -- and produce a structured pass/fail report with severity-categorized issues and auto-fix commands.
## Reference Loading Table
| Signal | Load These Files | Why |
|---|---|---|
| tasks related to this reference | `report-template.md` | Loads detailed guidance from `report-template.md`. |
| tasks related to this reference | `tool-commands.md` | Loads detailed guidance from `tool-commands.md`. |
## Instructions
### Phase 1: Detection and Setup
**Step 1: Read CLAUDE.md and detect project configuration.**
Read and follow the repository's CLAUDE.md before any execution. Then detect project configuration:
```bash
ls -la pyproject.toml setup.py setup.cfg mypy.ini .python-version 2>/dev/null
```
Identify Python version target, ruff config, pytest config, mypy config from pyproject.toml. Only validate code -- never add tools, features, or flexibility not requested.
**Step 2: Detect source and test directories.**
```bash
ls -d src/ app/ lib/ 2>/dev/null || echo "Source: current directory"
ls -d tests/ test/ 2>/dev/null || echo "Tests: not found"
```
**Step 3: Verify tool availability.**
```bash
ruff --version
pytest --version
mypy --version || echo "mypy not installed (optional)"
bandit --version || echo "bandit not installed (optional)"
```
If ruff or pytest are missing, STOP. These are required:
```
ERROR: Required tool not found: {tool_name}
Install with: pip install ruff pytest pytest-cov
```
Do not install missing tools automatically unless the user explicitly requests it. Do not modify pyproject.toml or configuration files unless explicitly asked.
**Gate**: ruff and pytest available. Project structure identified. Proceed only when gate passes.
### Phase 2: Execute Quality Checks
Run all checks in fixed order, capturing full output for each. Show complete command output with exact file paths and line numbers -- never summarize or paraphrase tool output, because summarization hides the details engineers need to locate and fix issues.
**Step 1: Ruff linting.**
```bash
ruff check . --output-format=grouped
```
**Step 2: Ruff formatting check.**
```bash
ruff format --check .
```
**Step 3: Type checking with mypy** (if installed).
```bash
mypy . --ignore-missing-imports --show-error-codes
```
Skip and note in report if mypy is not installed. Even if tests pass, still run mypy when available -- tests check behavior while types check contracts, and passing one does not make the other redundant.
**Step 4: Run test suite.**
```bash
pytest -v --tb=short --cov=src --cov-report=term-missing
```
If no tests directory exists, skip and note in report. Never skip tests to make the gate pass -- tests verify functionality, and skipping them hides broken code. Only skip optional tools (mypy, bandit) if genuinely unavailable, not to manufacture a passing status.
**Step 5: Security scanning with bandit** (if installed).
```bash
bandit -r src/ -ll --format=screen
```
Skip and note in report if bandit is not installed. Linting passing does not mean code is correct -- linting finds style issues, not logic or security bugs. Run every available tool.
**Gate**: All available tools have been run. Full output captured. Proceed to analysis.
### Phase 3: Categorize and Analyze
**Step 1: Categorize issues by severity.**
See `references/tool-commands.md` for complete severity classification tables.
Summary of severity levels:
- **Critical**: F errors (pyflakes), E9xx (syntax), undefined names, test failures, high-severity security
- **High**: E501, E711/E712, F841, N8xx, arg-type/assignment mypy errors
- **Medium**: W warnings, C4xx, no-untyped-def mypy errors
- **Low**: SIM suggestions, UP upgrade suggestions
Always prioritize critical issues over style fixes -- critical issues (F errors, test failures) break functionality while style issues do not. Fix critical first, high second; use auto-fix for bulk style cleanup only after critical issues are resolved.
**Step 2: Count auto-fixable issues.**
```bash
ruff check . --statistics
```
Issues marked with `[*]` are auto-fixable. Show suggested auto-fix commands for these issues so users know what can be fixed automatically.
**Step 3: Determine overall status.**
FAIL if:
- Any ruff F errors or test failures
- Any high-severity bandit issues
- Mypy errors exceed 10 (configurable)
- Test coverage below 80% (if coverage enabled)
PASS otherwise. Exit with non-zero status if any critical check fails.
**Gate**: All issues categorized. Pass/fail determined. Proceed to report.
### Phase 4: Generate Report
Format a structured markdown report. See `references/report-template.md` for the full template.
The report MUST include:
1. Overall PASS/FAIL status
2. Summary table (each tool's status and issue count)
3. Total issues and auto-fixable count
4. Detailed results per tool (issues grouped by severity, then grouped by type and file for readability)
5. Critical issues requiring attention with file:line references
6. Auto-fix commands section
7. Quality metrics: error counts and coverage percentages
Report facts -- show raw command output rather than describing it. No self-congratulation ("great job", "looking good"). Generate the full report even when only style issues are found, because style issues can hide real problems in noise and a full severity-prioritized report surfaces them.
Print the complete report to stdout. Never summarize or truncate. If `--output {file}` flag was provided, also write report to file. Remove any intermediate temporary files at completion -- keep the final report only if the user requested file output.
**Gate**: Report generated and displayed. Task complete.
### Auto-Fix Mode (only when explicitly requested)
Auto-fix modifies files in place -- never run it without explicit user confirmation. Running `ruff --fix` blindly can change code semantics (import removal, reformatting), so always run check-only first, review issues, confirm auto-fix intent, then verify changes.
When user explicitly requests auto-fix:
```bash
ruff check . --fix
ruff format .
```
After auto-fix, show the diff so changes can be reviewed, then re-run the quality gate to verify:
```bash
git diff
```
## Examples
### Example 1: Pre-Merge Quality Check
User says: "Run quality checks before I merge this PR"
Actions:
1. Detect project config and available tools (Phase 1)
2. Run ruff check, ruff format, mypy, pytest, bandit in order (Phase 2)
3. Categorize 12 issues: 0 critical, 3 high, 9 medium (Phase 3)
4. Generate report showing PASSED with 3 high-priority suggestions (Phase 4)
Result: Structured report with actionable fix commands
### Example 2: Quality Gate Failure
User says: "Check code quality on the payments module"
Actions:
1. Detect config, find src/payments/ directory (Phase 1)
2. Run all tools -- pytest shows 2 failures, ruff finds F401 errors (Phase 2)
3. Categorize: 2 critical (test failures), 1 critical (undefined name), 5 medium (Phase 3)
4. Generate FAILED report with critical issues listed first (Phase 4)
Result: FAILED status with prioritized fix list, auto-fix commands for 5 medium issues
## Error Handling
### Error: "ruff: command not found"
**Cause**: Ruff is not installed in the current environment
**Solution**: Install with `pip install ruff`. Do not proceed without ruff -- exit with status 2.
### Error: "Tests failed with exit code 1"
**Cause**: pytest found test failures
**Solution**: This is expected behavior, not a tool error. Parse output, include failure details in report, mark overall status as FAILED, continue with remaining checks.
### Error: "No Python files found"
**Cause**: Running from wrong directory or not a Python project
**Solution**: Verify location with `ls pyproject.toml src/ tests/`. Run from project root.
### Error: "Mypy cache corruption"
**Cause**: Stale or corrupted .mypy_cache directory
**Solution**: Clear cache with `rm -rf .mypy_cache` and retry. If mypy continues to fail, skip type checking and note in report.
## References
### Reference Files
- `${CLAUDE_SKILL_DIR}/references/tool-commands.md`: Severity classifications, expected output formats, CLI flags
- `${CLAUDE_SKILL_DIR}/references/report-template.md`: Full structured report template
- `${CLAUDE_SKILL_DIR}/references/pyproject-template.toml`: Complete ruff, pytest, mypy, bandit configuration
More from notque/vexjoy-agent
- adr-consultationMulti-agent consultation for architecture decisions.
- agent-comparisonA/B test agent variants for quality and token cost.
- agent-evaluationEvaluate agents and skills for quality and standards compliance.
- architecture-deepeningProactive architecture improvement: find shallow modules, propose deepening opportunities, design conversation.
- auto-dreamBackground memory consolidation and learning graduation — overnight knowledge lifecycle.
- bluesky-readerRead public Bluesky feeds via AT Protocol API.
- cobalt-coreCobalt Core infrastructure knowledge: KVM exporters, hypervisor tooling, OpenStack compute.
- code-cleanupDetect stale TODOs, unused imports, and dead code.
- code-lintingRun Python (ruff) and JavaScript (Biome) linting.
- codebase-analyzerStatistical rule discovery from Go codebase patterns.