Files
reverse-engineering-anything/src/application/AnalysisContextQueries.ts
T
morluto 676d29f9ee fix(native): preserve qualified feature trace observations
Use one containing-procedure parser beside its declared schema for
navigation, address facets, and feature trace references. Keep the trace
cache and reference type bound to parsed facts, returning typed malformed
output before SDK projection instead of passing unchecked JSON onward.

Retain same-address search alternatives such as Kuna's distinct string
encodings. References identify target addresses, so observe and emit each
target once while retaining duplicate rows from the provider observation.
Remove address-only match collapse and redundant residual deduplication.
Document these semantics.

Validation: regression-first runs reproduced four malformed-resolution
failures and three alternative/reference-replay failures. Focused MCP and
consumer controls passed after repair. Real native engines were not run.
2026-10-24 09:17:10 +08:00

186 lines
6.1 KiB
TypeScript

import type {
AnalysisExecution,
AnalysisOperation,
AnalysisOperationPort,
} from "./AnalysisProvider.js";
import type { AnalysisError } from "../domain/analysisErrorBase.js";
import { AnalysisOutputError } from "../domain/analysisErrorCore.js";
import type { JsonValue } from "../domain/jsonValue.js";
import {
analysisBookmarkSchema,
parseContainingProcedureResolution,
} from "../domain/hopperValues.js";
import { resolveAnalysisDocument } from "./AnalysisDocument.js";
import { err, ok, type Result } from "../domain/result.js";
type Facet =
| { readonly state: "available"; readonly value: JsonValue }
| {
readonly state: "unavailable";
readonly reason: string;
readonly remediation: string;
};
const parameters = (
document: string | undefined,
address?: string,
): Readonly<Record<string, JsonValue>> => ({
...(document === undefined ? {} : { document }),
...(address === undefined ? {} : { address }),
});
const executionOptions = (
signal: AbortSignal | undefined,
): { readonly signal?: AbortSignal } =>
signal === undefined ? {} : { signal };
/** Compose the provider's volatile selection state into one coherent query. */
export const getNavigationContext = async (
analysis: AnalysisOperationPort,
input: { readonly document?: string | undefined },
signal?: AbortSignal,
): Promise<Result<JsonValue, AnalysisError>> => {
const document =
input.document ??
(await analysis.execute("current_document", {}, executionOptions(signal)));
if (typeof document !== "string" && !document.ok) return document;
const documentName =
typeof document === "string" ? document : document.value.result;
if (typeof documentName !== "string")
return err(
new AnalysisOutputError(
"current_document",
"expected a document identity string",
),
);
const documentArgs = parameters(documentName);
const address = await analysis.execute(
"current_address",
documentArgs,
executionOptions(signal),
);
if (!address.ok) return address;
if (typeof address.value.result !== "string")
return err(
new AnalysisOutputError("current_address", "expected an address string"),
);
const procedure = await analysis.execute(
"resolve_containing_procedure",
parameters(documentName, address.value.result),
executionOptions(signal),
);
if (!procedure.ok) return procedure;
const resolution = parseContainingProcedureResolution(procedure.value.result);
if (!resolution.ok) return resolution;
return ok({
document: documentName,
address: address.value.result,
procedure: resolution.value.found ? resolution.value.procedure.name : null,
});
};
/** Inspect bounded provider-neutral facets at one explicit reproducible address. */
export const inspectAddressContext = async (
analysis: AnalysisOperationPort,
input: { readonly address: string; readonly document?: string | undefined },
signal?: AbortSignal,
): Promise<Result<JsonValue, AnalysisError>> => {
const document = await resolveAnalysisDocument(
analysis,
input.document,
signal,
);
if (!document.ok) return document;
const args = parameters(document.value, input.address);
const operations = [
"address_name",
"resolve_containing_procedure",
"comment",
"inline_comment",
"list_bookmarks",
] as const satisfies readonly AnalysisOperation[];
const results = await Promise.all(
operations.map((operation) =>
analysis.execute(
operation,
operation === "list_bookmarks" ? parameters(document.value) : args,
executionOptions(signal),
),
),
);
for (const result of results) {
if (!result.ok && isRequestLevelFailure(result.error)) return result;
}
const name = facet(results[0], operations[0]);
const procedureResult = results[1];
const resolution = procedureResult?.ok
? parseContainingProcedureResolution(procedureResult.value.result)
: procedureResult;
const procedure: Facet = resolution?.ok
? { state: "available", value: resolution.value }
: unavailableFacet(resolution?.error, operations[1]);
const comment = facet(results[2], operations[2]);
const inlineComment = facet(results[3], operations[3]);
const bookmarks = facet(results[4], operations[4]);
return ok({
address: input.address,
document: document.value,
name,
procedure,
comment,
inline_comment: inlineComment,
bookmarks:
bookmarks.state === "available"
? matchingBookmarks(
bookmarks.value,
resolution?.ok ? resolution.value.query_address : input.address,
)
: bookmarks,
});
};
const facet = (
result: Result<AnalysisExecution, AnalysisError> | undefined,
operation: AnalysisOperation,
): Facet =>
result?.ok === true
? { state: "available", value: result.value.result }
: unavailableFacet(result?.error, operation);
const unavailableFacet = (
error: AnalysisError | undefined,
operation: AnalysisOperation,
): Facet => ({
state: "unavailable",
reason: error?.message ?? `${operation} returned no result`,
remediation: `Call ${operation} directly to inspect provider availability and diagnostics.`,
});
const isRequestLevelFailure = (error: AnalysisError): boolean =>
error._tag === "AnalysisCancelledError" ||
error._tag === "AnalysisTimeoutError" ||
error._tag === "NoBinaryOpenError";
const matchingBookmarks = (value: JsonValue, address: string): Facet => {
if (!Array.isArray(value))
return {
state: "unavailable",
reason: "list_bookmarks returned malformed output; expected an array.",
remediation:
"Retry list_bookmarks directly and report the provider output shape if it remains malformed.",
};
const parsed = analysisBookmarkSchema.array().safeParse(value);
if (!parsed.success)
return {
state: "unavailable",
reason:
"list_bookmarks returned malformed entries; expected an address string and a string or null name.",
remediation:
"Retry list_bookmarks directly and report the provider output shape if it remains malformed.",
};
return {
state: "available",
value: parsed.data.filter((bookmark) => bookmark.address === address),
};
};