fix: address Copilot review on the schema portability lint

- Scope `non-object-root` to `inputSchema`. The pinned SDK types
  `inputSchema` with `type: literal("object")` but `outputSchema` as a
  bare `looseObject`, so a `{"type":"string"}` output is conforming; the
  rule was claiming a requirement MCP does not make, at error severity.

- Decide `untyped-schema` from an allowlist of constraining keywords
  rather than a denylist of annotations. JSON Schema ignores keywords it
  does not recognize, so `{"vendorHint": true}` accepts every value and a
  denylist passed it as constrained. `$defs`-only schemas now flag too.

- Walk `dependentSchemas` and draft-07 `dependencies`, with a test
  pinning that the property-name-array form is not a schema position.

- Suggest `anyOf` branches for an array-form `type`, never "drop it from
  `required`" — accepting `null` and permitting absence are independent
  contracts, so the old suggestion silently changed the schema's meaning.

- Reject `--strict` alongside `--app-info`. That path returns NDJSON from
  `runMethod` and never reaches the lint, so the flag was a no-op gate
  that could never fail.

- Colour the web sidebar flag from the `--inspector-*` severity tokens,
  matching the detail panel and avoiding the default yellow that failed
  the a11y check.

- Add a live integration test for `rawToolSchemas`. It caught that an
  `outputSchema` override on a preset returning no structured content
  makes every call to that tool fail client-side validation — the
  showcase config did exactly that, so the flagged tool could not be
  run. Moved the bare `true` onto `get_temp`, documented the caveat, and
  pinned both halves.

- Drop the double cast from the lint test fixture.

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:
cliffhall 2026-08-25 01:41:12 -04:00
commit c389565783

View file

@ -57,6 +57,11 @@ const ListItemButton = UnstyledButton.withProps({
// Schema-portability flag (#1005). Sits in the row rather than only in the
// detail panel so a problem tool is visible without clicking each one — the
// findings are rare enough that a marked row means something.
//
// Coloured from the same `--inspector-*` severity tokens the detail panel's
// findings list uses, rather than from Mantine's `color="yellow"`: those are
// the pairings this app already tunes against its own surfaces in both colour
// schemes, and the default yellow is what failed the a11y check there.
const SchemaFlagIcon = ThemeIcon.withProps({
size: "xs",
variant: "transparent",
@ -86,7 +91,11 @@ export function ToolListItem({ tool, selected, onClick }: ToolListItemProps) {
withArrow
>
<SchemaFlagIcon
color={hasError ? "red" : "yellow"}
c={
hasError
? "var(--inspector-danger-text)"
: "var(--inspector-warning-text)"
}
aria-label={
hasError
? "Schema portability errors"