| name | Quality Gates |
| description | Centralized quality gate execution for backend, frontend, and fullstack projects. Use when running format, lint, typecheck, or tests. Auto-detects stack and runs appropriate commands. Does NOT commit - calling command uses git-workflow skill. |
Quality Gates Skill
Centralized quality validation for tempo-demo workflows.
Purpose
Provide consistent quality gate execution:
- Auto-detect stack (backend/frontend/fullstack)
- Run appropriate commands per stack
- Return status for calling command to handle
- Does NOT commit (calling command uses git-workflow skill)
Core Responsibility
This skill is the single source of truth for quality gate execution. Commands should use this skill's functions rather than calling quality commands directly. This guarantees:
- ✅ Consistent execution across all workflows
- ✅ Proper stack detection and command routing
- ✅ Standardized return formats
- ✅ Separation of concerns (gates vs commits)
Functions
1. detect_stack()
Purpose: Determine if backend, frontend, or fullstack based on context
Usage:
Use quality-gates skill to detect stack
Implementation:
# Priority 1: Check .env PROJECT_STACK variable
if [ -f .env ]; then
source .env 2>/dev/null
if [ -n "$PROJECT_STACK" ]; then
echo "$PROJECT_STACK"
return
fi
fi
# Priority 2: Detect from current directory
CURRENT_DIR=$(pwd)
if [[ "$CURRENT_DIR" == *"/application/backend"* ]]; then
echo "backend"
return
elif [[ "$CURRENT_DIR" == *"/application/frontend"* ]]; then
echo "frontend"
return
fi
# Priority 3: Check for both backend and frontend existence
BACKEND_EXISTS=false
FRONTEND_EXISTS=false
if [ -f "application/backend/pyproject.toml" ]; then
BACKEND_EXISTS=true
fi
if [ -f "application/frontend/package.json" ]; then
FRONTEND_EXISTS=true
fi
if [ "$BACKEND_EXISTS" = true ] && [ "$FRONTEND_EXISTS" = true ]; then
echo "fullstack"
elif [ "$BACKEND_EXISTS" = true ]; then
echo "backend"
elif [ "$FRONTEND_EXISTS" = true ]; then
echo "frontend"
else
echo "unknown"
fi
Returns:
backend- Backend-only workfrontend- Frontend-only workfullstack- Both stacks presentunknown- Cannot determine
2. run_format()
Purpose: Auto-format code, return whether changes were made
Usage:
Use quality-gates skill to run format
Implementation:
# Detect stack first
STACK=$(detect_stack)
case "$STACK" in
backend)
cd application/backend || exit 1
# Capture files before formatting
BEFORE=$(git diff --name-only | sort)
# Run format
uv run ruff format .
# Check if changes were made
AFTER=$(git diff --name-only | sort)
if [ "$BEFORE" != "$AFTER" ] || [ -n "$(git diff)" ]; then
echo "CHANGES_MADE"
return 0
else
echo "NO_CHANGES"
return 0
fi
;;
frontend)
cd application/frontend || exit 1
# Capture files before formatting
BEFORE=$(git diff --name-only | sort)
# Run format
npm run format
# Check if changes were made
AFTER=$(git diff --name-only | sort)
if [ "$BEFORE" != "$AFTER" ] || [ -n "$(git diff)" ]; then
echo "CHANGES_MADE"
return 0
else
echo "NO_CHANGES"
return 0
fi
;;
fullstack)
# Run both, aggregate results
BACKEND_RESULT="NO_CHANGES"
FRONTEND_RESULT="NO_CHANGES"
# Backend
if [ -f "application/backend/pyproject.toml" ]; then
cd application/backend || exit 1
BEFORE=$(git diff --name-only | sort)
uv run ruff format .
AFTER=$(git diff --name-only | sort)
if [ "$BEFORE" != "$AFTER" ] || [ -n "$(git diff)" ]; then
BACKEND_RESULT="CHANGES_MADE"
fi
cd ../..
fi
# Frontend
if [ -f "application/frontend/package.json" ]; then
cd application/frontend || exit 1
BEFORE=$(git diff --name-only | sort)
npm run format
AFTER=$(git diff --name-only | sort)
if [ "$BEFORE" != "$AFTER" ] || [ -n "$(git diff)" ]; then
FRONTEND_RESULT="CHANGES_MADE"
fi
cd ../..
fi
# Determine overall result
if [ "$BACKEND_RESULT" = "CHANGES_MADE" ] || [ "$FRONTEND_RESULT" = "CHANGES_MADE" ]; then
echo "CHANGES_MADE"
else
echo "NO_CHANGES"
fi
return 0
;;
*)
echo "ERROR: Unknown stack"
return 1
;;
esac
Returns:
CHANGES_MADE- Files were modified by formattingNO_CHANGES- No formatting changes neededERROR: {message}- Execution failed
Calling Command Responsibility:
If CHANGES_MADE, use git-workflow skill to commit:
Use git-workflow skill to commit changes:
- Type: style
- Scope: (empty)
- Message: auto-format code
- Issue: {ISSUE_ID}
3. run_lint()
Purpose: Lint code with auto-fix where possible
Usage:
Use quality-gates skill to run lint
Implementation:
# Detect stack first
STACK=$(detect_stack)
case "$STACK" in
backend)
cd application/backend || exit 1
# Capture files before linting
BEFORE=$(git diff --name-only | sort)
# Run lint with auto-fix
if uv run ruff check --fix .; then
# Check if changes were made
AFTER=$(git diff --name-only | sort)
if [ "$BEFORE" != "$AFTER" ] || [ -n "$(git diff)" ]; then
echo "CHANGES_MADE"
return 0
else
echo "PASSED"
return 0
fi
else
# Lint failed - capture errors
echo "FAILED"
return 1
fi
;;
frontend)
cd application/frontend || exit 1
# Capture files before linting
BEFORE=$(git diff --name-only | sort)
# Run lint
if npm run lint; then
# Check if changes were made
AFTER=$(git diff --name-only | sort)
if [ "$BEFORE" != "$AFTER" ] || [ -n "$(git diff)" ]; then
echo "CHANGES_MADE"
return 0
else
echo "PASSED"
return 0
fi
else
echo "FAILED"
return 1
fi
;;
fullstack)
# Run both, aggregate results
BACKEND_RESULT="PASSED"
FRONTEND_RESULT="PASSED"
OVERALL_EXIT=0
# Backend
if [ -f "application/backend/pyproject.toml" ]; then
cd application/backend || exit 1
BEFORE=$(git diff --name-only | sort)
if uv run ruff check --fix .; then
AFTER=$(git diff --name-only | sort)
if [ "$BEFORE" != "$AFTER" ] || [ -n "$(git diff)" ]; then
BACKEND_RESULT="CHANGES_MADE"
fi
else
BACKEND_RESULT="FAILED"
OVERALL_EXIT=1
fi
cd ../..
fi
# Frontend
if [ -f "application/frontend/package.json" ]; then
cd application/frontend || exit 1
BEFORE=$(git diff --name-only | sort)
if npm run lint; then
AFTER=$(git diff --name-only | sort)
if [ "$BEFORE" != "$AFTER" ] || [ -n "$(git diff)" ]; then
FRONTEND_RESULT="CHANGES_MADE"
fi
else
FRONTEND_RESULT="FAILED"
OVERALL_EXIT=1
fi
cd ../..
fi
# Determine overall result
if [ "$OVERALL_EXIT" -ne 0 ]; then
echo "FAILED"
return 1
elif [ "$BACKEND_RESULT" = "CHANGES_MADE" ] || [ "$FRONTEND_RESULT" = "CHANGES_MADE" ]; then
echo "CHANGES_MADE"
return 0
else
echo "PASSED"
return 0
fi
;;
*)
echo "ERROR: Unknown stack"
return 1
;;
esac
Returns:
CHANGES_MADE- Auto-fixes were appliedPASSED- Lint passed with no changesFAILED- Lint errors that cannot be auto-fixedERROR: {message}- Execution failed
Calling Command Responsibility:
If CHANGES_MADE, use git-workflow skill to commit:
Use git-workflow skill to commit changes:
- Type: style
- Scope: (empty)
- Message: auto-fix lint issues
- Issue: {ISSUE_ID}
If FAILED, report errors and potentially fix manually.
4. run_typecheck()
Purpose: Type checking (reports errors, no auto-fix)
Usage:
Use quality-gates skill to run typecheck
Implementation:
# Detect stack first
STACK=$(detect_stack)
case "$STACK" in
backend)
cd application/backend || exit 1
# Run type check
if uv run mypy --strict .; then
echo "PASSED"
return 0
else
echo "FAILED"
return 1
fi
;;
frontend)
cd application/frontend || exit 1
# Run type check
if npm run type-check; then
echo "PASSED"
return 0
else
echo "FAILED"
return 1
fi
;;
fullstack)
# Run both, aggregate results
BACKEND_EXIT=0
FRONTEND_EXIT=0
# Backend
if [ -f "application/backend/pyproject.toml" ]; then
cd application/backend || exit 1
if ! uv run mypy --strict .; then
BACKEND_EXIT=1
fi
cd ../..
fi
# Frontend
if [ -f "application/frontend/package.json" ]; then
cd application/frontend || exit 1
if ! npm run type-check; then
FRONTEND_EXIT=1
fi
cd ../..
fi
# Determine overall result
if [ "$BACKEND_EXIT" -ne 0 ] || [ "$FRONTEND_EXIT" -ne 0 ]; then
echo "FAILED"
return 1
else
echo "PASSED"
return 0
fi
;;
*)
echo "ERROR: Unknown stack"
return 1
;;
esac
Returns:
PASSED- Type check passedFAILED- Type errors found (stderr contains details)ERROR: {message}- Execution failed
Note: Typecheck cannot auto-fix. Calling command should report errors and potentially attempt manual fixes.
5. run_tests()
Purpose: Run test suite
Usage:
Use quality-gates skill to run tests
Implementation:
# Detect stack first
STACK=$(detect_stack)
case "$STACK" in
backend)
cd application/backend || exit 1
# Run tests
if uv run pytest --cov --cov-report=term-missing; then
echo "PASSED"
return 0
else
echo "FAILED"
return 1
fi
;;
frontend)
cd application/frontend || exit 1
# Run tests
if npm test; then
echo "PASSED"
return 0
else
echo "FAILED"
return 1
fi
;;
fullstack)
# Run both, aggregate results
BACKEND_EXIT=0
FRONTEND_EXIT=0
# Backend
if [ -f "application/backend/pyproject.toml" ]; then
cd application/backend || exit 1
if ! uv run pytest --cov --cov-report=term-missing; then
BACKEND_EXIT=1
fi
cd ../..
fi
# Frontend
if [ -f "application/frontend/package.json" ]; then
cd application/frontend || exit 1
if ! npm test; then
FRONTEND_EXIT=1
fi
cd ../..
fi
# Determine overall result
if [ "$BACKEND_EXIT" -ne 0 ] || [ "$FRONTEND_EXIT" -ne 0 ]; then
echo "FAILED"
return 1
else
echo "PASSED"
return 0
fi
;;
*)
echo "ERROR: Unknown stack"
return 1
;;
esac
Returns:
PASSED- All tests passedFAILED- Test failures (stderr contains details)ERROR: {message}- Execution failed
Note: Tests cannot auto-fix. Calling command should report failures.
6. run_all()
Purpose: Run all gates in sequence
Usage:
Use quality-gates skill to run all gates
Implementation:
Run in order:
1. Use quality-gates skill to run format
- If CHANGES_MADE: Calling command should commit via git-workflow
2. Use quality-gates skill to run lint
- If CHANGES_MADE: Calling command should commit via git-workflow
3. Use quality-gates skill to run typecheck
- If FAILED: Report errors
4. Use quality-gates skill to run tests
- If FAILED: Report failures
Return: Overall pass/fail status based on all gates
Returns:
ALL_PASSED- All gates passed (format and lint may have made changes that were committed)SOME_FAILED- One or more gates failedERROR: {message}- Execution failed
Note: This is a meta-function that orchestrates the other functions. The calling command is responsible for:
- Committing format/lint changes via git-workflow skill
- Handling typecheck/test failures
- Potentially re-running after fixes
Usage in Commands
Pattern: /implement
## Quality Gate Execution
1. Use quality-gates skill to run format
- If CHANGES_MADE:
Use git-workflow skill to commit changes:
- Type: style
- Scope: (empty)
- Message: auto-format code
- Issue: {ISSUE_ID}
2. Use quality-gates skill to run lint
- If CHANGES_MADE:
Use git-workflow skill to commit changes:
- Type: style
- Scope: (empty)
- Message: auto-fix lint issues
- Issue: {ISSUE_ID}
- If FAILED: Report errors, potentially fix
3. Use quality-gates skill to run typecheck
- If FAILED: Report errors, potentially fix
4. Use quality-gates skill to run tests
- If FAILED: Report failures
Pattern: /test
## Quality Gate Validation
Use quality-gates skill to run all gates
Handle results:
- Format/Lint CHANGES_MADE: Commit via git-workflow
- Typecheck/Test FAILED: Report and loop until fixed
Stack Detection Logic
Priority 1: .env Variable
Check for PROJECT_STACK variable in .env:
PROJECT_STACK=backend # Forces backend
PROJECT_STACK=frontend # Forces frontend
PROJECT_STACK=fullstack # Forces fullstack
Priority 2: Current Directory
Detect from current working directory:
- In
application/backend/→ backend - In
application/frontend/→ frontend
Priority 3: Project Structure
Check for existence of both stacks:
- Both
application/backend/pyproject.tomlANDapplication/frontend/package.json→ fullstack - Only
application/backend/pyproject.toml→ backend - Only
application/frontend/package.json→ frontend
Gate Commands by Stack
Backend Gates
Working Directory: application/backend/
Format:
uv run ruff format .- Auto-fixes: Yes
- Can commit: Yes
Lint:
uv run ruff check --fix .- Auto-fixes: Partial (safe fixes only)
- Can commit: Yes (if changes made)
Typecheck:
uv run mypy --strict .- Auto-fixes: No
- Can commit: No
Tests:
uv run pytest --cov --cov-report=term-missing- Auto-fixes: No
- Can commit: No
Frontend Gates
Working Directory: application/frontend/
Format:
npm run format- Auto-fixes: Yes
- Can commit: Yes
Lint:
npm run lint- Auto-fixes: Partial
- Can commit: Yes (if changes made)
Typecheck:
npm run type-check- Auto-fixes: No
- Can commit: No
Tests:
npm test- Auto-fixes: No
- Can commit: No
Fullstack Gates
Run both backend and frontend gates sequentially:
- Run backend gate
- Run frontend gate
- Aggregate results
Result Aggregation:
CHANGES_MADEif either stack has changesFAILEDif either stack failsPASSEDonly if both pass with no changes
Error Handling
Gate Execution Failures
If a gate command fails to execute:
- Capture stderr
- Return
ERROR: {message} - Calling command should handle and potentially abort
Stack Detection Failures
If stack cannot be determined:
- Return
ERROR: Unknown stack - Suggest:
- Add
PROJECT_STACK=backend|frontend|fullstackto.env - Or run from correct directory
- Or check project structure
- Add
Missing Dependencies
If required tools are missing:
- Backend:
uvnot installed - Frontend:
npmnot installed - Return
ERROR: Missing dependency: {tool} - Suggest installation instructions
Best Practices
- Always detect stack first - Never assume stack type
- Run gates in order - Format → Lint → Typecheck → Test
- Commit format/lint changes separately - Via git-workflow skill
- Don't commit typecheck/test fixes - Let developer fix properly
- Handle errors gracefully - Return clear status codes
- Aggregate results for fullstack - Report both stacks clearly
- Use absolute paths - When changing directories
- Capture git state - Before and after for change detection
Integration with Other Skills
With git-workflow Skill
Quality-gates skill detects changes, git-workflow skill commits them:
# Quality-gates skill
Use quality-gates skill to run format
# Returns: CHANGES_MADE
# Git-workflow skill
Use git-workflow skill to commit changes:
- Type: style
- Scope: (empty)
- Message: auto-format code
- Issue: TEMPO-123
Why Separate?
- Quality-gates focuses on execution and detection
- Git-workflow focuses on commit formatting and conventions
- Single responsibility principle
- Commands can choose when/how to commit
With task-patterns Skill
Quality-gates can be used before/after Linear operations:
# Before implementation
Use task-patterns skill to fetch issue TEMPO-123
Use quality-gates skill to run all gates # Ensure clean starting state
# After implementation
Use quality-gates skill to run all gates
Use task-patterns skill to comment on TEMPO-123 with gate results
Troubleshooting
Skill not detecting correct stack
Solution:
# Add to .env
PROJECT_STACK=backend # or frontend or fullstack
Format/lint not finding files
Solution:
- Ensure you're in project root
- Check that
application/backend/orapplication/frontend/exist - Verify
pyproject.tomlorpackage.jsonexist
Commands return "ERROR: Unknown stack"
Solution:
- Check directory structure
- Add
PROJECT_STACKto.env - Ensure at least one stack exists
Typecheck passes in skill but fails manually
Solution:
- Check that same command is being run
- Verify working directory
- Check for environment differences
Examples
Example 1: Backend Format with Commit
## Command: /implement TEMPO-123
1. Use quality-gates skill to detect stack
# Returns: backend
2. Use quality-gates skill to run format
# Returns: CHANGES_MADE
3. Use git-workflow skill to commit changes:
- Type: style
- Scope: (empty)
- Message: auto-format code
- Issue: TEMPO-123
# Commits format changes
Example 2: Fullstack All Gates
## Command: /test
1. Use quality-gates skill to run all gates
# Runs format, lint, typecheck, test for both backend and frontend
# Returns: SOME_FAILED (backend typecheck failed)
2. Report: Backend typecheck failed with 3 errors
- Fix type errors manually
- Re-run: Use quality-gates skill to run typecheck
# Returns: PASSED
3. Use quality-gates skill to run all gates
# Returns: ALL_PASSED
Example 3: Frontend Lint with Auto-Fix
## Command: /implement TEMPO-456
1. Use quality-gates skill to detect stack
# Returns: frontend
2. Use quality-gates skill to run lint
# Returns: CHANGES_MADE (auto-fixed unused imports)
3. Use git-workflow skill to commit changes:
- Type: style
- Scope: (empty)
- Message: auto-fix lint issues
- Issue: TEMPO-456
Testing the Skill
Manual Testing
# Test stack detection
STACK=$(detect_stack)
echo "Detected stack: $STACK"
# Test format (no commit)
RESULT=$(run_format)
echo "Format result: $RESULT"
# Test lint
RESULT=$(run_lint)
echo "Lint result: $RESULT"
# Test typecheck
RESULT=$(run_typecheck)
echo "Typecheck result: $RESULT"
# Test tests
RESULT=$(run_tests)
echo "Tests result: $RESULT"
Integration Testing
From a command:
Use quality-gates skill to run all gates
# Verify all gates execute correctly
# Verify correct stack is detected
# Verify results are properly returned
Future Enhancements
Potential additions (not required now):
- Custom Coverage Thresholds: Pass coverage minimum to run_tests()
- Parallel Execution: Run backend and frontend gates in parallel for fullstack
- Detailed Error Parsing: Return structured error objects
- Gate Timing: Report execution time per gate
- Selective Gate Execution: Run only specific gates
- Watch Mode: Continuous gate execution on file changes
Ready to use! This skill provides consistent quality validation across all tempo-demo workflows.