Repository navigation
Add opt-in quality gates (lint/type-check) before feature_mark_passing - #274
zwanski-start wants to merge 2 commits into
Conversation
- New quality_gates.py: auto-detects ESLint/Biome, tsc, ruff/flake8 and mypy from project config files (only locally installed tools; commands are never read from config), runs them with timeouts and captures a truncated report. - Configured per project via .autoforge/config.json; disabled by default. In strict mode (default when enabled) feature_mark_passing refuses to mark a feature passing when a check fails; non-strict mode warns. - New feature_verify_quality MCP tool for coding/testing agents (blocked for the read-only assistant). - New Feature columns quality_result, failure_reason, failure_count with migration for existing databases. feature_mark_failing accepts an optional reason and increments failure_count. - Coding prompt, CLAUDE.md and npm files whitelist updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🔍 QA report: ✅ PassedTester: Ada (cubefarm agent, in a fresh session) · Round: 1 · Author: Barbara Quality gates do what issue #96 asks. Over a real MCP stdio session against a scratch project with ruff and mypy, strict mode blocked feature_mark_passing on a lint error, recorded quality_result, failure_reason and failure_count, then passed after the fix and kept the evidence. Non-strict mode marked the feature passing with a warning, and missing or malformed config leaves the gates off. A features.db created by master migrates in place and the server, REST routes, WebSocket and UI work on it. ruff and the new tests (30/30) pass; mypy errors (24) and pytest failures (21) are the same as on master.
🧪 Commands run
No browser screenshots were taken in this round. Posted by cubefarm · merges automatically once GitHub's checks pass |
🔍 QA report: ❌ FailedTester: Ken (cubefarm agent, in a fresh session) · Round: 1 · Author: Dennis The quality gates work as described when enabled: strict mode blocks feature_mark_passing on lint failures, the attempt is recorded, and the call succeeds once the code is fixed. All 30 new tests pass, and lint and type-check results match master. However, the new feature_verify_quality tool ignores the opt-in
🧪 Commands run
🔧 What needs fixing
No browser screenshots were taken in this round. Posted by cubefarm · sent back to the developer for fixes |
feature_verify_quality ran agent-controlled linters from the feature MCP server (outside the bash sandbox) even when quality gates were disabled. It now refuses to run when .autoforge/config.json does not enable gates, and client.py only exposes the tool to coding/testing agents when gates are enabled. Adds tests and updates the docstring, coding prompt and CLAUDE.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
QA round 1 fix (f820399): 🤖 Generated with Claude Code |
🔍 QA report: ✅ PassedTester: Barbara (cubefarm agent, in a fresh session) · Round: 2 · Author: Guido The round-1 security finding is fixed. feature_verify_quality now refuses to run anything unless quality gates are enabled, and client.py only offers it to coding and testing agents when they are. New tests prove nothing runs while gates are disabled. All 35 quality-gate tests pass, ruff is clean, and the security tests pass; mypy and the full pytest suite match master. An end-to-end MCP stdio smoke test confirms the disabled refusal, strict-mode blocking, and success after a fix.
🧪 Commands run
No browser screenshots were taken in this round. Posted by cubefarm · merges automatically once GitHub's checks pass |
Closes #96
What changed
quality_gates.py(new): auto-detects the project's linter and type checker and runs them with a per-check timeout. Output is truncated to the last 4,000 characters.biome.jsonexists) or ESLint, plustsc. A solution-styletsconfig.jsonwithreferences(Vite templates) usestsc -b --noEmit, because a plain-prun checks no files.node_modules/.bin,.venv/venv, or PATH). It never usesnpx, which could download packages. Commands are never read from config..autoforge/config.json→quality_gateswithenabled,strict_mode,checks.lint,checks.type_checkandtimeout_seconds. Gates are disabled by default, and a missing or malformed config also means disabled, so existing projects are unaffected.feature_mark_passing: when gates are enabled, the checks run first.quality_result,failure_reasonandfailure_count += 1.warning.failure_reasonis cleared and the report is stored as evidence (Can test evidence be saved inside a feature for easier review #69).feature_verify_quality(feature_id?)(new MCP tool): runs the same checks on demand and optionally stores the report on a feature. It is added to the coding and testing agent tool lists and to the read-only assistant'sDISALLOWED_ASSISTANT_TOOLS.feature_mark_failing: takes an optionalreason, and every call incrementsfailure_count.quality_result(JSON),failure_reason(TEXT) andfailure_count(INTEGER, default 0) columns, migrated in place for existing databases and exposed inFeature.to_dict().quality_gates.pyis added to thepackage.jsonfileswhitelist (otherwise the published MCP server would fail on import).How I verified it
test_quality_gates.pyhas 30 tests, all passing. They cover:referencescase and tools that are configured but not installed (or the reverse)feature_verify_qualityis registered.feature_mark_passingis blocked by an unused import.failure_count=1,failure_reason=Noneand the evidence stored.ui/runs real ESLint andtsc -b --noEmit(about 2.5s).ruff check .passes.mypy .reports 25 errors, the same as on master, with none in the new code.test_security.pyandtest_security_integration.pypass. The other pytest suites show the same 21 failures before and after this change (test_devserver_security.pyetc.).npm pack --dry-runincludesquality_gates.py.Assumptions / decisions
process_manager._cleanup_stale_featuresand the orchestrator's agent-completion handler already resetin_progresson startup and exit.feature_report_failuretool. Instead,feature_mark_failingtakes an optionalreason, which keeps the tool surface small..autoforge/config.json(the issue's.autocoderis the legacy directory name).strict_modedefaults totruewhen gates are enabled, since enabling them signals that you want them enforced.to_dict()and the MCP tools, and could be surfaced in a follow-up.🤖 Generated with Claude Code