[PR #1543] [CLOSED] fix(verifiers): reuse validators for duplicate tool output schema ids #2959

Closed
opened 2026-10-17 21:12:15 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1543
Author: @BaaRai
Created: 10/10/2026
Status: ❌ Closed

Base: main ← Head: fix/duplicate-output-schema-validators


📝 Commits (1)

  • f74fb07 fix(verifiers): reuse validators for duplicate tool output schema ids

📊 Changes

3 files changed (+20 additions, -4 deletions)

View changed files

📝 scripts/lib/real-ghidra-boundaries.mjs (+7 -1)
📝 scripts/lib/real-hopper-boundaries.mjs (+7 -1)
📝 scripts/verify/electron/tool-contracts.mjs (+6 -2)

📄 Description

Supersedes #1527 with the same fix for the two boundary scripts plus the third affected site, validated on the real lanes. Credit to CassieFox23 for the diagnosis and the reuse approach on the #1382 thread.

Summary

Since #1433, self-contained tool output schemas carry a content-derived $id, and tools with identical output schemas intentionally share one id (139 catalog tools, 118 distinct ids). The real-tool verifier scripts compile every catalog schema into one shared Ajv instance, so the second tool with a shared id throws before any fixture runs. Three scripts share this pattern: the Ghidra boundary check (all Ghidra lanes, #1518), the Hopper boundary check, and the Electron tool-contract probe, which compiles both input and output schemas through one instance.

Problem and expected behavior

main @3cd80cbb, npm run verify:ghidra:cross-format, fails immediately, matching the #1382 lane report byte for byte:

Error: schema with key or id "urn:rea:tool-output:sha256:8d99d0ac\u2026" already exists
    at verifyGhidraBoundaries (scripts/lib/real-ghidra-boundaries.mjs:43)

Expected: compiling a catalog whose tools intentionally share identical schemas must reuse the registered validator. An id that hashes the whole schema means an equal id is an equal schema, so per-tool validation semantics are unchanged.

Change and scope

Three call sites switch from unconditional ajv.compile to reuse-when-id-registered. No src/ changes; the server-side validator reuse from #1433 is untouched, and schemas without an $id behave exactly as before.

Contract and boundary impact

not applicable: verification scripts only; no tool contracts, providers, or product code change.

Evidence and regression coverage

All runs on Linux (Kali, node 24.19, Ghidra 12.1.4 + JDK 21, Hopper 6.4.2 demo, Electron 34.3.0 under xvfb):

  • main @3cd80cbb reproduces the schema throw (above).
  • This branch: verify:ghidra:cross-format completes fully green: ok: true, all seven fixtures, catalog_tools: 139, successful_calls: 286, rejected_calls: 52, cli_mcp_parity: true, cleanup: complete. This also re-validates the merged #1382 cross-format fixture end to end.
  • verify:hopper:linux: the boundary-contract phase now compiles the catalog and runs its tool-call verification (it previously aborted at the schema line); the lane then stops at the long-literal string-typing boundary of the pinned demo documented on #341, which predates this break and does not reproduce on a licensed build.
  • verify:electron: the tool-contract phase compiles input and output schemas without the id collision and completes all four probes with schema-validated results; the lane afterwards fails on a process-tree cleanup assertion (run-token mismatch under the xvfb wrapper) that is specific to this environment and unrelated to schemas.

Versus #1527: that PR applies the reuse to the two boundary scripts only and its validation section notes the lanes were not run there. This PR covers the Electron tool-contract site as well (input schemas compile through the same shared instance) and each changed site was exercised on a real lane.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/1543 **Author:** [@BaaRai](https://github.com/BaaRai) **Created:** 10/10/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/duplicate-output-schema-validators` --- ### 📝 Commits (1) - [`f74fb07`](https://github.com/morluto/rea/commit/f74fb0795658cc94fd3f98b77aed35152ba05666) fix(verifiers): reuse validators for duplicate tool output schema ids ### 📊 Changes **3 files changed** (+20 additions, -4 deletions) <details> <summary>View changed files</summary> 📝 `scripts/lib/real-ghidra-boundaries.mjs` (+7 -1) 📝 `scripts/lib/real-hopper-boundaries.mjs` (+7 -1) 📝 `scripts/verify/electron/tool-contracts.mjs` (+6 -2) </details> ### 📄 Description Supersedes #1527 with the same fix for the two boundary scripts plus the third affected site, validated on the real lanes. Credit to CassieFox23 for the diagnosis and the reuse approach on the #1382 thread. ## Summary Since #1433, self-contained tool output schemas carry a content-derived $id, and tools with identical output schemas intentionally share one id (139 catalog tools, 118 distinct ids). The real-tool verifier scripts compile every catalog schema into one shared Ajv instance, so the second tool with a shared id throws before any fixture runs. Three scripts share this pattern: the Ghidra boundary check (all Ghidra lanes, #1518), the Hopper boundary check, and the Electron tool-contract probe, which compiles both input and output schemas through one instance. ## Problem and expected behavior main @3cd80cbb, `npm run verify:ghidra:cross-format`, fails immediately, matching the #1382 lane report byte for byte: ``` Error: schema with key or id "urn:rea:tool-output:sha256:8d99d0ac\u2026" already exists at verifyGhidraBoundaries (scripts/lib/real-ghidra-boundaries.mjs:43) ``` Expected: compiling a catalog whose tools intentionally share identical schemas must reuse the registered validator. An id that hashes the whole schema means an equal id is an equal schema, so per-tool validation semantics are unchanged. ## Change and scope Three call sites switch from unconditional `ajv.compile` to reuse-when-id-registered. No `src/` changes; the server-side validator reuse from #1433 is untouched, and schemas without an $id behave exactly as before. ## Contract and boundary impact not applicable: verification scripts only; no tool contracts, providers, or product code change. ## Evidence and regression coverage All runs on Linux (Kali, node 24.19, Ghidra 12.1.4 + JDK 21, Hopper 6.4.2 demo, Electron 34.3.0 under xvfb): - main @3cd80cbb reproduces the schema throw (above). - This branch: `verify:ghidra:cross-format` completes fully green: `ok: true`, all seven fixtures, `catalog_tools: 139`, `successful_calls: 286`, `rejected_calls: 52`, `cli_mcp_parity: true`, `cleanup: complete`. This also re-validates the merged #1382 cross-format fixture end to end. - `verify:hopper:linux`: the boundary-contract phase now compiles the catalog and runs its tool-call verification (it previously aborted at the schema line); the lane then stops at the long-literal string-typing boundary of the pinned demo documented on #341, which predates this break and does not reproduce on a licensed build. - `verify:electron`: the tool-contract phase compiles input and output schemas without the id collision and completes all four probes with schema-validated results; the lane afterwards fails on a process-tree cleanup assertion (run-token mismatch under the xvfb wrapper) that is specific to this environment and unrelated to schemas. Versus #1527: that PR applies the reuse to the two boundary scripts only and its validation section notes the lanes were not run there. This PR covers the Electron tool-contract site as well (input schemas compile through the same shared instance) and each changed site was exercised on a real lane. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:12:15 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#2959
No description provided.