From 088f6c2ea1fa3f2f5dcd7c14b5f51f31621be4c8 Mon Sep 17 00:00:00 2001 From: Mother Seara Date: Tue, 25 Aug 2026 04:46:11 +0900 Subject: [PATCH] test(mcp): report what was counted, not just the failure count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to #5, from review feedback on that PR. The summary line read `all _run contract tests passed (0 failed)`. A run that collected ZERO checks prints exactly the same thing, so the line could not tell "everything passed" apart from "nothing ran". The real evidence was the eight `ok` lines above it — but the summary is what a human quotes later, and it was the weakest statement in the file. This is the same rule the rest of this work applies elsewhere: a green without a denominator is not a measurement. `substance_check.py` was already reporting `n/n (...)`; the two summary lines in this repo now agree with each other. - summary is now `N/M checks passed`, so a sabotaged run reads `4/8` instead of a bare count - an empty run is an explicit failure rather than a vacuous pass, and it is decided BEFORE printing — a summary saying "passed" above a failure line is the same trap one line lower Also drops an em-dash from the MCP import step's output: it renders as `?` on the Windows console, which reads like a mojibake defect in the log when nothing is wrong. The test passes either way; this only stops the log from carrying a false signal. Verified in all three directions: normal run 8/8, fix reverted 4/8, no checks collected fails. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 4 +++- mcp/tests/test_run_contract.py | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ecce60..1c93e53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,9 @@ jobs: 'arc_close','build_handoff','ralph_gate_check','arc_prereg','verify_gate', 'status','arc_list')] assert len(tools) == 12, tools - print("yeoul-mcp OK — 12 tools") + # ASCII only: the em-dash renders as "?" on the Windows console, which reads like + # a mojibake defect in the log when nothing is actually wrong. + print("yeoul-mcp OK - 12 tools") PY - name: _run subprocess contract (stdin never inherited, UTF-8 pinned) run: python mcp/tests/test_run_contract.py diff --git a/mcp/tests/test_run_contract.py b/mcp/tests/test_run_contract.py index 6ab56cf..bca76b2 100644 --- a/mcp/tests/test_run_contract.py +++ b/mcp/tests/test_run_contract.py @@ -29,9 +29,11 @@ from yeoul_mcp import server # noqa: E402 FAIL = [] +RAN = [] def check(desc, cond, detail=""): + RAN.append(desc) print((" ok " if cond else " FAIL ") + desc + ((" -- " + detail) if detail and not cond else "")) if not cond: FAIL.append(desc) @@ -122,7 +124,18 @@ def main(): test_stdin_not_inherited(tmp) test_utf8_pinned_under_hostile_locale(tmp) test_missing_script_is_not_a_pass(tmp) - print("\n%s (%d failed)" % ("all _run contract tests passed" if not FAIL else "CONTRACT TESTS FAILED", len(FAIL))) + # 🔴 Print WHAT WAS COUNTED, not just the failure count. A run that collected zero checks + # prints "0 failed" too, so that summary cannot tell "everything passed" apart from + # "nothing ran" — and the summary line is what a human quotes later, not the ok lines. + # (substance_check.py already reports `n/n (...)`; these two summaries now match.) + if not RAN: + # Decide BEFORE printing: a summary that says "passed" above a failure line is the + # same trap one line lower down. + print("\nCONTRACT TESTS FAILED: no checks ran at all — an empty run is not a pass") + return 1 + print("\n%s: %d/%d checks passed" + % ("all _run contract tests passed" if not FAIL else "CONTRACT TESTS FAILED", + len(RAN) - len(FAIL), len(RAN))) return 1 if FAIL else 0