Skip to content

Conversation

@cabana8471-arch
Copy link
Contributor

@cabana8471-arch cabana8471-arch commented Jan 26, 2026

Summary

Implements the Quality Gates proposal from issue #96. This system enforces code quality checks before features can be marked as passing.

  • Auto-detect linters: ESLint, Biome (JS/TS), ruff, flake8 (Python)
  • Auto-detect type checkers: TypeScript (tsc), Python (mypy)
  • Custom scripts: Support for .autocoder/quality-checks.sh
  • Strict mode: Block feature_mark_passing if quality checks fail (default: enabled)

New MCP Tools

  • feature_verify_quality - Run quality checks on demand and see results

Modified Behavior

  • feature_mark_passing now runs quality checks before marking
  • In strict mode, returns error if lint/type-check fails
  • Quality results are returned with the response

Configuration

Create .autocoder/config.json in the project directory:

{
  "quality_gates": {
    "enabled": true,
    "strict_mode": true,
    "checks": {
      "lint": true,
      "type_check": true,
      "custom_script": null
    }
  }
}

To disable (not recommended):

{"quality_gates": {"enabled": false}}

Files Changed

File Changes
quality_gates.py New module with quality checking logic
mcp_server/feature_mcp.py Added feature_verify_quality, modified feature_mark_passing
progress.py Added clear_stuck_features() for auto-recovery

Test plan

  • Ruff lint passes
  • Test with TypeScript project (tsc detection)
  • Test with Python project (ruff/mypy detection)
  • Test strict mode blocking

Addresses #96

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a quality verification tool to run linting, type checks, and optional custom checks; returns aggregated quality results and can be invoked independently.
    • Quality checks can be applied during feature operations and optionally included in responses; strict-mode can block operations when checks fail.
  • Improvements

    • Converted many operations to atomic, cross-process-safe updates to reduce race conditions.
    • Automatic recovery of stuck in-progress features on startup and stronger existence/dependency validations.

✏️ Tip: You can customize this high-level summary in your review settings.

…tures

Implements proposal from issue leonvanzyl#96 - Quality Gates system that:

- Auto-detects linters: ESLint, Biome (JS/TS), ruff, flake8 (Python)
- Auto-detects type checkers: TypeScript (tsc), Python (mypy)
- Supports custom quality scripts via .autocoder/quality-checks.sh
- Runs quality checks before allowing feature_mark_passing
- In strict mode (default), blocks marking if checks fail
- Stores quality results for evidence

New files:
- quality_gates.py: Core quality checking module

Modified files:
- mcp_server/feature_mcp.py: Added feature_verify_quality tool,
  modified feature_mark_passing to enforce quality gates
- progress.py: Added clear_stuck_features() for auto-recovery

Configuration (.autocoder/config.json):
```json
{
  "quality_gates": {
    "enabled": true,
    "strict_mode": true,
    "checks": {
      "lint": true,
      "type_check": true,
      "custom_script": null
    }
  }
}
```

Addresses leonvanzyl#96

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 26, 2026

📝 Walkthrough

Walkthrough

Adds a quality-gates subsystem and integrates it into the MCP server: new quality_gates module and feature_verify_quality tool, strict-mode checks in feature_mark_passing, atomic SQLite update/transaction patterns for cross-process safety across many feature operations, and startup logic to clear stuck in-progress features.

Changes

Cohort / File(s) Summary
Quality Gates Module
quality_gates.py
New module implementing detection and execution of lint/type-check/custom checks, typed result shapes (QualityCheckResult, QualityGateResult), command runner (_run_command), detectors, per-check runners (run_lint_check, run_type_check, run_custom_script), verify_quality orchestrator, and load_quality_config.
MCP Server — Feature Tools & DB Atomicity
mcp_server/feature_mcp.py
Adds public feature_verify_quality(); integrates verify_quality into feature_mark_passing with optional strict-mode blocking; replaces many in-process locks with atomic SQL updates and explicit transactions (BEGIN IMMEDIATE/EXCLUSIVE) across feature operations (mark passing/failing/skip/in-progress, claim/clear, create/create_bulk, dependency changes, priority updates); adds existence/self/circular/forward-reference checks and optional quality_result in responses.
Progress / DB Helpers
progress.py
Adds _get_connection(db_file: Path) helper (timeout/PRAGMA busy_timeout), replaces direct sqlite connects in several helpers, and introduces clear_stuck_features(project_dir: Path) -> int to reset stuck in-progress features at startup (duplicate definition appears in diff).
Integrations & Responses
...
Multiple MCP tool responses updated to optionally include quality_result; quality gate checks invoked at additional update paths and responses may surface aggregated results.

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant MCP as MCP Server\n(mcp_server/feature_mcp.py)
    participant QG as Quality Gates\n(quality_gates.py)
    participant DB as SQLite DB

    Client->>MCP: feature_verify_quality() or feature_mark_passing()
    MCP->>QG: load_quality_config(project_dir)
    MCP->>QG: verify_quality(do_lint?, do_type?, do_custom?)
    QG->>QG: detect tools & run checks (lint, type, custom)
    QG-->>MCP: QualityGateResult
    alt strict mode && failed checks
        MCP-->>Client: error (blocking)
    else checks passed or non-blocking
        MCP->>DB: BEGIN IMMEDIATE/EXCLUSIVE
        MCP->>DB: atomic UPDATE/INSERT (mark passing/flags/deps/etc.)
        DB-->>MCP: commit
        MCP-->>Client: success (optional quality_result)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Poem

🐰 I hop through diffs with careful eyes,

Linters sing and type checks rise.
I nudge the stuck, I guard the gate,
Mark passing neat, and block when fate —
A tiny rabbit, keeping code concise.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly and clearly describes the main feature being added: Quality Gates to enforce lint/type-check before marking features as passing.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cabana8471-arch
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 27, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@mcp_server/feature_mcp.py`:
- Around line 293-323: The code runs load_quality_config and verify_quality
while a DB session/transaction is open, which can hold locks; move the quality
checks (load_quality_config and verify_quality) to execute before opening or
while the session is closed (or explicitly close the current session before
calling verify_quality and reopen afterwards). Specifically, call
load_quality_config(PROJECT_DIR) and run verify_quality(...) before you
fetch/modify the Feature object and before using session, or if a session must
exist, session.close() before verify_quality and then create a new session to
reload the Feature, update feature.passes/feature.in_progress and call
session.commit(); ensure you preserve and propagate quality_result into the
final result.

In `@progress.py`:
- Around line 235-256: The try/except block that opens the SQLite connection
(conn = sqlite3.connect(db_file)) can leak the DB handle on errors; update the
logic to ensure conn is always closed and transactions rolled back by using a
context manager (with sqlite3.connect(db_file) as conn:) or adding a finally
that calls conn.rollback() if needed and conn.close() if conn is defined, and
move cursor and commit/close logic inside that guarded scope; reference the
variables conn, cursor and the existing exception handlers to locate and replace
the current try/except so all error paths close the connection.

In `@quality_gates.py`:
- Around line 233-273: If a user explicitly configured a custom script
(script_path parameter not None) the function run_custom_script should treat a
missing file as a failing QualityCheckResult instead of returning None; change
the missing-file branch to return a QualityCheckResult dict with "name":
"custom_script", "passed": False, "output": a clear message that the configured
script (include script_path) is missing, and "duration_ms": 0 when script_path
was provided, while keeping the current behavior of returning None only when
script_path was None (i.e., the default script was not present); keep the rest
of run_custom_script (chmod, _run_command, truncation) unchanged.

cabana8471-arch added a commit to cabana8471-arch/autocoder that referenced this pull request Jan 27, 2026
…yl#110)

Combined quality gates with atomic SQL updates for parallel safety.
- Quality checks run before marking features as passing
- Atomic UPDATE prevents race conditions in parallel mode

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
cabana8471-arch added a commit to cabana8471-arch/autocoder that referenced this pull request Jan 27, 2026
…nzyl#100, leonvanzyl#108, leonvanzyl#109, leonvanzyl#110

PR leonvanzyl#110 (Quality Gates):
- Move quality checks before DB session to avoid holding locks
- Return error instead of None for missing configured custom script
- Use contextlib.closing for SQLite connections in progress.py

PR leonvanzyl#109 (Rate Limit):
- Extract rate limit logic to shared rate_limit_utils.py module
- Remove duplicated code from agent.py and test_agent.py

PR leonvanzyl#108 (SQLite Parallel):
- Sort imports alphabetically in feature_mcp.py

PR leonvanzyl#100 (Config Diagnostics):
- Add logger.warning for pkill_processes validation failures

PR leonvanzyl#95 (Infrastructure Mock):
- Add language tags to fenced code blocks in initializer template

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move quality checks before DB session to avoid holding locks
- Return error instead of None for missing configured custom script
- Use contextlib.closing for SQLite connections in progress.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@mcp_server/feature_mcp.py`:
- Around line 30-51: The import block for the project-local module is not
alphabetically ordered causing a ruff I001; reorder the names imported from
api.database (atomic_transaction, create_database, Feature) into alphabetical
order (atomic_transaction, create_database, Feature) or simply run `ruff check
--fix mcp_server/feature_mcp.py` to auto-fix; ensure the reordered import
remains directly after the sys.path insertion and before other local imports so
import order is consistent with ruff expectations.

In `@quality_gates.py`:
- Around line 130-143: The npx invocation in _detect_type_checker should include
the --no-install flag to avoid implicit downloads in CI; update the branch that
returns ("tsc", ["npx", "tsc", "--noEmit"]) to instead return ("tsc", ["npx",
"--no-install", "tsc", "--noEmit"]) so npx fails if the binary isn't present
locally.

Comment on lines 30 to 51
import json
import os
import sys
import threading
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Annotated

from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field
from sqlalchemy import text

# Add parent directory to path so we can import from api module
sys.path.insert(0, str(Path(__file__).parent.parent))

from api.database import Feature, create_database
from api.database import atomic_transaction, create_database, Feature
from api.dependency_resolver import (
MAX_DEPENDENCIES_PER_FEATURE,
compute_scheduling_scores,
would_create_circular_dependency,
)
from api.migration import migrate_json_to_sqlite
from quality_gates import load_quality_config, verify_quality
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's read the actual lines 30-51 from the file
head -n 51 mcp_server/feature_mcp.py | tail -n 22

Repository: leonvanzyl/autocoder

Length of output: 743


🏁 Script executed:

#!/bin/bash
# Run ruff check on the file to see if there are import ordering issues
ruff check mcp_server/feature_mcp.py --select=I

Repository: leonvanzyl/autocoder

Length of output: 1188


Fix import ordering to satisfy ruff (I001 error).
The import block at lines 44–51 is unsorted. Run ruff check --fix mcp_server/feature_mcp.py to automatically correct the import ordering, or manually sort the imports from api.database alphabetically.

🧰 Tools
🪛 GitHub Actions: CI

[error] 44-51: ruff check: Import block is unsorted or unformatted. Organize imports. 1 fixable with the --fix option. Command 'ruff check .' failed with exit code 1.

🤖 Prompt for AI Agents
In `@mcp_server/feature_mcp.py` around lines 30 - 51, The import block for the
project-local module is not alphabetically ordered causing a ruff I001; reorder
the names imported from api.database (atomic_transaction, create_database,
Feature) into alphabetical order (atomic_transaction, create_database, Feature)
or simply run `ruff check --fix mcp_server/feature_mcp.py` to auto-fix; ensure
the reordered import remains directly after the sys.path insertion and before
other local imports so import order is consistent with ruff expectations.

getworken pushed a commit to getworken/autocoder that referenced this pull request Jan 27, 2026
getworken pushed a commit to getworken/autocoder that referenced this pull request Jan 27, 2026
SUMMARY:
Fixed TypeScript build error in ProjectSetupRequired.tsx where startAgent
was being called with a boolean instead of an options object.

DETAILS:
- The startAgent API function signature was updated (in previous PR merges)
  to accept an options object: { yoloMode?, parallelMode?, maxConcurrency?, testingAgentRatio? }
- ProjectSetupRequired.tsx was still calling it with the old signature:
  startAgent(projectName, yoloMode) - passing boolean directly
- Changed to: startAgent(projectName, { yoloMode }) - wrapping in options object

This was the only remaining build error after merging 13+ PRs from upstream:
- PR leonvanzyl#112: Security vulnerabilities and race conditions
- PR leonvanzyl#89: Windows subprocess blocking fix
- PR leonvanzyl#109: Rate limit handling with exponential backoff
- PR leonvanzyl#88: MCP server config for ExpandChatSession
- PR leonvanzyl#100: Diagnostic warnings for config loading
- PR leonvanzyl#110: Quality gates (quality_gates.py)
- PR leonvanzyl#113: Structured logging (structured_logging.py)
- PR leonvanzyl#48: Knowledge files support (API, schemas, prompts)
- PR leonvanzyl#29: Feature editing/deletion (MCP tools)
- PR leonvanzyl#45: Chat persistence
- PR leonvanzyl#52: Refactoring feature guidance
- PR leonvanzyl#4: Project reset functionality
- PR leonvanzyl#95: UI polish, health checks, cross-platform fixes

Build now passes: npm run build succeeds with all 2245 modules transformed.
When tsc is not locally installed, npx without --no-install may prompt
or auto-download the package. Use --no-install to fail fast instead,
which is more predictable for quality gate checks.

Addresses CodeRabbit review feedback.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
cabana8471-arch added a commit to cabana8471-arch/autocoder that referenced this pull request Jan 27, 2026
Includes npx --no-install fix to prevent auto-download of tsc.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Parameters run_lint, run_type_check, run_custom shadowed the function
names run_lint_check, run_type_check, run_custom_script, causing
"'bool' object is not callable" errors at runtime.

Renamed to do_lint, do_type_check, do_custom.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant