Files
reverse-engineering-anything/src/application/ProcessCli.ts
T

82 lines
2.9 KiB
TypeScript

import { readFile } from "node:fs/promises";
import { parseConfig } from "../config.js";
import { createEvidence, parseEvidence } from "../domain/evidence.js";
import { jsonValueSchema } from "../domain/jsonValue.js";
import {
compareProcessCaptures,
LEGACY_PROCESS_CAPTURE_MESSAGE,
parseProcessScenario,
parseProcessCapture,
} from "../domain/processCapture.js";
import { captureProcessScenario } from "./ProcessHarness.js";
import {
PROCESS_PROVIDER,
createProcessCaptureEvidence,
} from "./ProcessEvidence.js";
const MAX_INPUT_BYTES = 64 * 1024 * 1024;
/** Capture one JSON scenario through the same policy and evidence contract as MCP. */
export const captureProcessScenarioFile = async (path: string) => {
const scenario = parseProcessScenario(await readJson(path));
const config = parseConfig(process.env);
if (!config.ok) throw config.error;
const captured = await captureProcessScenario(
scenario,
config.value.processExecutionPolicy,
);
if (!captured.ok) throw captured.error;
return createProcessCaptureEvidence(scenario, captured.value);
};
/** Compare two capture Evidence files and emit derived comparison Evidence. */
export const compareProcessEvidenceFiles = async (
leftPath: string,
rightPath: string,
) => {
const left = parseCaptureEvidence(await readJson(leftPath));
const right = parseCaptureEvidence(await readJson(rightPath));
const comparison = compareProcessCaptures(left.capture, right.capture);
return createEvidence(undefined, PROCESS_PROVIDER, {
predicateType: "rea.process-comparison/v3",
operation: "compare_process_captures",
parameters: {
left_evidence_id: left.id,
right_evidence_id: right.id,
left_normalization: left.capture.normalization,
right_normalization: right.capture.normalization,
},
result: jsonValueSchema.parse(comparison),
confidence: "derived",
authority: "analyst-inference",
limitations: comparison.limitations,
evidenceLinks: [left.id, right.id],
});
};
const parseCaptureEvidence = (input: unknown) => {
const evidence = parseEvidence(input);
if (
evidence.operation !== "capture_process_scenario" ||
evidence.predicate_type !== "rea.process-capture/v4" ||
evidence.provider.id !== PROCESS_PROVIDER.id ||
evidence.provider.version !== PROCESS_PROVIDER.version
) {
if (evidence.predicate_type === "rea.process-capture/v3")
throw new TypeError(LEGACY_PROCESS_CAPTURE_MESSAGE);
throw new TypeError("Expected REA Process Capture v4 Evidence");
}
return {
id: evidence.evidence_id,
capture: parseProcessCapture(evidence.normalized_result),
};
};
const readJson = async (path: string): Promise<unknown> => {
const bytes = await readFile(path);
if (bytes.length > MAX_INPUT_BYTES)
throw new TypeError("Process JSON input exceeds byte limit");
return JSON.parse(bytes.toString("utf8")) as unknown;
};