From c3eeaa710582a2a56e16de8e77ea11ccdd538255 Mon Sep 17 00:00:00 2001 From: luvs01 Date: Fri, 7 Aug 2026 15:35:04 +0900 Subject: [PATCH] fix(routing): bound reasoning effort hydration --- src/routing/trace.ts | 13 +++++++------ tests/route-decision-trace.test.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/routing/trace.ts b/src/routing/trace.ts index 169400d8d..439092f18 100644 --- a/src/routing/trace.ts +++ b/src/routing/trace.ts @@ -465,13 +465,14 @@ function parseCapability(raw: unknown, caps: ParseCaps): RouteCapabilityEvidence if (image !== undefined) out.image = image; const structuredOutput = unknownable(raw.structuredOutput); if (structuredOutput !== undefined) out.structuredOutput = structuredOutput; - if (Array.isArray(raw.reasoningEfforts) - && raw.reasoningEfforts.slice(0, 8).every((value): value is string => typeof value === "string")) { - if (raw.reasoningEfforts.some((value: unknown) => typeof value === "string" + const reasoningEfforts = Array.isArray(raw.reasoningEfforts) + ? raw.reasoningEfforts.slice(0, 8) + : undefined; + if (reasoningEfforts + && reasoningEfforts.every((value): value is string => typeof value === "string")) { + if (reasoningEfforts.some((value: unknown) => typeof value === "string" && value.length > MAX_TRACE_STRING)) caps.strings = true; - out.reasoningEfforts = raw.reasoningEfforts - .slice(0, 8) - .map(value => value.slice(0, MAX_TRACE_STRING)); + out.reasoningEfforts = reasoningEfforts.map(value => value.slice(0, MAX_TRACE_STRING)); } if (raw.serviceTier === "unknown") { out.serviceTier = "unknown"; diff --git a/tests/route-decision-trace.test.ts b/tests/route-decision-trace.test.ts index 5a0c00579..da62d8480 100644 --- a/tests/route-decision-trace.test.ts +++ b/tests/route-decision-trace.test.ts @@ -223,6 +223,33 @@ describe("route decision traces (RI-01)", () => { expect(trace.candidates.every(candidate => candidate.exclusions.length === MAX_EXCLUSIONS_PER_CANDIDATE)).toBe(true); }); + test("normalization only inspects retained reasoning efforts", () => { + const reasoningEfforts = Array.from({ length: 1_000_000 }) as unknown[]; + reasoningEfforts.fill("medium", 0, 8); + Object.defineProperty(reasoningEfforts, reasoningEfforts.length - 1, { + get: () => { throw new Error("reasoning effort outside the retained range was inspected"); }, + }); + const raw = { + version: 1, + decisionId: "abcdef012345", + createdAt: 1, + requestedModel: "a/m1", + routeKind: "policy", + requirements: [], + candidates: [{ + provider: "a", + model: "m1", + eligible: true, + exclusions: [], + capability: { reasoningEfforts }, + }], + selected: { candidateIndex: 0, provider: "a", model: "m1", reason: "policy" }, + }; + + expect(normalizeRouteDecisionTrace(raw)?.candidates[0]?.capability?.reasoningEfforts) + .toEqual(Array.from({ length: 8 }, () => "medium")); + }); + test("startup hydration reads trace-sized usage rows", () => { const trace = oversizedTrace(); for (let index = 0; index < 20; index++) {