UVH-IN7: an observed tool error reaches response, even unauthored - #4491
UVH-IN7: an observed tool error reaches response, even unauthored#4491chelojimenez wants to merge 3 commits into
Conversation
A case can author only transcript predicates — nothing about tools at all —
and still have a tool fail on the server during the run. `response` was
`notApplicable` for such a case, because applicability was decided purely
from what the case AUTHORED. So when `failOnToolError` failed the trial on
exactly that tool error, the chain had every applicable stage green and no
row able to say why the verdict was red.
That is the disagreement class found in prod: the legacy verdict failing on
a recovered tool error the chain could not represent. It was never a
verdict bug — it was a chain with no vocabulary for what happened.
An observed errored tool call now makes `response` measurable on its own,
filing `failed / toolError` under `serverData` like any other
server-answered error. Applicability and the deriver share ONE predicate
(`hasObservedToolFailure`) rather than two copies of the condition, so a
stage cannot be switched on by one rule and then found empty by the other.
Two boundaries are deliberate:
- A span carrying an `mcpErrorCode` never reached the server's handler,
so it stays a setup fact and does NOT turn the stage on. Attributing
our own transport failure to the server is the mis-attribution this
module exists to prevent.
- A case with no tool failure is unchanged: `response` stays
`notApplicable`, because there is still nothing for it to decide.
This is the one evidence-driven entry in the applicability table, and it is
a POSITIVE observation rather than a gap — which is what keeps the
surrounding rule intact. A stage turned on by observed evidence cannot then
be reported as an evidence gap, because the deriver holds the very span
that turned it on.
Analyzer 6 -> 7; `STAGE_REASONS` unmoved, so no mirror re-pin. Verdicts and
gate exit codes unchanged (CLI 1182 tests); runner-parity snapshots differ
only in the version stamp, verified by filtering the diff.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y4jTtZJsDeaterEzKwpF2p
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_1be93e91-c1dd-4b66-bd30-cb8277c2b848) |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Internal previewPreview URL: https://mcp-inspector-pr-4491.up.railway.app |
…vc-mcp-eval-reporting-gyycwl-in7
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_de307d95-4a1f-4d82-9a60-a3e6f23dd3ca) |
…vc-mcp-eval-reporting-gyycwl-in7
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_030d07d2-4f4b-4296-8f77-f692359ad86f) |
UVH-IN7 — inspector lane, step 3. Analyzer 6 → 7. Stacked on #4490 (UVH-IN1) → #4488 (UVH-IN5).
This is the fix for the O0 investigation: the 8 prod trials that were fully green in the chain while their legacy verdict said
failed.What those trials actually were
A case can author only transcript predicates — nothing about tools at all — and still have a tool fail on the server during the run.
responsewasnotApplicablefor such a case, because applicability was decided purely from what the case authored. So whenfailOnToolErrorfailed the trial on exactly that tool error, the chain had every applicable stage green and no row able to say why the verdict was red.It was never a verdict bug. It was a chain with no vocabulary for what happened — which is why the right fix is an analyzer change rather than copy that papers over the disagreement.
The change
An observed errored tool call now makes
responsemeasurable on its own, filingfailed / toolErrorunderserverDatalike any other server-answered error.Applicability and the deriver share one predicate (
hasObservedToolFailure) rather than two copies of the condition, so a stage cannot be switched on by one rule and then found empty by the other.Two boundaries are deliberate:
mcpErrorCodedoes not turn the stage on. It never reached the server's handler, so it stays a setup fact — attributing our own transport failure to the server is precisely the mis-attribution this module exists to prevent.responsestaysnotApplicable, because there is still nothing for it to decide.Why this doesn't break the "computed before evidence" rule
The applicability table's whole point is that an inapplicable stage can never be reported as an evidence gap. This entry reads a single positive observation, not an absence — and a stage turned on by observed evidence cannot then be reported as a gap, because
deriveResponseholds the very span that turned it on. That reasoning is written at the call site so the next reader doesn't have to reconstruct it.Verification
response: failed / toolErrorwith categoryserverDataandfirstFailedStage: response; the chain no longer goes all-green while the verdict fails (the O0 shape, asserted directly); a transport-local error does not turn the stage on; no errored span leaves an unauthoredresponseinapplicable; an already-authored case is unaffected.sdk: 6886 passed (313 files). Inspector server: 700 passed. CLI: 1182 passed — gate exit codes unchanged.runner-paritysnapshots: 84 diff lines, all the version stamp, verified by filtering.STAGE_REASONSdoes not move (toolErroralready existed), so the backend mirror needs no re-pin for this bump.Note for the reader
Post-IN7, the
failOnToolError: falsevariant now reportsresponse: failed / toolErrorwhile the trial verdict passes. That is intended and is the honest reading: the chain reports what the server did, and the trial's own policy decides whether that fails the run. The two are allowed to differ — what was wrong before was the chain having nothing to say.Generated by Claude Code
Note
Medium Risk
Changes core eval stage applicability and failure attribution for transcript-only cases; behavior shifts for trials where tool errors were previously invisible in the stage chain.
Overview
Fixes eval stage derivation so predicate-only cases can still surface server tool failures on the
responsestage instead of leaving itnotApplicablewhile the legacy verdict fails onfailOnToolError.hasObservedToolFailureis introduced and used for bothresponseapplicability andderiveResponse, so an observed content/domain tool error filesfailed / toolError(serverData) without applicability and derivation drifting apart. Errored spans with anmcpErrorCode(transport/setup) still do not turnresponseon; runs with no tool failure behave as before.STAGE_ANALYZER_VERSIONbumps 6 → 7;STAGE_REASONSis unchanged. Tests, parity corpus, and runner snapshots are re-stamped for the new version.Reviewed by Cursor Bugbot for commit dbb9fb3. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Fixes the stage analyzer so an observed tool error makes
responsemeasurable even when the case authored nothing about tools. PreviouslyresponsewasnotApplicablefor such cases, so a server tool error that failed the trial left every applicable stage green with no row saying why the verdict was red. Now the chain filesfailed / toolErrorunderserverDatainstead.Note
hasObservedToolFailurepredicate.mcpErrorCodestays a setup fact and does not turn the stage on.responseasnotApplicable.STAGE_REASONSis unchanged, so the backend mirror needs no re-pin.Written for commit dbb9fb3. Summary will update on new commits.