fix: drop the unreachable root rule, correct the always-false suggestion
Copilot review round 2.
- Remove `non-object-root` entirely. It could never fire: the SDK types
`inputSchema` with `type: literal("object")`, so a tool with any other
root fails `ListToolsResultSchema` and `salvageListItems` drops it
before any client sees it. Verified against a live server advertising
`inputSchema: {type: "array"}` — `listAllTools()` returns []. A rule
that cannot fire is worse than none, because the docs then claim a
check the tool does not perform; the condition is already reported
through the malformed-items surface. Pinned by an integration test so
a change in that behavior is a signal rather than a silent gap.
- Fix the bare-`false` suggestion. `properties: {a: false}` forbids the
property; deleting the entry *permits* it with any value under the
default `additionalProperties`, so the advice inverted the schema it
replaced. Now recommends `{"not": {}}` and says why deletion differs.
- Exempt `not`-parented schemas from `untyped-schema`, so the `{"not":
{}}` above does not trip this module's own rule — under negation an
always-accepting subschema means always-reject, making "accepts any
value" the exact opposite of what it does. Scoped to that position,
not inherited by its subtree.
- Say plainly, in the `true` and untyped suggestions, that they narrow
the schema deliberately rather than implying an equivalent rewrite.
`true` has no portable object-form equivalent — `{}` is the very shape
this lint flags.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UL9retfvAXRgvi6EWk4SY4
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
c389565783
commit
cac97c142c
1 changed files with 136 additions and 78 deletions
|
|
@ -110,6 +110,24 @@ describe("rawToolSchemas override (#1005)", () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it("drops a tool whose inputSchema root is not an object, before any client sees it", async () => {
|
||||
// This is why `schemaLint` has no "inputSchema must be an object" rule.
|
||||
// The SDK types `inputSchema` with `type: literal("object")`, so such a
|
||||
// tool fails `ListToolsResultSchema` and `salvageListItems` removes it —
|
||||
// no client can pass it to the lint, and a rule for it could never fire.
|
||||
// If this ever starts returning the tool, that rule becomes worth adding
|
||||
// back and this test is the signal.
|
||||
const started = await start({
|
||||
rawToolSchemas: {
|
||||
echo: { inputSchema: { type: "array", items: { type: "string" } } },
|
||||
},
|
||||
});
|
||||
const connected = await connect(started.url);
|
||||
|
||||
const { tools } = await connected.listAllTools();
|
||||
expect(tools.map((t) => t.name)).toEqual(["get_weather"]);
|
||||
});
|
||||
|
||||
it("leaves an unnamed tool's real schema alone", async () => {
|
||||
const started = await start({
|
||||
rawToolSchemas: { echo: { outputSchema: { type: "object" } } },
|
||||
|
|
|
|||
Loading…
Reference in a new issue