Files
reverse-engineering-anything/src/domain/functionCallCoverage.ts
T
morlutoandCursor Agent 31278c7b5a fix!: qualify call paths by provider discovery (#8443)
* fix!: qualify call paths by provider discovery

* fix: preserve compact call coverage schema guidance

* fix: preserve call discovery reasons in path evidence

* fix(evidence): retain discovery limits in call verification

* test: declare discovery in reconstruction controls

* fix: preserve call discovery across facet limits

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-11-08 01:21:29 +08:00

146 lines
5.1 KiB
TypeScript

import {
relationshipCoverageLimitations,
type RelationshipCoverage,
type RelationshipDiscoveryStatus,
} from "./relationshipCoverage.js";
import type { FunctionDossier } from "./native/functionDossier.js";
import { uniqueSorted } from "./canonicalOrdering.js";
const callerCoveragePrefix = "Callers: ";
const calleeCoveragePrefix = "Callees: ";
/** Combine caller and callee read outcomes without losing either explanation. */
export const combineFunctionRelationshipCoverage = (
callers: RelationshipCoverage | undefined,
callees: RelationshipCoverage | undefined,
): RelationshipCoverage => {
const reads = [
{ direction: "callers" as const, coverage: callers },
{ direction: "callees" as const, coverage: callees },
];
const diagnostics = uniqueSorted(
reads.flatMap(({ coverage }) => coverage?.diagnostics ?? []),
);
const discovery = {
...(callers?.discovery?.callers === undefined
? {}
: { callers: callers.discovery.callers }),
...(callees?.discovery?.callees === undefined
? {}
: { callees: callees.discovery.callees }),
};
const details = {
...(diagnostics.length > 0 ? { diagnostics } : {}),
...(Object.keys(discovery).length === 0 ? {} : { discovery }),
};
const callersLimited = callers?.status !== "complete";
const calleesLimited = callees?.status !== "complete";
const limited_directions: Extract<
RelationshipCoverage,
{ status: "partial" }
>["limited_directions"] = callersLimited
? calleesLimited
? ["callers", "callees"]
: ["callers"]
: ["callees"];
const reasons = reads.flatMap(({ direction, coverage }) => {
const label =
direction === "callers" ? callerCoveragePrefix : calleeCoveragePrefix;
return relationshipCoverageLimitations(coverage).map(
(reason) => `${label}${reason}`,
);
});
if (
reads.some(
({ coverage }) => coverage === undefined || coverage.status === "unknown",
)
)
return {
status: "unknown",
reason: uniqueSorted(reasons).join(" "),
limited_directions,
...details,
};
if (reasons.length > 0)
return {
status: "partial",
limitations: uniqueSorted(reasons),
limited_directions,
...details,
};
return { status: "complete", ...details };
};
/**
* Forward searches depend on callee coverage. Preserve the historical
* unknown-reason encoding when reading observations without explicit directions.
*/
export const isCallerOnlyIncompleteCoverage = (
coverage: RelationshipCoverage,
): boolean => {
if (coverage.status === "complete") return false;
if (coverage.limited_directions !== undefined)
return !coverage.limited_directions.some(
(direction) => direction === "callees",
);
return (
coverage.status === "unknown" &&
coverage.reason.startsWith(callerCoveragePrefix) &&
!coverage.reason.includes(calleeCoveragePrefix)
);
};
export interface FunctionCallCoverageAssessment {
/** Reasons the observed call sets cannot establish equality. */
readonly blockers: readonly string[];
/** Explicit unresolved outgoing calls, kept separate for forward searches. */
readonly unresolvedCallCaveats: readonly string[];
/** Provider caveats that remain relevant even with complete coverage. */
readonly diagnostics: readonly string[];
/** Discovery limits do not invalidate comparisons of the observed sets. */
readonly discoveryLimitations: readonly string[];
/** Whether all requested call discovery directions are established. */
readonly discoveryStatus: RelationshipDiscoveryStatus;
}
/** Keep observed-set blockers separate from descriptive provider caveats. */
export const assessFunctionCallCoverage = (
coverage: RelationshipCoverage | null,
dossier: Pick<FunctionDossier, "unresolved_calls">,
): FunctionCallCoverageAssessment => {
const unresolvedCallCaveats = uniqueSorted(
(dossier.unresolved_calls ?? []).map(
({ address, reason }) => `Unresolved call at ${address}: ${reason}`,
),
);
const missingDiscovery: string[] = [];
const discoveryLimitations: string[] = [];
let discoveryStatus: RelationshipDiscoveryStatus = "complete";
for (const direction of ["callers", "callees"] as const) {
const discovery = coverage?.discovery?.[direction];
if (discovery?.status === "partial") discoveryStatus = "partial";
else if (discovery?.status !== "complete" && discoveryStatus !== "partial")
discoveryStatus = "unknown";
if (discovery?.status === "complete") continue;
if (discovery?.reason === undefined) missingDiscovery.push(direction);
else
discoveryLimitations.push(
`Static direct-call discovery for ${direction} is ${discovery.status}: ${discovery.reason}`,
);
}
if (missingDiscovery.length > 0)
discoveryLimitations.push(
`Static direct-call discovery is not established for ${missingDiscovery.join(" and ")}.`,
);
return {
blockers: uniqueSorted([
...relationshipCoverageLimitations(coverage),
...unresolvedCallCaveats,
]),
unresolvedCallCaveats,
diagnostics: uniqueSorted(coverage?.diagnostics ?? []),
discoveryLimitations,
discoveryStatus,
};
};