From 2b9ae41872b31233b6ab6d5fd4055292f5469c54 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Wed, 29 Jul 2026 23:43:17 +0300 Subject: [PATCH] refactor: replace fragile io.StringIO output suppression with validate_all_detailed _run_checks() was using io.StringIO + redirect_stdout/redirect_stderr to suppress terminal output while running ValidationEngine.validate_all(). This approach was fragile and manually reconstructed check dicts from rule templates rather than actual failure details. Switch to ValidationEngine.validate_all_detailed() which: - Internally sets _suppress_output on each validator - Returns structured CheckOutcome objects with real failure details - Provides to_dict() for direct serialization - Runs all rules through a single engine call instead of one per rule --- src/commit_check_mcp/server.py | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/commit_check_mcp/server.py b/src/commit_check_mcp/server.py index 139a63a..e389597 100644 --- a/src/commit_check_mcp/server.py +++ b/src/commit_check_mcp/server.py @@ -3,16 +3,14 @@ from __future__ import annotations from contextlib import contextmanager -from contextlib import redirect_stderr, redirect_stdout from importlib.metadata import version -import io from pathlib import Path import os from typing import Any from commit_check import __version__ as commit_check_version from commit_check.config_merger import deep_merge, get_default_config, load_toml_config -from commit_check.engine import ValidationContext, ValidationEngine, ValidationResult +from commit_check.engine import ValidationContext, ValidationEngine, CheckOutcome from commit_check.rule_builder import RuleBuilder, ValidationRule from commit_check.rules_catalog import BRANCH_RULES, COMMIT_RULES, PUSH_RULES from mcp.server.fastmcp import FastMCP @@ -114,25 +112,17 @@ def _run_checks( context: ValidationContext, config: dict[str, Any], ) -> dict[str, Any]: - """Run commit-check rules and always return structured per-check results.""" + """Run commit-check rules and return structured per-check results. + + Uses ValidationEngine.validate_all_detailed() which internally + suppresses terminal output and collects structured failure details. + """ rules = RuleBuilder(config).build_all_rules() filtered: list[ValidationRule] = [r for r in rules if r.check in check_names] - checks: list[dict[str, Any]] = [] - for rule in filtered: - with io.StringIO() as _out, io.StringIO() as _err: - with redirect_stdout(_out), redirect_stderr(_err): - status = ValidationEngine([rule]).validate_all(context) - passed = status == ValidationResult.PASS - checks.append( - { - "check": rule.check, - "status": "pass" if passed else "fail", - "value": context.stdin_text or "", - "error": "" if passed else (rule.error or ""), - "suggest": "" if passed else (rule.suggest or ""), - } - ) + engine = ValidationEngine(filtered) + outcomes: list[CheckOutcome] = engine.validate_all_detailed(context) + checks = [o.to_dict() for o in outcomes] overall = "fail" if any(c["status"] == "fail" for c in checks) else "pass" return {"status": overall, "checks": checks}