seed-skills/quality-gates-ci/SKILL.md
Teach agents to define and enforce CI quality gates for diff coverage, flaky tests, performance budgets, security thresholds, and regression health.
npx skillsauth add PramodDutta/qaskills Quality Gates CIInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are a CI quality architect who turns quality expectations into pass or fail gates for code coverage, regression health, flake budgets, performance budgets, security thresholds, and review discipline.
Create a CI quality directory.
mkdir -p ci/quality-gates ci/reports scripts
touch ci/quality-gates/policy.json
touch scripts/check-quality-gates.sh
chmod +x scripts/check-quality-gates.sh
Define a policy file.
{
"diffCoverage": 80,
"flakeRate": 2,
"maxHighSecurityFindings": 0,
"maxCriticalSecurityFindings": 0,
"maxLcpMs": 2500,
"maxBundleKb": 300
}
Use one wrapper to make gate behavior consistent.
#!/usr/bin/env bash
set -euo pipefail
echo "Running quality gates"
npm run lint
npm run test:unit -- --coverage
npm run test:e2e -- --reporter=line
npm run security:scan
npm run perf:budget
echo "Quality gates passed"
Require new or changed code to meet a threshold.
// ci/quality-gates/check-diff-coverage.ts
type CoverageSummary = {
changedLines: number;
coveredChangedLines: number;
};
export function diffCoveragePercent(summary: CoverageSummary): number {
if (summary.changedLines === 0) return 100;
return Math.round((summary.coveredChangedLines / summary.changedLines) * 10000) / 100;
}
export function assertDiffCoverage(summary: CoverageSummary, threshold: number): void {
const percent = diffCoveragePercent(summary);
if (percent < threshold) {
throw new Error(`Diff coverage ${percent}% is below ${threshold}%`);
}
}
assertDiffCoverage({ changedLines: 20, coveredChangedLines: 18 }, 80);
Track flaky tests as a first-class signal.
// ci/quality-gates/check-flake-budget.ts
type TestAttempt = {
testId: string;
attempt: number;
status: 'passed' | 'failed';
};
export function calculateFlakeRate(attempts: TestAttempt[]): number {
const byTest = new Map<string, TestAttempt[]>();
for (const attempt of attempts) {
byTest.set(attempt.testId, [...(byTest.get(attempt.testId) || []), attempt]);
}
const flaky = [...byTest.values()].filter((items) => {
const statuses = new Set(items.map((item) => item.status));
return statuses.has('passed') && statuses.has('failed');
}).length;
return Math.round((flaky / Math.max(byTest.size, 1)) * 10000) / 100;
}
Run gates in parallel where possible, then require the aggregate result.
name: quality-gates
on:
pull_request:
jobs:
gates:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: bash scripts/check-quality-gates.sh
- uses: actions/upload-artifact@v4
if: always()
with:
name: quality-gate-reports
path: ci/reports
| Gate | Pass | Fail | Evidence | |---|---|---|---| | Lint | No errors | Any error | Lint log | | Unit tests | Required suites pass | Confirmed failure | Coverage report | | Diff coverage | At or above threshold | Below threshold | Coverage diff | | E2E smoke | Critical paths pass | Any critical fail | Playwright report | | Flake budget | Under budget | Over budget | Retry history | | Security | No high or critical | High or critical | Scanner report | | Performance | Within budget | Budget exceeded | Trace or metrics |
development
Research market rates, build negotiation strategy, and create counter-offer scripts
data-ai
Track different resume versions, maintain master resume, manage tailored versions
testing
Customize resume for specific job postings while maintaining truthfulness
development
Create targeted resume sections optimized for different experience levels and roles