Overview
Quality gates are automated checkpoints that run linting, typechecking, and tests at strategic moments during development. They help catch issues early and maintain code quality throughout the session.
Configuration
Quality gates are configured in your project’s config.json:
{
"quality_gates" : {
"run_lint" : true ,
"run_typecheck" : true ,
"run_tests" : true ,
"lint_command" : "npm run lint" ,
"typecheck_command" : "npm run typecheck" ,
"test_command" : "npm test -- --related"
}
}
Enable automatic linting at quality gate checkpoints
quality_gates.run_typecheck
Enable automatic type checking at quality gate checkpoints
Enable automatic test execution at quality gate checkpoints
quality_gates.lint_command
string
default: "npm run lint"
Shell command to run linting
quality_gates.typecheck_command
string
default: "npm run typecheck"
Shell command to run type checking
quality_gates.test_command
string
default: "npm test -- --related"
Shell command to run tests (typically only affected tests)
When Quality Gates Run
Quality gates trigger automatically at strategic checkpoints:
Edit Count Thresholds
The system tracks edits and prompts for validation:
Checkpoint Default Threshold Action First 5 edits Review checkpoint - suggest git diff --stat Second 10 edits Run full quality gates Repeat Every 10 edits Run quality gates again
Thresholds are adaptive based on your correction history. If recent sessions have high correction rates, thresholds tighten automatically (e.g., 3/6/6 instead of 5/10/10).
Adaptive Thresholds
The quality gate script analyzes your recent sessions to determine optimal checkpoint frequency:
if ( correctionRate > 0.25 ) {
return { first: 3 , second: 6 , repeat: 6 }; // Tight gates
} else if ( correctionRate > 0.15 ) {
return { first: 5 , second: 10 , repeat: 10 }; // Default
} else if ( correctionRate > 0.05 ) {
return { first: 8 , second: 15 , repeat: 15 }; // Relaxed
} else {
return { first: 10 , second: 20 , repeat: 20 }; // Very relaxed
}
Correction rate = corrections_count / edit_count across last 10 sessions.
Hook Integration
Quality gates work seamlessly with the hook system:
PostEdit hook (automatic)
PreCommit hook (validation)
{
"PostEdit" : [{
"command" : "node scripts/quality-gate.js" ,
"background" : true
}]
}
PostEdit Hook
Runs after every file edit to track edit count and trigger checkpoints:
[ProWorkflow] 5 edits — checkpoint for review
[ProWorkflow] Run: git diff --stat | to see changes
[ProWorkflow] 10 edits — run quality gates:
[ProWorkflow] npm run lint && npm run typecheck && npm test --changed
PreCommit Hook
Runs validation before allowing commits to proceed:
# If quality gates fail, commit is blocked
✗ Lint errors found
✗ Type errors: 3 issues
✗ Tests failed: 2 tests
PreCommit hook failed. Fix issues before committing.
Wrap-Up Integration
Quality gates also run during wrap-up phase:
{
"wrap_up" : {
"check_uncommitted" : true ,
"verify_tests" : true ,
"update_claude_md" : true ,
"create_summary" : true
}
}
wrap_up.check_uncommitted
Check for uncommitted changes and prompt for action
Run tests one final time before session ends
Update CLAUDE.md with learned patterns
Generate session summary with changes and decisions
Commands Configuration
Customize quality gate commands for your project’s tooling:
{
"quality_gates" : {
"lint_command" : "npm run lint -- --fix"
}
}
TypeScript with strict mode
{
"quality_gates" : {
"typecheck_command" : "tsc --noEmit --strict"
}
}
Jest with coverage threshold
{
"quality_gates" : {
"test_command" : "jest --coverage --coverageThreshold=80 --onlyChanged"
}
}
Vitest for unit tests only
{
"quality_gates" : {
"test_command" : "vitest run --changed --testNamePattern='unit'"
}
}
Parallel execution (faster)
{
"quality_gates" : {
"lint_command" : "npm run lint & npm run typecheck & npm test -- --related"
}
}
Quality Gate Script
The reference implementation from scripts/quality-gate.js:
#!/usr/bin/env node
const fs = require ( 'fs' );
const path = require ( 'path' );
const os = require ( 'os' );
function getTempDir () {
return path . join ( os . tmpdir (), 'pro-workflow' );
}
function getAdaptiveThreshold ( store ) {
if ( ! store ) return { first: 5 , second: 10 , repeat: 10 };
try {
const sessions = store . getRecentSessions ( 10 );
if ( sessions . length < 3 ) return { first: 5 , second: 10 , repeat: 10 };
const totalEdits = sessions . reduce (( s , sess ) => s + sess . edit_count , 0 );
const totalCorrections = sessions . reduce (( s , sess ) => s + sess . corrections_count , 0 );
const correctionRate = totalEdits > 0 ? totalCorrections / totalEdits : 0 ;
if ( correctionRate > 0.25 ) {
return { first: 3 , second: 6 , repeat: 6 };
} else if ( correctionRate > 0.15 ) {
return { first: 5 , second: 10 , repeat: 10 };
} else if ( correctionRate > 0.05 ) {
return { first: 8 , second: 15 , repeat: 15 };
} else {
return { first: 10 , second: 20 , repeat: 20 };
}
} catch ( e ) {
return { first: 5 , second: 10 , repeat: 10 };
}
}
async function main () {
const sessionId = process . env . CLAUDE_SESSION_ID || String ( process . ppid ) || 'default' ;
let count = 1 ;
let threshold = { first: 5 , second: 10 , repeat: 10 };
// Track edits and determine threshold...
if ( count === threshold . first ) {
console . error ( `[ProWorkflow] ${ count } edits — checkpoint for review` );
console . error ( '[ProWorkflow] Run: git diff --stat | to see changes' );
}
if ( count === threshold . second ) {
console . error ( `[ProWorkflow] ${ count } edits — run quality gates:` );
console . error ( '[ProWorkflow] npm run lint && npm run typecheck && npm test --changed' );
}
if ( count > threshold . second && count % threshold . repeat === 0 ) {
console . error ( `[ProWorkflow] ${ count } edits — quality gates due` );
}
}
Session Tracking
Quality gates integrate with session tracking to improve over time:
{
"session_id" : "unique-session-id" ,
"edit_count" : 15 ,
"corrections_count" : 2 ,
"quality_gate_runs" : 2 ,
"quality_gate_failures" : 0 ,
"timestamp" : "2026-03-08T10:30:00Z"
}
The system learns from:
Edit patterns : How many edits before issues appear
Correction frequency : How often you need to fix Claude’s code
Quality gate success rate : How often gates pass on first try
Manual Quality Gates
Run quality gates manually at any time:
# Full quality gates
npm run lint && npm run typecheck && npm test -- --related
# Individual checks
npm run lint
npm run typecheck
npm test -- --related
# Review changes
git diff --stat
git status
Disabling Quality Gates
Disable specific gates when not needed:
{
"quality_gates" : {
"run_lint" : true ,
"run_typecheck" : false , // Disable typecheck
"run_tests" : true
}
}
Or disable entirely for prototyping:
{
"quality_gates" : {
"run_lint" : false ,
"run_typecheck" : false ,
"run_tests" : false
}
}
Run Only Changed Tests
{
"quality_gates" : {
"test_command" : "npm test -- --related --changedSince=HEAD"
}
}
Cache-Friendly Commands
{
"quality_gates" : {
"lint_command" : "eslint . --cache" ,
"typecheck_command" : "tsc --incremental"
}
}
Parallel Execution
# Run all gates in parallel (faster, but harder to debug)
npm run lint & npm run typecheck & npm test -- --related
# Or use a parallel task runner
npm install --save-dev concurrently
npx concurrently "npm:lint" "npm:typecheck" "npm:test"
Troubleshooting
Quality gates not triggering
Cause : PostEdit hook not configuredFix : Add to hooks.json:{
"PostEdit" : [{
"command" : "node scripts/quality-gate.js" ,
"background" : true
}]
}
Commands failing with 'command not found'
Cause : npm scripts not defined in package.jsonFix : Add scripts:{
"scripts" : {
"lint" : "eslint ." ,
"typecheck" : "tsc --noEmit" ,
"test" : "jest"
}
}
Cause : Session database not initializedFix : Check database configuration:{
"database" : {
"path" : "~/.pro-workflow/data.db" ,
"auto_init" : true
}
}
Gates running too frequently
Cause : High correction rate from recent sessionsFix : This is intentional - the system detected issues. Improve code quality or manually override thresholds by modifying the script.
Best Practices
Fast Feedback Keep quality gate commands fast (<10s) for quick feedback loops. Use --changed and --related flags.
Fail Early Configure PreCommit hooks to block commits with quality issues. Better to catch errors before they enter git history.
Adapt to Project Customize commands for your tech stack. Not all projects need all three gates.
Monitor Trends Review correction rates periodically. Increasing rates indicate architectural or tooling issues.
Next Steps
Hooks System Learn about the hook events that power quality gates
Model Preferences Configure models for different task types
Wrap-Up Phase Understand end-of-session quality verification