Repository navigation
Prove the three unusable-URL guards that landed unproved - #415
Conversation
The code review named these vacuous in its FIRST round; I fixed the other findings and disclosed these rather than fixing them, then let each subsequent round's new P1 push them further down. Stating a gap in a commit message is not the same as closing it. Cursor and Claude are proved by non-entry through the injectable client factories they already expose. Both matter for the same reason: asserting exit 0 is vacuous, because Cursor's outer catch-all returns 0 and Claude's CreateClientWithinBudgetAsync swallows the exception and takes the SAME degraded branch — so every effect assertion passes with the guard deleted. Only non-entry separates the two. McpJudgeServer had no test at all. A child process is the only honest venue, since the failure being fixed is the process dying before the JSON-RPC handshake: the test completes the handshake, asserts a tool call comes back as a protocol-level error rather than a crash, and asserts the server is still answering afterwards. All three mutation-checked: deleting the Cursor guard, deleting the Claude client guard, or restoring eager client construction in the judge each fails a test (the last fails five). Unit suite vs origin/main: one extra failure, ImportChainsAsync_dispatches_independent_chains_in_parallel — a parallel-dispatch timing test unrelated to this change, green 3/3 in isolation. Integration 191/191. AOT clean.
PR Summary by QodoAdd mutation-resistant tests for remaining unusable-URL guards
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Code Review by Qodo
1.
|
The judge test wrote to the child's stdin without flushing and timed out via Task.WhenAny without cancelling the losing ReadLineAsync — so a slow child could miss the request, and the abandoned read could later consume a response meant for a subsequent assertion, desynchronising every later check. It now mirrors McpSessionsServerTests.SendRequest: flush, read under a cancellation token, and surface stderr when stdout closes. Requests are built with JsonObject rather than hand-quoted raw strings, which had already produced one malformed payload. Also trimmed the XML doc comments qodo flagged against this repo's keep-comments-minimal rule, leaving only the non-obvious rationale — why non-entry rather than exit code, and why the cancellation token matters. The judge mutant still kills 5 tests. Integration suite green locally; the concurrent MCP-test flakes seen while verifying are the machine, not this change — merged main without this commit fails 4 and 14 in the same suite under the same load.
Follow-up to #413. Linear: AI-1586
Tests only — no production change, 106 lines.
#413 landed with three guards whose tests could not fail if the guard were deleted. The code review named all three in its first round; I fixed the other findings and disclosed these instead, then let each subsequent round's new P1 push them down. Stating a gap in a commit message is not closing it.
Why each was vacuous
CreateClientWithinBudgetAsyncswallow the exception and take the same branch, so every effect is identicalMcpJudgeServerWhat replaces them
Cursor and Claude are proved by non-entry, through the injectable client factories they already expose: the factory records invocation and fails the test if called. That is the only assertion form that separates "the guard ran" from "something downstream absorbed it".
McpJudgeServergets a child-process JSON-RPC exchange. A child is the only honest venue, because the failure being fixed is the process dying before the handshake — an in-process test cannot observe it. The test completesinitialize, asserts atools/callreturns a protocol-level error rather than crashing, asserts the server still answers a subsequenttools/list, and asserts it does not exit 2.Mutation-checked
Unit suite diffed against
origin/main: one extra failure,ImportChainsAsync_dispatches_independent_chains_in_parallel— a parallel-dispatch timing test unrelated to this change, green 3/3 in isolation. Integration 191/191. AOT publish clean.