Skip to content

test(semantic): route the semantic tool tests through the gate - #119

Merged
AlexMost merged 6 commits into
mainfrom
test/semantic-tests-through-gate
Aug 30, 2026
Merged

AlexMost merged 6 commits into
mainfrom
test/semantic-tests-through-gate

Conversation

@AlexMost

Copy link
Copy Markdown
Owner

Third of four PRs for #112. Converts runSearch (~120 call sites behind it) and
the six files in test/semantic/tools/ to reach tools through the registration,
so the repo-wide rule PR 4 records has no exception.

grep -rn '\.handler(' test/semantic/ now returns nothing; the only surviving
handler-direct calls in the repo are the two commented edit_note WRITE_FAILED
tests whose subject is the CallToolResult envelope.

Triage — every previously-green test the migration broke

Seven tests failed once their calls crossed the gate. None was relaxed; each was
either a false pin on an unreachable handler check, or a fixture passing a
parameter the advertised schema does not declare.

Unreachable handler checks (5). The schema already states the constraint, so
registerTool's .strict() wrapper rejects with INVALID_PARAMS and
details.issues before the handler's own check can run. The pins on
INVALID_ARGUMENT were pinning a branch no client can reach. Rewritten to assert
INVALID_PARAMS plus the offending field — the same triage read_notes got in
PR 1 (task 1.4), and exactly the divergence ADR-0015 is being written to record.

Test Schema constraint Was Now
rejects thresholds below 0 and above 1 threshold: z.number().min(0).max(1) INVALID_ARGUMENT INVALID_PARAMS, path: 'threshold'
rejects an empty query array query: …array(z.string()).min(1).max(8) INVALID_ARGUMENT INVALID_PARAMS, path: 'query'
rejects a query array longer than 8 same INVALID_ARGUMENT INVALID_PARAMS, path: 'query'
handler treats empty path_prefix array as empty filter filter.path_prefix .min(1) INVALID_ARGUMENT INVALID_PARAMS, path: 'filter.path_prefix'; renamed to rejects an empty path_prefix array at the gate
handler treats empty exclude_path_prefix array as empty filter filter.exclude_path_prefix .min(1) INVALID_ARGUMENT INVALID_PARAMS, path: 'filter.exclude_path_prefix'; renamed likewise

The dead code these expose is left in place deliberately — readThreshold's
value < 0 || value > 1 branch in src/modules/semantic/tool-helpers.ts and the
empty-path_prefix arm of the filter fallback are now provably unreachable
through the gate. Removing them is a source change, not a test migration; it
belongs with the same sweep as the set_property finding below.

Fixtures naming the only vault (3). In single-vault mode vaultParamShape
contributes no vault parameter at all, so { vault: 'v', … } is an unknown key.
The subject of each test was the lexical-only fallback / semantic_status /
missing backend — never vault routing — so the redundant argument was dropped and
the assertion kept intact. Same shape as PR 2's VAULT_NOT_FOUND triage.

  • search-notes.test.ts — returns lexical-only matches (no throw) when vault has no semantic backend
  • search-notes.test.ts — reports unavailable when the semantic module is globally off (no backend)
  • get-similar-notes.test.ts — throws SEMANTIC_INDEX_NOT_FOUND when vault has no semantic backend

New coverage

Per task 3.4, a rejects a vault argument in single-vault mode case was added to
get-similar-notes.test.ts and find-duplicates.test.ts, asserting
INVALID_PARAMS with path: '<root>' and a message naming vault. Net test
count: 1331 → 1333.

Notes

  • find_duplicates and get_similar_notes resolve with an array, and
    toToolResponse only populates structuredContent for a plain record — so
    callTool reads them off the text channel, as the helper's doc comment
    describes. Expected, not a gate bug. Their result types are module-internal, so
    the tests derive them from the tool's own handler rather than exporting from src/.
  • Assertions on reg.spec.inputSchema (hybrid) and registerTool(tool).spec.description
    (search-notes) were left untouched — they already cross the gate. The raw
    tool.inputSchema.safeParse assertions likewise stay on the unwrapped schema,
    which is their actual subject.
  • No schema, response shape, or error code was changed. Every commit is green on
    npm test && npm run lint && npm run typecheck.

Carried forward, not fixed here

set_property is the only caller of inferTypeAndValidate, and all three of its
UNSUPPORTED_VALUE_TYPE throws are unreachable under the declared value union
(null/undefined, a non-string/number list element, a non-scalar value — the gate
cuts all three first). The code is still declared in OperationsErrorCode. Found
in PR 2; deserves its own change rather than a drive-by.

Refs #112

🤖 Generated with Claude Code

AlexMost and others added 6 commits August 30, 2026 16:51
Refs #112

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Refs #112

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Refs #112

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…he gate

Refs #112

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Refs #112

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Refs #112

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@AlexMost
AlexMost merged commit 393866f into main Aug 30, 2026
2 checks passed
@AlexMost
AlexMost deleted the test/semantic-tests-through-gate branch August 30, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant