Files
rea/src/domain/analysisView/commandObservationView.ts
T
gensokyo-dev 17f581ff75 perf(reverse): add retained GDB and objdump summaries (#5614)
Add opt-in retained GDB and objdump summaries using the shared analysis-view layer. Preserve default complete Evidence, ordered records, provenance and completion facts.

Validate real Bash disassembly, whole-client context costs, CLI publication and cleanup; retain the original measured cohorts and explicit coverage limitations.

Closes #5584.
2026-10-21 01:20:52 +08:00

177 lines
5.4 KiB
TypeScript

import { z } from "zod";
import type { AnalysisError } from "../analysisErrorBase.js";
import {
commandObservationSchema,
gdbCommandResultSchema,
} from "../commandObservation.js";
import { digestSchema } from "../digests.js";
import { providerSchema } from "../evidence.js";
import { analysisInputErrorFromIssues } from "../inputIssueProjection.js";
import { jsonValueSchema } from "../jsonValue.js";
import { err, ok, type Result } from "../result.js";
import type {
AnalysisViewParent,
AnalysisViewRequest,
UnsignedAnalysisView,
} from "./analysisView.js";
import {
boundedViewMessages,
completeWithinViewCoverage,
} from "./analysisViewCoverage.js";
import { analysisViewInputError } from "./analysisViewErrors.js";
import { parseAnalysisViewResult } from "./analysisViewParent.js";
export const commandSummaryContext = {
source_provider: providerSchema.nullable(),
source_analysis_profile_digest: digestSchema.nullable(),
source_parameters: jsonValueSchema,
};
/** Keep every ordered record, including asynchronous and unrecognized records. */
export const gdbCommandSummarySchema = gdbCommandResultSchema
.omit({ console: true, target: true, log: true })
.extend({
available_counts: z.strictObject({
records: z.number().int().nonnegative(),
console_utf16_units: z.number().int().nonnegative(),
target_utf16_units: z.number().int().nonnegative(),
log_utf16_units: z.number().int().nonnegative(),
}),
});
/** Select existing owner facts without parsing a command or its output protocol. */
export const projectCommandObservationView = (
parent: AnalysisViewParent,
view: AnalysisViewRequest,
): Result<UnsignedAnalysisView, AnalysisError> => {
if (view.kind !== "summary")
return err(
analysisViewInputError([
{
path: ["view"],
reason: "invalid_value",
message: "Command observations support summary views.",
},
]),
);
if (
parent.operation !== "gdb_console" &&
parent.operation !== "inspect_with_objdump"
)
return err(
analysisViewInputError([
{
path: ["source", "operation"],
reason: "invalid_value",
message: "Unsupported command-observation operation.",
},
]),
);
const parameters = jsonValueSchema.safeParse(parent.parameters ?? null);
if (!parameters.success)
return err(
analysisInputErrorFromIssues(
"inspect_analysis_view",
parameters.error.issues.map((issue) => ({
...issue,
path: ["source", "parameters", ...issue.path],
})),
{ source: { parameters: parent.parameters } },
{ cause: parameters.error },
),
);
const artifact =
parent.subject === null
? null
: parent.subject === undefined
? (parent.artifact ?? null)
: {
path: parent.subject.local_path,
sha256: parent.subject.digest.sha256,
};
const shared = {
kind: "summary" as const,
view,
parent_evidence_id: parent.evidenceId,
parent_digest: parent.evidenceId.slice(3),
artifact,
source_provider: parent.provider ?? null,
source_analysis_profile_digest: parent.analysisProfileDigest ?? null,
source_parameters: parameters.data,
coverage: completeWithinViewCoverage(1, 1),
limitations: boundedViewMessages(
parent.limitations,
parent.evidenceId,
"limitations",
),
unknowns: boundedViewMessages(
[
"This retained command observation does not establish current target state or global analysis coverage.",
],
parent.evidenceId,
"unknowns",
),
};
if (parent.operation === "gdb_console") {
const parsed = parseAnalysisViewResult(gdbCommandResultSchema, parent);
if (!parsed.ok) return parsed;
const selection = parameters.data;
if (
typeof selection === "object" &&
selection !== null &&
!Array.isArray(selection) &&
typeof selection.command === "string" &&
selection.command !== parsed.value.command
)
return err(
analysisViewInputError([
{
path: ["source", "parameters", "command"],
reason: "invalid_value",
message:
"The captured command conflicts with its source parameters.",
},
]),
);
const { console, target, log, ...records } = parsed.value;
return ok({
...shared,
parent_operation: "gdb_console",
summary: {
...records,
available_counts: {
records: records.records.length,
console_utf16_units: console.length,
target_utf16_units: target.length,
log_utf16_units: log.length,
},
},
});
}
const parsed = parseAnalysisViewResult(commandObservationSchema, parent);
if (!parsed.ok) return parsed;
const report = parsed.value;
if (
artifact !== null &&
report.artifact_sha256_after !== null &&
report.artifact_changed !== null &&
report.artifact_changed !==
(artifact.sha256 !== report.artifact_sha256_after)
)
return err(
analysisViewInputError([
{
path: ["source", "normalized_result", "artifact_changed"],
reason: "invalid_value",
message:
"The recorded artifact-change flag conflicts with the observed digests.",
},
]),
);
return ok({
...shared,
parent_operation: "inspect_with_objdump",
summary: report,
});
};