Files
gh-andre-mygentic-andre-eng…/agents/quality-checker.md
2025-11-29 17:54:49 +08:00

13 KiB

name, description, model, color
name description model color
quality-checker Comprehensive quality audit with automated linting, type checking, formatting, tests, and builds. Auto-configures missing tools. Maximum 6 minutes. sonnet blue

Quality Checker - Comprehensive Automated Quality Enforcement

Role

Enforce code quality standards automatically. Detect language, auto-configure missing tools, run all checks. Maximum 6 minutes.

Input

Issue number from manifest

Workflow

STEP 1: Load Context and Error Handler

ISSUE_NUM=$1
MANIFEST=".agent-state/issue-${ISSUE_NUM}-implementation.yaml"
AGENT_NAME="quality-checker"

# Get git root and load error handler
GIT_ROOT=$(git rev-parse --show-toplevel)
if [ -f "$GIT_ROOT/.claude/scripts/error-handler.sh" ]; then
  source "$GIT_ROOT/.claude/scripts/error-handler.sh"
else
  echo "⚠️ Error handler not found, proceeding without retry logic"
fi

# Initialize results
PYTHON_DETECTED=false
JAVASCRIPT_DETECTED=false

STEP 2: Detect Language and Auto-Configure Tools

echo "Detecting project language and configuring tools..."

# Detect Python
if ls *.py 2>/dev/null || [ -d "src" ] && ls src/**/*.py 2>/dev/null; then
  PYTHON_DETECTED=true
  echo "✓ Python code detected"

  # Auto-configure flake8 if not configured
  if [ ! -f ".flake8" ] && [ ! -f "setup.cfg" ] && ! grep -q "\[flake8\]" pyproject.toml 2>/dev/null; then
    echo "Creating .flake8 configuration..."
    cat > .flake8 << 'EOF'
[flake8]
max-line-length = 100
extend-ignore = E203, W503
exclude = .git,__pycache__,venv,.venv,build,dist
EOF
    git add .flake8
  fi

  # Auto-configure mypy if not configured
  if [ ! -f "mypy.ini" ] && ! grep -q "\[tool.mypy\]" pyproject.toml 2>/dev/null; then
    echo "Creating mypy.ini configuration..."
    cat > mypy.ini << 'EOF'
[mypy]
python_version = 3.11
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = False
ignore_missing_imports = True
EOF
    git add mypy.ini
  fi

  # Auto-configure black if not configured
  if ! grep -q "\[tool.black\]" pyproject.toml 2>/dev/null; then
    echo "Adding black configuration to pyproject.toml..."
    if [ ! -f "pyproject.toml" ]; then
      cat > pyproject.toml << 'EOF'
[tool.black]
line-length = 100
target-version = ['py311']
EOF
    else
      # Append if pyproject.toml exists
      if ! grep -q "\[tool.black\]" pyproject.toml; then
        echo "" >> pyproject.toml
        echo "[tool.black]" >> pyproject.toml
        echo "line-length = 100" >> pyproject.toml
        echo "target-version = ['py311']" >> pyproject.toml
      fi
    fi
    git add pyproject.toml
  fi

  # Auto-configure isort if not configured
  if ! grep -q "\[tool.isort\]" pyproject.toml 2>/dev/null && [ ! -f ".isort.cfg" ]; then
    echo "Adding isort configuration to pyproject.toml..."
    if ! grep -q "\[tool.isort\]" pyproject.toml 2>/dev/null; then
      echo "" >> pyproject.toml
      echo "[tool.isort]" >> pyproject.toml
      echo "profile = \"black\"" >> pyproject.toml
      echo "line_length = 100" >> pyproject.toml
    fi
    git add pyproject.toml
  fi
fi

# Detect JavaScript/TypeScript
if [ -f "package.json" ]; then
  JAVASCRIPT_DETECTED=true
  echo "✓ JavaScript/TypeScript code detected"

  # Auto-configure ESLint if not configured
  if [ ! -f ".eslintrc.json" ] && [ ! -f ".eslintrc.js" ] && [ ! -f "eslint.config.js" ]; then
    echo "Creating .eslintrc.json configuration..."
    cat > .eslintrc.json << 'EOF'
{
  "extends": ["next/core-web-vitals"],
  "rules": {
    "no-unused-vars": "error",
    "no-console": "warn",
    "@typescript-eslint/no-explicit-any": "warn"
  }
}
EOF
    git add .eslintrc.json
  fi

  # Auto-configure Prettier if not configured
  if [ ! -f ".prettierrc" ] && [ ! -f ".prettierrc.json" ]; then
    echo "Creating .prettierrc configuration..."
    cat > .prettierrc << 'EOF'
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2
}
EOF
    git add .prettierrc
  fi

  # Ensure ESLint and Prettier are installed
  if ! npm list eslint &>/dev/null; then
    echo "Installing ESLint..."
    npm install --save-dev eslint eslint-config-next @typescript-eslint/eslint-plugin @typescript-eslint/parser
  fi

  if ! npm list prettier &>/dev/null; then
    echo "Installing Prettier..."
    npm install --save-dev prettier
  fi
fi

STEP 3: Python Quality Checks (if Python detected)

if [ "$PYTHON_DETECTED" = true ]; then
  echo "=== Python Quality Checks ==="

  # Flake8 - PEP 8 style guide enforcement
  echo "Running Flake8..."
  FLAKE8_RESULT="PASS"
  FLAKE8_OUTPUT=""
  python -m flake8 . --count --statistics 2>&1 | tee flake8-output.txt || true
  if [ ${PIPESTATUS[0]} -ne 0 ]; then
    FLAKE8_RESULT="FAIL"
    FLAKE8_OUTPUT=$(cat flake8-output.txt)
  fi

  # mypy - Static type checking
  echo "Running mypy..."
  MYPY_RESULT="PASS"
  MYPY_OUTPUT=""
  python -m mypy . --no-error-summary 2>&1 | tee mypy-output.txt || true
  if [ ${PIPESTATUS[0]} -ne 0 ]; then
    MYPY_RESULT="FAIL"
    MYPY_OUTPUT=$(cat mypy-output.txt)
  fi

  # black - Code formatting check
  echo "Running black --check..."
  BLACK_RESULT="PASS"
  BLACK_OUTPUT=""
  python -m black --check . 2>&1 | tee black-output.txt || true
  if [ ${PIPESTATUS[0]} -ne 0 ]; then
    BLACK_RESULT="FAIL"
    BLACK_OUTPUT=$(cat black-output.txt)
  fi

  # isort - Import order check
  echo "Running isort --check..."
  ISORT_RESULT="PASS"
  ISORT_OUTPUT=""
  python -m isort --check-only . 2>&1 | tee isort-output.txt || true
  if [ ${PIPESTATUS[0]} -ne 0 ]; then
    ISORT_RESULT="FAIL"
    ISORT_OUTPUT=$(cat isort-output.txt)
  fi

  # pylint - Additional linting
  echo "Running pylint..."
  PYLINT_RESULT="PASS"
  PYLINT_OUTPUT=""
  python -m pylint **/*.py --exit-zero 2>&1 | tee pylint-output.txt
  PYLINT_SCORE=$(grep "Your code has been rated at" pylint-output.txt | awk '{print $7}' | cut -d'/' -f1)
  if (( $(echo "$PYLINT_SCORE < 7.0" | bc -l) )); then
    PYLINT_RESULT="WARN"
    PYLINT_OUTPUT=$(cat pylint-output.txt | tail -20)
  fi

  # pytest - Run tests
  echo "Running pytest..."
  PYTEST_RESULT="PASS"
  PYTEST_OUTPUT=""
  if [ -f "pytest.ini" ] || [ -d "tests" ]; then
    retry_command "timeout 90 python -m pytest -v 2>&1 | tee pytest-output.txt" "Python tests"
    if [ $? -ne 0 ]; then
      PYTEST_RESULT="FAIL"
      PYTEST_OUTPUT="$LAST_ERROR_MSG"
    fi
  fi

  # Python syntax check
  echo "Checking Python syntax..."
  PYTHON_SYNTAX_RESULT="PASS"
  find . -name "*.py" -not -path "./venv/*" -not -path "./.venv/*" | while read pyfile; do
    python -m py_compile "$pyfile" 2>&1
    if [ $? -ne 0 ]; then
      PYTHON_SYNTAX_RESULT="FAIL"
    fi
  done

  # Coverage (non-blocking)
  COVERAGE="N/A"
  if [ -f "pytest.ini" ] || [ -d "tests" ]; then
    COVERAGE=$(python -m pytest --cov 2>&1 | grep "TOTAL" | awk '{print $NF}')
  fi
fi

STEP 4: JavaScript/TypeScript Quality Checks (if JS detected)

if [ "$JAVASCRIPT_DETECTED" = true ]; then
  echo "=== JavaScript/TypeScript Quality Checks ==="

  # ESLint - Linting
  echo "Running ESLint..."
  ESLINT_RESULT="PASS"
  ESLINT_OUTPUT=""
  npx eslint . --ext .js,.jsx,.ts,.tsx 2>&1 | tee eslint-output.txt || true
  if [ ${PIPESTATUS[0]} -ne 0 ]; then
    ESLINT_RESULT="FAIL"
    ESLINT_OUTPUT=$(cat eslint-output.txt)
  fi

  # Prettier - Formatting check
  echo "Running Prettier --check..."
  PRETTIER_RESULT="PASS"
  PRETTIER_OUTPUT=""
  npx prettier --check . 2>&1 | tee prettier-output.txt || true
  if [ ${PIPESTATUS[0]} -ne 0 ]; then
    PRETTIER_RESULT="FAIL"
    PRETTIER_OUTPUT=$(cat prettier-output.txt)
  fi

  # TypeScript - Type checking
  echo "Running TypeScript compiler..."
  TSC_RESULT="PASS"
  TSC_OUTPUT=""
  if [ -f "tsconfig.json" ]; then
    npx tsc --noEmit 2>&1 | tee tsc-output.txt || true
    if [ ${PIPESTATUS[0]} -ne 0 ]; then
      TSC_RESULT="FAIL"
      TSC_OUTPUT=$(cat tsc-output.txt)
    fi
  fi

  # npm test - Run tests
  echo "Running npm test..."
  NPM_TEST_RESULT="PASS"
  NPM_TEST_OUTPUT=""
  retry_command "timeout 90 npm test 2>&1 | tee npm-test-output.txt" "JavaScript tests"
  if [ $? -ne 0 ]; then
    NPM_TEST_RESULT="FAIL"
    NPM_TEST_OUTPUT="$LAST_ERROR_MSG"
  fi

  # npm run build - Build check
  echo "Running npm run build..."
  BUILD_RESULT="PASS"
  BUILD_OUTPUT=""
  if grep -q '"build"' package.json; then
    timeout 120 npm run build 2>&1 | tee build-output.txt || true
    if [ ${PIPESTATUS[0]} -ne 0 ]; then
      BUILD_RESULT="FAIL"
      BUILD_OUTPUT=$(cat build-output.txt)
    fi
  fi
fi

STEP 5: Determine Blocking Issues

# Blocking criteria (critical errors only):
# 1. Tests fail (pytest/npm test)
# 2. Build fails (npm run build)
# 3. Syntax errors (Python syntax/TypeScript compiler)

BLOCKING_COUNT=0

# Python blocking issues
if [ "$PYTHON_DETECTED" = true ]; then
  [ "$PYTEST_RESULT" = "FAIL" ] && BLOCKING_COUNT=$((BLOCKING_COUNT + 1))
  [ "$PYTHON_SYNTAX_RESULT" = "FAIL" ] && BLOCKING_COUNT=$((BLOCKING_COUNT + 1))
fi

# JavaScript blocking issues
if [ "$JAVASCRIPT_DETECTED" = true ]; then
  [ "$NPM_TEST_RESULT" = "FAIL" ] && BLOCKING_COUNT=$((BLOCKING_COUNT + 1))
  [ "$BUILD_RESULT" = "FAIL" ] && BLOCKING_COUNT=$((BLOCKING_COUNT + 1))
  [ "$TSC_RESULT" = "FAIL" ] && BLOCKING_COUNT=$((BLOCKING_COUNT + 1))
fi

# Determine overall status
if [ $BLOCKING_COUNT -eq 0 ]; then
  OVERALL_STATUS="PASS"
else
  OVERALL_STATUS="FAIL"
fi

STEP 6: Generate Comprehensive Quality Report

mkdir -p .agent-state/review-results

cat > .agent-state/review-results/quality-check.yaml << EOF
agent: quality-checker
status: ${OVERALL_STATUS}
timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ")

blocking_issues:
$(if [ "$PYTHON_DETECTED" = true ]; then
  [ "$PYTEST_RESULT" = "FAIL" ] && echo "  - type: python_test_failures"
  [ "$PYTHON_SYNTAX_RESULT" = "FAIL" ] && echo "  - type: python_syntax_errors"
fi)
$(if [ "$JAVASCRIPT_DETECTED" = true ]; then
  [ "$NPM_TEST_RESULT" = "FAIL" ] && echo "  - type: javascript_test_failures"
  [ "$BUILD_RESULT" = "FAIL" ] && echo "  - type: build_failure"
  [ "$TSC_RESULT" = "FAIL" ] && echo "  - type: typescript_errors"
fi)

python_checks:
$(if [ "$PYTHON_DETECTED" = true ]; then
cat << PYTHON_EOF
  detected: true
  flake8:
    status: ${FLAKE8_RESULT}
    blocking: false
    output: |
$(echo "$FLAKE8_OUTPUT" | head -15 | sed 's/^/      /')
  mypy:
    status: ${MYPY_RESULT}
    blocking: false
    output: |
$(echo "$MYPY_OUTPUT" | head -15 | sed 's/^/      /')
  black:
    status: ${BLACK_RESULT}
    blocking: false
    output: |
$(echo "$BLACK_OUTPUT" | head -10 | sed 's/^/      /')
  isort:
    status: ${ISORT_RESULT}
    blocking: false
    output: |
$(echo "$ISORT_OUTPUT" | head -10 | sed 's/^/      /')
  pylint:
    status: ${PYLINT_RESULT}
    score: ${PYLINT_SCORE:-N/A}
    blocking: false
    output: |
$(echo "$PYLINT_OUTPUT" | head -10 | sed 's/^/      /')
  pytest:
    status: ${PYTEST_RESULT}
    blocking: true
    output: |
$(echo "$PYTEST_OUTPUT" | head -20 | sed 's/^/      /')
  syntax:
    status: ${PYTHON_SYNTAX_RESULT}
    blocking: true
  coverage: ${COVERAGE}
PYTHON_EOF
else
  echo "  detected: false"
fi)

javascript_checks:
$(if [ "$JAVASCRIPT_DETECTED" = true ]; then
cat << JS_EOF
  detected: true
  eslint:
    status: ${ESLINT_RESULT}
    blocking: false
    output: |
$(echo "$ESLINT_OUTPUT" | head -15 | sed 's/^/      /')
  prettier:
    status: ${PRETTIER_RESULT}
    blocking: false
    output: |
$(echo "$PRETTIER_OUTPUT" | head -10 | sed 's/^/      /')
  typescript:
    status: ${TSC_RESULT}
    blocking: true
    output: |
$(echo "$TSC_OUTPUT" | head -20 | sed 's/^/      /')
  npm_test:
    status: ${NPM_TEST_RESULT}
    blocking: true
    output: |
$(echo "$NPM_TEST_OUTPUT" | head -20 | sed 's/^/      /')
  build:
    status: ${BUILD_RESULT}
    blocking: true
    output: |
$(echo "$BUILD_OUTPUT" | head -20 | sed 's/^/      /')
JS_EOF
else
  echo "  detected: false"
fi)

summary:
  total_checks_run: $((PYTHON_DETECTED == true ? 8 : 0))$((JAVASCRIPT_DETECTED == true ? 5 : 0))
  blocking_failures: ${BLOCKING_COUNT}
  note: "Only tests, builds, and syntax/type errors block merge. Linting and formatting issues are reported but non-blocking."

auto_fix_suggestions:
$(if [ "$PYTHON_DETECTED" = true ]; then
  [ "$BLACK_RESULT" = "FAIL" ] && echo "  - Run: python -m black ."
  [ "$ISORT_RESULT" = "FAIL" ] && echo "  - Run: python -m isort ."
  [ "$FLAKE8_RESULT" = "FAIL" ] && echo "  - Fix Flake8 issues or update .flake8 config"
  [ "$MYPY_RESULT" = "FAIL" ] && echo "  - Add type hints or update mypy.ini config"
fi)
$(if [ "$JAVASCRIPT_DETECTED" = true ]; then
  [ "$PRETTIER_RESULT" = "FAIL" ] && echo "  - Run: npx prettier --write ."
  [ "$ESLINT_RESULT" = "FAIL" ] && echo "  - Run: npx eslint --fix . --ext .js,.jsx,.ts,.tsx"
fi)
EOF

echo "✓ Quality report generated at .agent-state/review-results/quality-check.yaml"
echo "Overall status: ${OVERALL_STATUS}"
echo "Blocking issues: ${BLOCKING_COUNT}"

Output

Comprehensive quality report at .agent-state/review-results/quality-check.yaml

Blocking Criteria (ONLY)

  • Python tests fail (pytest)
  • JavaScript tests fail (npm test)
  • Build fails (npm run build)
  • Syntax errors (Python syntax check)
  • Type errors (TypeScript compiler)

Non-Blocking (Reported Only)

  • Flake8 violations
  • mypy type hints
  • black formatting
  • isort import order
  • pylint score
  • ESLint warnings
  • Prettier formatting
  • Code coverage

Success Criteria

  • Completes in under 6 minutes
  • Auto-configures missing tools
  • Only blocks on critical errors (tests, builds, syntax)
  • Reports all findings for visibility