Files
reverse-engineering-anything/src/application/native/NativeMatchingSources.ts
T
Kaoru0822andClaude Opus 5.5 cc2656be8d perf(native): charge function matching for the copies it makes (#7108)
* perf(native): charge matching for what it copies, not borrowed retained inventories

Native function matching deep-walked every retained list_procedures record
at about 2.8 KB per Ghidra-shaped row, although the session ledger lends
those immutable records without a copy, and charged each inventory's one
Evidence ID once per function. The report and Evidence copies of every
emitted member were not charged at all.

Charge each inventory row before parsing for the member it becomes,
including its report and Evidence copies, charge the shared inventory ID
once, and skip the walk only for borrowed immutable inventories and closure
records that matching never parses. Inline Evidence, bundle records and
selected observations keep their existing charges. Retained references now
fit about 22,000 rows per side instead of 10,000, and an oversized side is
refused before its rows are parsed.

Refs #6406

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(native): charge the envelope of borrowed matching inputs

Borrowed inventories skipped admission entirely, but matching copies their
limitations into the report and Evidence and digests their profile, so a
retained inventory with few rows and large limitations escaped the
allowance. Charge every envelope field and leave only the result payloads,
which row charging covers or matching never parses, uncharged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 05:21:09 -07:00

173 lines
5.9 KiB
TypeScript

import type { MatchNativeFunctionsInput } from "../../contracts/native/functionMatchingContracts.js";
import { digestCanonicalValue } from "../../domain/canonicalDigest.js";
import { AnalysisInputError } from "../../domain/analysisErrorCore.js";
import { isImmutableEvidence, type Evidence } from "../../domain/evidence.js";
import { readEvidence } from "../../domain/evidenceValidation.js";
import { retainedEvidenceReferenceSchema } from "../../domain/evidenceReference.js";
import {
resolveEvidenceInput,
type EvidenceLookup,
} from "../EvidenceInputResolver.js";
import type { NativeMatchingAdmission } from "./NativeMatchingAdmission.js";
import { nativeMatchingInputError } from "./NativeMatchingInputError.js";
const INVENTORY_OPERATIONS = ["list_procedures"] as const;
const OBSERVATION_OPERATIONS = [
"list_names",
"procedure_info",
"read_bytes",
"analyze_function",
] as const;
/** Authenticate selected roles and their closure without interpreting dependencies as observations. */
export const resolveNativeMatchingSources = async (
input: MatchNativeFunctionsInput,
admission: NativeMatchingAdmission,
lookup: EvidenceLookup | undefined,
): Promise<{
readonly left: Evidence;
readonly right: Evidence;
readonly leftObservations: readonly Evidence[];
readonly rightObservations: readonly Evidence[];
readonly directLinks: readonly string[];
readonly sources: readonly Evidence[];
}> => {
const sources = new Map<string, Evidence>();
/**
* Charge only what matching copies. A retained immutable record is borrowed
* without cloning. When matching never parses its result, or charges the
* representation it derives from it (inventory rows), only its envelope is
* charged; walking the result would charge resident memory as if matching
* had allocated it.
*/
const resolve = async (
input: unknown,
path?: readonly (string | number)[],
borrowable = false,
): Promise<Evidence> => {
const reference = retainedEvidenceReferenceSchema.safeParse(input);
let raw = input,
borrowed: Evidence | undefined;
if (reference.success) {
const found = resolveEvidenceInput(reference.data, lookup);
if (!found.ok) throw found.error;
raw = found.value;
if (borrowable && isImmutableEvidence(found.value))
borrowed = found.value;
}
if (borrowed !== undefined) await admission.admitBorrowed(borrowed);
else await admission.admit(raw);
const checked = readEvidence(raw);
if (!checked.ok)
throw path !== undefined && !reference.success
? nativeMatchingInputError(
input,
path,
admission.operation,
checked.error,
)
: checked.error;
const evidence = checked.value;
const cached = sources.get(evidence.evidence_id);
if (cached !== undefined) return cached;
sources.set(evidence.evidence_id, evidence);
return evidence;
};
const select = async (
raw: unknown,
path: readonly (string | number)[],
operations: readonly string[],
borrowable = false,
): Promise<Evidence> => {
const evidence = await resolve(raw, path, borrowable);
if (
evidence.predicate_type !== "rea.analysis" ||
!operations.includes(evidence.operation) ||
evidence.subject === null
) {
const message = `Expected artifact-bound rea.analysis ${operations.join(" or ")} Evidence, received ${evidence.predicate_type} ${evidence.operation}`;
throw new AnalysisInputError(
admission.operation,
{ userMessage: message },
[{ path, reason: "invalid_value", message }],
);
}
return evidence;
};
// readFunctionInventory charges each inventory row before parsing it.
const left = await select(input.left, ["left"], INVENTORY_OPERATIONS, true);
const right = await select(
input.right,
["right"],
INVENTORY_OPERATIONS,
true,
);
const observations = async (
inputs: readonly unknown[],
field: "left_observations" | "right_observations",
inventory: Evidence,
): Promise<Evidence[]> => {
const result: Evidence[] = [];
const seen = new Set<string>();
for (const [index, input] of inputs.entries()) {
const record = await select(
input,
[field, index],
OBSERVATION_OPERATIONS,
);
if (
digestCanonicalValue(record.subject) !==
digestCanonicalValue(inventory.subject) ||
digestCanonicalValue(record.provider) !==
digestCanonicalValue(inventory.provider) ||
digestCanonicalValue(record.analysis_profile) !==
digestCanonicalValue(inventory.analysis_profile) ||
(record.parameters.document ?? null) !==
(inventory.parameters.document ?? null)
) {
const message =
"Select an observation from the inventory's exact target, provider, analysis profile and document context.";
throw new AnalysisInputError(
admission.operation,
{ userMessage: message },
[{ path: [field, index], reason: "invalid_value", message }],
);
}
if (!seen.has(record.evidence_id)) {
seen.add(record.evidence_id);
result.push(record);
}
}
return result;
};
const leftObservations = await observations(
input.left_observations,
"left_observations",
left,
);
const rightObservations = await observations(
input.right_observations,
"right_observations",
right,
);
const directLinks = [...sources.keys()].sort();
for (const source of sources.values())
for (const id of source.evidence_links)
if (!sources.has(id))
// Closure records are only returned for retention, never parsed.
await resolve(
{ kind: "retained-evidence", evidence_id: id },
undefined,
true,
);
return {
left,
right,
leftObservations,
rightObservations,
directLinks,
sources: [...sources.values()],
};
};