From cc00d7ea5d4b09e4fa313bba64250ee7556e0212 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 24 Oct 2026 11:32:51 +0000 Subject: [PATCH] refactor(downgrader): drop the unreachable isRecord check on anyOf targets `convertSchemaRef` only skipped adding a holder that isn't an object, which happens just for a kept `$ref` whose part before `/anyOf/` doesn't resolve. `anyOfTargets` is only queried with input schema objects, so adding the unresolved value is harmless, and branch coverage is back to 100%. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01YNzPR6fb2NHVQPYKsD2eta --- packages/downgrader/src/v3.1-to-v3.0.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/downgrader/src/v3.1-to-v3.0.ts b/packages/downgrader/src/v3.1-to-v3.0.ts index 39e4b35..0b8ff35 100644 --- a/packages/downgrader/src/v3.1-to-v3.0.ts +++ b/packages/downgrader/src/v3.1-to-v3.0.ts @@ -131,7 +131,7 @@ const twoBranchAnyOfs: [schema: Record, input: object][] = [] // Input schemas whose `anyOf` a `$ref` kept as written points into. They keep // it, so the `$ref` still resolves. -const anyOfTargets = new Set() +const anyOfTargets = new Set() // A branch with these stays: null can still fail them beside `nullable: true`, // and a `nullable` already there was written 3.0-style. @@ -280,10 +280,7 @@ function refOr(convert: Convert): Convert { function convertSchemaRef(ref: string, ctx: Context): unknown { if (!isInlined(ref, ctx)) { for (let at = ref.indexOf('/anyOf/'); at !== -1; at = ref.indexOf('/anyOf/', at + 1)) { - const holder = resolvePointer(ref.slice(0, at), ctx) - if (isRecord(holder)) { - anyOfTargets.add(holder) - } + anyOfTargets.add(resolvePointer(ref.slice(0, at), ctx)) } // A `$ref` kept as written loses what its target loses. Converting the // target here reuses the copy the components get, and stops at a cycle.