Skip to main content

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:
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"
  }
}
quality_gates.run_lint
boolean
default:"true"
Enable automatic linting at quality gate checkpoints
quality_gates.run_typecheck
boolean
default:"true"
Enable automatic type checking at quality gate checkpoints
quality_gates.run_tests
boolean
default:"true"
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:
CheckpointDefault ThresholdAction
First5 editsReview checkpoint - suggest git diff --stat
Second10 editsRun full quality gates
RepeatEvery 10 editsRun 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": [{
    "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:
config.json
{
  "wrap_up": {
    "check_uncommitted": true,
    "verify_tests": true,
    "update_claude_md": true,
    "create_summary": true
  }
}
wrap_up.check_uncommitted
boolean
default:"true"
Check for uncommitted changes and prompt for action
wrap_up.verify_tests
boolean
default:"true"
Run tests one final time before session ends
wrap_up.update_claude_md
boolean
default:"true"
Update CLAUDE.md with learned patterns
wrap_up.create_summary
boolean
default:"true"
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"
  }
}
{
  "quality_gates": {
    "typecheck_command": "tsc --noEmit --strict"
  }
}
{
  "quality_gates": {
    "test_command": "jest --coverage --coverageThreshold=80 --onlyChanged"
  }
}
{
  "quality_gates": {
    "test_command": "vitest run --changed --testNamePattern='unit'"
  }
}
{
  "quality_gates": {
    "lint_command": "prettier --check . && eslint ."
  }
}
{
  "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:
Database schema
{
  "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:
config.json
{
  "quality_gates": {
    "run_lint": true,
    "run_typecheck": false,    // Disable typecheck
    "run_tests": true
  }
}
Or disable entirely for prototyping:
config.json
{
  "quality_gates": {
    "run_lint": false,
    "run_typecheck": false,
    "run_tests": false
  }
}

Performance Optimization

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

Cause: PostEdit hook not configuredFix: Add to hooks.json:
{
  "PostEdit": [{
    "command": "node scripts/quality-gate.js",
    "background": true
  }]
}
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
  }
}
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

Build docs developers (and LLMs) love