Files
reverse-engineering-anything/src/application/FunctionAnalysisEvidence.ts
T
gensokyo-dev 5508b2affd fix(analysis): retain source evidence through directory exports (#7250)
Retain authenticated provider source records independently of snapshot replay eligibility and return them explicitly to plain application callers, including late cancellation. CLI/MCP commit source records before delivering links; function dossiers share the canonical Evidence constructor. Keep directory replies compact and preserve successful retry verification.

Real Ghidra CLI/MCP investigations verify 652-function ls, historical report provenance, cross-session resume, unchanged source/project content and complete offline Evidence. Final full 14,338-function libcrypto comparison matches all metadata/pseudocode facts and independent fresh-import observations: 14,194 written, 143 external, one recorded deadline; 494.03 s, 445.63 CPU s, 1.584 GiB sampled family peak under 2-CPU/8-GiB guards, with no OOM or cleanup failure.

144 focused tests and static/docs/site checks pass; latest-main integration passes 289 cases plus typecheck/lint and actual CLI snapshot source retrieval. Final CI source/static/build/docs/quality/package checks pass. Four ADB shard failures also occur in main CI 40349559391; cancelled coverage remains unverified and author declarations stay unchecked under the user's explicit bypass authorization. No human-review attestation is made.
2026-10-26 23:56:03 +08:00

75 lines
2.5 KiB
TypeScript

import { parseAnalysisInput } from "./AnalysisInput.js";
import type {
AnalysisOperationPort,
ExecutionOptions,
} from "./AnalysisProvider.js";
import { nativeProcedureInputSchema } from "../domain/native/nativeProcedureInput.js";
import type { BinaryTarget } from "../domain/binaryTargetTypes.js";
import { createAnalysisExecutionEvidence } from "../domain/analysisObservation.js";
import { parseFunctionDossier } from "../domain/hopperValues.js";
import type { JsonValue } from "../domain/jsonValue.js";
import { completeProviderEvidence } from "./ProviderOperationExecution.js";
import type { Evidence } from "../domain/evidence.js";
import { EvidenceLedger } from "./investigation/EvidenceLedger.js";
import {
recordEvidenceSources,
withEvidenceSources,
type AnalysisResultWithSources,
} from "./investigation/recordEvidenceSources.js";
/**
* Preserve the provider's observations when presenting a validated function
* dossier. Parameters are the provider input only: adapters separate delivery
* options such as MCP detail before calling.
*/
export const executeFunctionAnalysisEvidence = async (
analysis: AnalysisOperationPort,
parameters: Readonly<Record<string, JsonValue>>,
target: BinaryTarget | undefined,
options?: ExecutionOptions,
): Promise<AnalysisResultWithSources<Evidence>> => {
const input = parseAnalysisInput(
"analyze_function",
parameters,
nativeProcedureInputSchema,
options?.signal,
);
if (!input.ok) return input;
const arguments_ = input.value;
const execution = await analysis.execute(
"analyze_function",
arguments_,
options,
);
if (!execution.ok) return execution;
const sourceLedger = new EvidenceLedger();
const recorded = recordEvidenceSources(
(source) => sourceLedger.record(source),
execution.value.sourceEvidence ?? [],
);
const sources = sourceLedger.recordsForAnalysis();
if (!recorded.ok) return withEvidenceSources(recorded, sources);
const dossier = parseFunctionDossier(execution.value.result);
if (!dossier.ok) return withEvidenceSources(dossier, sources);
const observation = execution.value;
return withEvidenceSources(
completeProviderEvidence(
createAnalysisExecutionEvidence(
"analyze_function",
arguments_,
{
...observation,
sourceEvidence: sources,
result: dossier.value,
...(observation.subject === undefined && target !== undefined
? { subject: target }
: {}),
},
"observed",
),
options?.signal,
),
sources,
);
};