From 30128a03cff3289479f78df09b3aacf62382d4c2 Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Wed, 14 Oct 2026 08:22:07 +0800 Subject: [PATCH] refactor(domain): centralize relationship coverage interpretation --- src/domain/callPath.ts | 14 ++++------ src/domain/functionCallCoverage.ts | 44 ++++++++---------------------- src/domain/relationshipCoverage.ts | 16 +++++++++++ 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/domain/callPath.ts b/src/domain/callPath.ts index 65524fbc2..3b8bd1cfe 100644 --- a/src/domain/callPath.ts +++ b/src/domain/callPath.ts @@ -1,3 +1,4 @@ +import { relationshipCoverageLimitations } from "./relationshipCoverage.js"; import { callPathInputSchema, callPathResultSchema, @@ -240,15 +241,12 @@ const inspectSearch = ({ const coverage = snapshot.evidence.relationship_coverage; for (const limitation of snapshot.limitations) limitations.push(limitation); - if (coverage?.status === "partial") - for (const limitation of coverage.limitations) + if (coverage !== null) { + for (const limitation of relationshipCoverageLimitations(coverage)) limitations.push(limitation); - else if (coverage?.status === "unknown") - limitations.push(coverage.reason); - for (const diagnostic of coverage !== null && "diagnostics" in coverage - ? coverage.diagnostics - : []) - limitations.push(diagnostic); + for (const diagnostic of coverage.diagnostics ?? []) + limitations.push(diagnostic); + } // The requested goal is a terminal for this search. Its outgoing edges // cannot add a path to the goal, so its dossier limits are contextual // but do not make the searched start-to-goal closure incomplete. diff --git a/src/domain/functionCallCoverage.ts b/src/domain/functionCallCoverage.ts index ce3798c4f..06fc06fe5 100644 --- a/src/domain/functionCallCoverage.ts +++ b/src/domain/functionCallCoverage.ts @@ -1,4 +1,7 @@ -import type { RelationshipCoverage } from "./relationshipCoverage.js"; +import { + relationshipCoverageLimitations, + type RelationshipCoverage, +} from "./relationshipCoverage.js"; import type { FunctionDossier } from "./hopperValues.js"; import { uniqueSorted } from "./canonicalOrdering.js"; @@ -15,11 +18,7 @@ export const combineFunctionRelationshipCoverage = ( { direction: "callees" as const, coverage: callees }, ]; const diagnostics = uniqueSorted( - reads.flatMap(({ coverage }) => - coverage !== undefined && "diagnostics" in coverage - ? coverage.diagnostics - : [], - ), + reads.flatMap(({ coverage }) => coverage?.diagnostics ?? []), ); const details = diagnostics.length > 0 ? { diagnostics } : {}; const callersLimited = callers?.status !== "complete"; @@ -35,15 +34,9 @@ export const combineFunctionRelationshipCoverage = ( const reasons = reads.flatMap(({ direction, coverage }) => { const label = direction === "callers" ? callerCoveragePrefix : calleeCoveragePrefix; - const limitations = - coverage === undefined - ? ["Provider did not report relationship coverage."] - : coverage.status === "unknown" - ? [coverage.reason] - : coverage.status === "partial" - ? coverage.limitations - : []; - return limitations.map((reason) => `${label}${reason}`); + return relationshipCoverageLimitations(coverage).map( + (reason) => `${label}${reason}`, + ); }); if ( reads.some( @@ -90,24 +83,11 @@ export const functionCallCoverageLimitations = ( coverage: RelationshipCoverage | null, dossier: Pick, ): string[] => { - const limitations = - coverage === null - ? ["Provider did not report relationship coverage."] - : coverage.status === "unknown" - ? [ - coverage.reason, - ...("diagnostics" in coverage ? coverage.diagnostics : []), - ] - : coverage.status === "partial" - ? [ - ...coverage.limitations, - ...("diagnostics" in coverage ? coverage.diagnostics : []), - ] - : []; - limitations.push( + return uniqueSorted([ + ...relationshipCoverageLimitations(coverage), + ...(coverage?.status === "complete" ? [] : (coverage?.diagnostics ?? [])), ...(dossier.unresolved_calls ?? []).map( ({ address, reason }) => `Unresolved call at ${address}: ${reason}`, ), - ); - return uniqueSorted(limitations); + ]); }; diff --git a/src/domain/relationshipCoverage.ts b/src/domain/relationshipCoverage.ts index 4dd4e0c40..f241206a0 100644 --- a/src/domain/relationshipCoverage.ts +++ b/src/domain/relationshipCoverage.ts @@ -33,3 +33,19 @@ export const relationshipCoverageSchema = z.discriminatedUnion("status", [ ]); export type RelationshipCoverage = z.infer; + +/** Reasons the observed relationship inventory cannot establish completeness. */ +export const relationshipCoverageLimitations = ( + coverage: RelationshipCoverage | null | undefined, +): readonly string[] => { + switch (coverage?.status) { + case undefined: + return ["Provider did not report relationship coverage."]; + case "complete": + return []; + case "partial": + return coverage.limitations; + case "unknown": + return [coverage.reason]; + } +};