Files
reverse-engineering-anything/tests/boundary/mcp/analysisViewMcp.test.ts
T
morluto b138f52e12 refactor: prune internal seams and preserve configuration ownership (#10430)
* refactor: prune internal seams and preserve configuration ownership

* fix(setup): keep YAML aliases and inherited registration settings on refresh

- Reuse an unchanged YAML collection only while every alias in it still
  resolves after the edit; otherwise rebuild it so the alias becomes its
  value. A sibling anchor replaced or moved in the same refresh no longer
  leaves an unresolved alias in Hermes or Goose output.
- Keep a connection selector whose existing value already chooses stdio
  (for example an inherited Hermes transport: stdio) instead of superseding
  it; remote selectors are still replaced. Explicit stdio selectors are
  therefore no longer rewritten (Kimi expectation updated).
- When the whole Hermes registration is inherited through a merge,
  override it with that merge and write only the changed fields.

* fix(setup): edit registration fields whose YAML key is an alias

A key written as an alias to a string scalar (for example *field with
field: &field env) was treated as a source-only key, so any change to
its value was refused in Hermes and Goose. Resolve such keys to their
string, keep the aliased spelling while its anchor survives the edit,
and write the plain key when the same edit rebuilds the anchor.

* test(process): bound cleanup-boundary waits and always release gates

Both cancellation tests awaited a bare started promise and released
their gates only on success, so a missed boundary waited for the outer
deadline and could leave cleanup parked. Use awaitAcknowledgement and
release and join the cleanup in finally.

* fix(setup): repair only aliases an edit leaves unresolved

Replace the pre-edit alias survival guess, which expanded aliases to
sibling anchors that survive unchanged, with an exact repair: record
what each alias in the replaced value resolves to, write the edit, then
replace only aliases left without a preceding anchor by that value.

- Keep an aliased key's source position, so its anchor stays ahead of
  later aliases.
- Treat an aliased key as its string only when no other key in the map
  resolves to the same string; an ambiguous one stays guarded.
- Override an inherited Hermes registration only when the requested
  entry keeps every inherited field, so an explicit replacement can drop
  remote selectors.

* fix(setup): repair aliases whose binding an edit changes, keeping comments

An alias whose own anchor was removed could resolve to an earlier anchor
with the same name and silently change value. Record the node each alias
resolved to and repair any alias that no longer resolves to that node.
Carry the alias's comments and spacing onto the repaired value.

* test(setup): split the Hermes anchor and merge refresh cases

* fix(setup): refuse removing an overridden key its merge would restore

The merge-retention check skipped keys the mapping also overrides, so
dropping such a key (for example a remote url during an explicit stdio
replacement) let the retained merge restore it. Check removal before
skipping overridden keys, so the edit is refused with the existing
message instead of producing a registration that cannot be applied.
2026-11-14 04:08:37 -05:00

2213 lines
74 KiB
TypeScript

import { createMcpSchemaValidation } from "../../fixtures/mcpSchemaValidation.js";
import { advertisedMcpToolSchemas } from "../../fixtures/advertisedMcpTool.js";
import { API_SURFACE_EXAMPLE } from "../../../src/contracts/analysisViewApiSurfaceExample.js";
import { ENVIRONMENT_MANIFEST_EXAMPLE } from "../../../src/contracts/analysisViewEnvironmentManifestExample.js";
import { createHash } from "node:crypto";
import { readFile, writeFile } from "node:fs/promises";
import { WebNetworkCaptureService } from "../../../src/application/WebNetworkCaptureService.js";
import { decodeHarCapture } from "../../../src/browser/history/HarCapture.js";
import { join } from "node:path";
import {
apiSurfaceHar,
environmentManifestHar,
} from "../../fixtures/historicalHar.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { parseMcpToolError } from "../../fixtures/mcpToolError.js";
import { STDIO_DEFAULT_MAX_BUFFER_SIZE } from "@modelcontextprotocol/server";
import { afterAll, expect, it, onTestFinished } from "vitest";
import { z } from "zod";
import { BinaryLayoutService } from "../../../src/application/binaryDiagnostics/BinaryLayoutService.js";
import { toolContract } from "../../../src/contracts/toolContracts.js";
import { createEvidence, parseEvidence } from "../../../src/domain/evidence.js";
import { createAnalysisProfile } from "../../../src/domain/analysisProfile.js";
import {
jsonObjectSchema,
type JsonValue,
} from "../../../src/domain/jsonValue.js";
import { functionDossierSchema } from "../../../src/domain/native/functionDossier.js";
import { inspectMachoSchema } from "../../../src/domain/native/nativeInspection.js";
import { ghidraFunctionDossier } from "../../../src/domain/ghidraValues.fixture.js";
import { ok } from "../../../src/domain/result.js";
import {
createJavaScriptApplicationGraph,
createJavaScriptApplicationNode,
} from "../../../src/domain/javascript/javascriptApplicationGraph.js";
import { connectGhidraMcp } from "./ghidraMcpHarness.js";
import {
analysisViewJavaScriptEvidence,
analysisViewJavaScriptAnalysisWithSource,
analysisViewBindJavaScriptGraphs,
analysisViewLayoutEvidence,
analysisViewLayoutFixture,
analysisViewCaptureFixture,
analysisViewCaptureEvidence,
analysisViewObjectDenseCapture,
analysisViewNativeEvidence,
environmentManifestCaptureFixture,
environmentStateCaptureFixture,
timedCaptureEvidence,
} from "../../fixtures/analysisView.js";
import { BOOK_ROWS } from "../../fixtures/environmentStateWrites.js";
import { createTestBinarySession } from "../../fixtures/binarySession.js";
import { createApplicationMcpHarness } from "../../fixtures/applicationMcpHarness.js";
import { createLinkedIl2cppMetadataFixture } from "../../fixtures/il2cpp/metadata.js";
import {
createIl2cppBinaryFixture,
FIXTURE_RETURN_TYPE_NAME,
} from "../../fixtures/il2cpp/binary.js";
import {
analysisViewResultSchema,
il2cppMetadataSummaryViewResultSchema,
} from "../../../src/domain/analysisView/analysisViewResult.js";
import {
BINARY_LAYOUT_TEST_PROVIDER,
binaryLayoutFixture,
} from "../../fixtures/binaryDiagnostics/layout.js";
import { wasmArtifactFixture } from "../../fixtures/wasm/artifact.js";
import { evmInterfaceFixture } from "../../fixtures/evm/interface.js";
import type { RelationshipCoverage } from "../../../src/domain/relationshipCoverage.js";
const schemaValidation = createMcpSchemaValidation();
afterAll(() => schemaValidation.clear());
const connect = async (
binaryLayout?: BinaryLayoutService,
webNetworkCapture?: WebNetworkCaptureService,
maximumInputElements?: number,
) => {
const session = createTestBinarySession(() => {
throw new Error("selected views must not start a deep provider");
});
return createApplicationMcpHarness({
session,
clientIdentity: { name: "analysis-view-mcp", version: "1" },
schemaValidator: schemaValidation,
serverOptions: {
// These schema conformance cases exercise full nested constraints.
environment: {
...process.env,
REA_MCP_INPUT_SCHEMA_PROFILE: "full",
REA_MCP_MAX_INPUT_ELEMENTS:
maximumInputElements === undefined
? process.env.REA_MCP_MAX_INPUT_ELEMENTS
: String(maximumInputElements),
},
...(binaryLayout === undefined ? {} : { binaryLayout }),
...(webNetworkCapture === undefined ? {} : { webNetworkCapture }),
},
});
};
it("selects every IL2CPP native type reference by rendered name with stable row identity", async () => {
const { client } = await connect();
const root = await createTestTempDirectory("rea-il2cpp-native-names-");
const path = join(root, "global-metadata.dat");
const binaryPath = join(root, "GameAssembly.dylib");
await writeFile(binaryPath, createIl2cppBinaryFixture());
const inspect = async (version: 27 | 31) => {
await writeFile(path, createLinkedIl2cppMetadataFixture({ version }).bytes);
const inspected = await client.callTool({
name: "inspect_il2cpp_metadata",
arguments: { path, binary_path: binaryPath },
});
expect(inspected.isError, JSON.stringify(inspected)).not.toBe(true);
const summary = il2cppMetadataSummaryViewResultSchema.parse(
parseEvidence(inspected.structuredContent).normalized_result,
);
return {
kind: "retained-evidence",
evidence_id: summary.parent_evidence_id,
};
};
let source = await inspect(31);
const select = async (
collection: "return_types" | "field_types" | "parameter_types",
filters: Record<string, unknown>,
) => {
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source,
view: { kind: "il2cpp-metadata", collection, ...filters },
},
});
expect(response.isError, JSON.stringify(response)).not.toBe(true);
const page = analysisViewResultSchema.parse(
parseEvidence(response.structuredContent).normalized_result,
);
if (page.kind !== "il2cpp-metadata")
throw new Error("Expected IL2CPP page");
return page;
};
for (const [collection, count] of [
["return_types", 5],
["field_types", 2],
["parameter_types", 1],
] as const) {
const names = [FIXTURE_RETURN_TYPE_NAME];
const expected = Array.from({ length: count }, (_, index) => ({
index,
type: 0,
name: FIXTURE_RETURN_TYPE_NAME,
}));
const unfiltered = await select(collection, {});
expect(unfiltered.items).toEqual(expected);
const all = await select(collection, { names });
expect(all.items).toEqual(expected);
expect(all.coverage).toMatchObject({ total: count, exhausted: true });
const selected = await select(collection, {
names,
indices: [count - 1, 0, count - 1],
offset: 1,
limit: 1,
fields: ["type"],
});
expect(selected.items).toEqual(
count === 1 ? [] : [{ index: count - 1, type: 0 }],
);
expect(selected.coverage).toMatchObject({
total: Math.min(count, 2),
exhausted: true,
});
for (const missing of [[], ["absent"], ["system.Größe<int>[]"]]) {
const empty = await select(collection, { names: missing });
expect(empty.items).toEqual([]);
expect(empty.coverage).toMatchObject({ total: 0, exhausted: true });
}
}
const owned = await select("parameter_types", {
names: [FIXTURE_RETURN_TYPE_NAME],
method_indices: [2],
});
expect(owned.items).toEqual([
{ index: 0, type: 0, name: FIXTURE_RETURN_TYPE_NAME },
]);
const otherOwner = await select("parameter_types", {
names: [FIXTURE_RETURN_TYPE_NAME],
method_indices: [0],
});
expect(otherOwner.items).toEqual([]);
// Version 27 intentionally retains unavailable native display names as null.
source = await inspect(27);
for (const collection of [
"return_types",
"field_types",
"parameter_types",
] as const) {
const unfiltered = await select(collection, {});
expect(unfiltered.items.length).toBeGreaterThan(0);
expect(
unfiltered.items.every((row) => "name" in row && row.name === null),
).toBe(true);
const unavailable = await select(collection, {
names: [FIXTURE_RETURN_TYPE_NAME, "null", ""],
});
expect(unavailable.items).toEqual([]);
expect(unavailable.coverage).toMatchObject({ total: 0, exhausted: true });
}
});
it("preserves native relationship coverage through inline and retained MCP views", async () => {
const { client, session } = await connect();
const { toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
const coverages: (RelationshipCoverage | undefined)[] = [
{
status: "partial",
limited_directions: ["callees"],
limitations: ["Callees: fixture read limit"],
diagnostics: ["Fixture relationship diagnostic"],
},
{ status: "partial", limitations: ["Historical read limit"] },
{
status: "unknown",
limited_directions: ["callees"],
reason: "Callees not measured",
diagnostics: ["Unknown coverage diagnostic"],
},
{
status: "complete",
diagnostics: ["Only direct references are observed"],
},
{ status: "complete" },
undefined,
];
for (const coverage of coverages) {
const parent = analysisViewNativeEvidence(coverage);
const parentBefore = JSON.stringify(parent);
const recorded = session.recordEvidence(parent);
if (!recorded.ok) throw recorded.error;
const outputs = [];
for (const source of [
{ kind: "inline", evidence: parent },
{ kind: "retained-evidence", evidence_id: parent.evidence_id },
]) {
const response = await client.callTool(
{
name: "inspect_analysis_view",
arguments: {
source,
view: { kind: "native", facet: "callees", offset: 0, limit: 1 },
},
},
{ toolDefinition },
);
expect(response.isError).not.toBe(true);
const evidence = parseEvidence(response.structuredContent);
expect(evidence.relationship_coverage).toEqual(
parent.relationship_coverage,
);
expect(evidence.normalized_result).toMatchObject({
item: [],
coverage: { total: 0, exhausted: true },
limitations: expect.arrayContaining(["Fixture dossier caveat"]),
});
expect(session.evidenceById(evidence.evidence_id)).toEqual(evidence);
outputs.push(evidence);
}
expect(outputs[0]).toEqual(outputs[1]);
expect(JSON.stringify(parent)).toBe(parentBefore);
}
});
it("directs unsupported parent views to the original Evidence", async () => {
const { client, session } = await connect();
const root = await createTestTempDirectory("rea-unsupported-view-mcp-");
const file = join(root, "evidence.json");
const bundle = join(root, "bundle.json");
const parent = createEvidence(
{ path: "/fixtures/native.exe", format: "pe", sha256: "a".repeat(64) },
{ id: "fixture", name: "Fixture", version: "1" },
{
operation: "inspect_recorded_crash",
parameters: {},
result: { path: "/artifacts/crash.core" },
},
);
expect(session.recordEvidence(parent).ok).toBe(true);
await writeFile(file, JSON.stringify(parent));
const errorSchema = JSON.parse(
await readFile("docs/error-contract.schema.json", "utf8"),
);
for (const source of [
{ kind: "inline", evidence: parent },
{ kind: "retained-evidence", evidence_id: parent.evidence_id },
{ kind: "evidence-file", path: file },
]) {
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: { source, view: { kind: "summary" } },
});
const { error } = parseMcpToolError(response);
expect(schemaValidation.assertions.validate(errorSchema, error)).toBe(true);
expect(error).toMatchObject({
code: "unsupported_target",
retryable: false,
details: {
operation: "inspect_analysis_view",
reason: expect.stringContaining(
'Parent Evidence operation "inspect_recorded_crash"',
),
},
});
expect(error.remediation.action).toContain("original complete Evidence");
expect(error.remediation.action).toContain("get_evidence_bundle");
expect(error.remediation.action).toContain("export_evidence_bundle");
expect(error.remediation.action).not.toContain("target format");
}
const complete = await client.callTool({
name: "get_evidence_bundle",
arguments: { detail: "complete" },
});
expect(complete.isError).not.toBe(true);
expect(complete.structuredContent).toMatchObject({
result: { records: expect.arrayContaining([parent]) },
});
const exported = await client.callTool({
name: "export_evidence_bundle",
arguments: { path: bundle },
});
expect(exported.isError).not.toBe(true);
const saved = JSON.parse(await readFile(bundle, "utf8"));
expect(saved.records).toContainEqual(parent);
});
it("advertises typed module references and preserves portable/retained Evidence parity", async () => {
const { client, session } = await connect();
const parent = analysisViewJavaScriptEvidence(
analysisViewJavaScriptAnalysisWithSource(),
);
const recorded = session.recordEvidence(parent);
if (!recorded.ok) throw recorded.error;
const { ajv, inputSchema, toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
const view = {
kind: "javascript",
collection: "modules",
projection: "references",
where: { path: "renderer.js" },
limit: 1,
};
const outputs = [];
for (const source of [
{ kind: "inline", evidence: parent },
{ kind: "retained-evidence", evidence_id: parent.evidence_id },
]) {
expect(ajv.validate(inputSchema, { source, view })).toBe(true);
expect(
ajv.validate(inputSchema, {
source,
view: { ...view, where: { glob: "*" } },
}),
).toBe(false);
const response = await client.callTool(
{ name: "inspect_analysis_view", arguments: { source, view } },
{ toolDefinition },
);
expect(response.isError).not.toBe(true);
const evidence = parseEvidence(response.structuredContent);
expect(evidence).toMatchObject({
evidence_links: [parent.evidence_id],
normalized_result: {
kind: "javascript",
rows: [
{
path: "renderer.js",
identity: expect.any(Object),
basis: expect.any(Array),
},
],
coverage: { exhausted: true },
},
});
expect(session.evidenceById(evidence.evidence_id)).toEqual(evidence);
outputs.push(evidence.normalized_result);
}
expect(outputs[0]).toEqual(outputs[1]);
});
it("projects opted-in query names identically from retained and portable MCP Evidence", async () => {
const { client, session } = await connect();
const capture = analysisViewCaptureFixture();
capture.records = capture.records.slice(0, 2);
capture.total_records = 2;
capture.records.forEach((record, index) => {
record.reported = {
request: {
method: "GET",
url:
index === 0
? "https://api.test/products?a+b=one&a%2Bb=two&=three&a+b=four"
: "https://api.test/products?a+b=five&snow=six#ignored",
},
};
});
const parent = analysisViewCaptureEvidence(capture);
const retained = session.recordEvidence(parent);
if (!retained.ok) throw retained.error;
const outputs = [];
for (const source of [
{ kind: "inline", evidence: parent },
{ kind: "retained-evidence", evidence_id: parent.evidence_id },
]) {
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source,
view: { kind: "api-surface", include_query_parameter_names: true },
},
});
expect(response.isError).not.toBe(true);
const evidence = parseEvidence(response.structuredContent);
expect(evidence.normalized_result).toMatchObject({
parent_evidence_id: parent.evidence_id,
groups: [
{
query_parameter_names: [
{ name: "", record_ordinals: [0] },
{ name: "a b", record_ordinals: [0, 1] },
{ name: "a+b", record_ordinals: [0] },
{ name: "snow", record_ordinals: [1] },
],
},
],
});
outputs.push(evidence.normalized_result);
}
expect(outputs[0]).toEqual(outputs[1]);
});
it("discovers an oversized native dossier by exact metadata and reads its retained view", async () => {
const { client, session } = await connect();
const advertised = (await client.listTools()).tools.find(
(tool) => tool.name === "inspect_analysis_view",
);
expect(advertised?.name).toBe("inspect_analysis_view");
const provider = { id: "ghidra", name: "Ghidra", version: "12.1.4" };
const profile = createAnalysisProfile(provider, { language: "fixture" });
const parent = createEvidence(
{ path: "/fixtures/large.exe", format: "pe", sha256: "a".repeat(64) },
provider,
{
operation: "analyze_function",
parameters: { procedure: "0x401000" },
analysisProfile: profile,
result: {
...jsonObjectSchema.parse(ghidraFunctionDossier()),
pseudocode: "x".repeat(6 * 1024 * 1024),
},
rawResult: null,
},
);
const other = createEvidence(
{ path: "/fixtures/other.exe", format: "pe", sha256: "b".repeat(64) },
provider,
{
operation: "analyze_function",
parameters: {},
result: ghidraFunctionDossier(),
},
);
for (const record of [parent, other]) {
const retained = session.recordEvidence(record);
if (!retained.ok) throw retained.error;
}
// The summary stays compact however large the retained pseudocode is.
const summary = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
view: { kind: "summary" },
},
});
expect(summary.isError, JSON.stringify(summary.content)).not.toBe(true);
expect(
toolContract("inspect_analysis_view").outputSchema.parse(
summary.structuredContent,
).normalized_result,
).toMatchObject({
kind: "summary",
parent_evidence_id: parent.evidence_id,
summary: {
pseudocode: { available: true, code_units: 6 * 1024 * 1024 },
},
});
const broad = await client.callTool({
name: "get_evidence_bundle",
arguments: {},
});
const broadError = parseMcpToolError(broad).error;
expect(broadError.code).toBe("resource_constraint");
expect(broadError.remediation?.action).toContain(
"get_evidence_bundle and detail: summary",
);
expect(broadError.remediation?.action).toContain(
"REA_MCP_MAX_RESPONSE_BYTES",
);
const response = await client.callTool({
name: "get_evidence_bundle",
arguments: {
detail: "summary",
filters: {
operation: "analyze_function",
target_sha256: "a".repeat(64),
analysis_profile_digest: profile.digest,
procedure_address: "0x401000",
},
},
});
expect(response.isError).not.toBe(true);
const result = toolContract("get_evidence_bundle").outputSchema.parse(
response.structuredContent,
).result;
// Two analyze_function records plus the retained summary view.
expect(result).toMatchObject({
kind: "evidence-bundle-summary",
total_retained_records: 3,
matching_records: 1,
records: [
{
evidence_id: parent.evidence_id,
analysis_profile_digest: profile.digest,
retention: "complete-record",
native_dossier: { available: true, procedure_address: "0x401000" },
},
],
});
expect(JSON.stringify(response)).not.toContain("pseudocode");
expect(
JSON.parse(response.content.find((c) => c.type === "text")?.text ?? "null"),
).toEqual(response.structuredContent);
const page = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
view: { kind: "native", facet: "pseudocode", offset: 0, limit: 32 },
},
});
expect(page.isError).not.toBe(true);
expect(
toolContract("inspect_analysis_view").outputSchema.parse(
page.structuredContent,
).normalized_result,
).toMatchObject({
item: { text: "x".repeat(32) },
coverage: { total: 6 * 1024 * 1024, exhausted: false },
});
const empty = await client.callTool({
name: "get_evidence_bundle",
arguments: {
detail: "summary",
filters: { evidence_id: `ev_${"e".repeat(64)}` },
},
});
expect(
toolContract("get_evidence_bundle").outputSchema.parse(
empty.structuredContent,
).result,
).toMatchObject({ matching_records: 0, records: [] });
await client.ping();
const invalid = await client.callTool({
name: "get_evidence_bundle",
arguments: { filters: { operation: "analyze_function" } },
});
expect(parseMcpToolError(invalid).error.code).toBe("invalid_request");
});
it("advertises exact schemas and projects one layout section from retained Evidence", async () => {
const layout = analysisViewLayoutFixture();
const service = new BinaryLayoutService({
inspectAndClose(input, options) {
return this.inspect(input, options);
},
identity: BINARY_LAYOUT_TEST_PROVIDER,
inspect: () => Promise.resolve(ok(layout)),
});
const { client, session } = await connect(service);
const { ajv, inputSchema, toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
expect(
ajv.validate(inputSchema, {
source: { kind: "inline", evidence: analysisViewLayoutEvidence() },
view: { kind: "summary" },
}),
).toBe(true);
expect(
ajv.validate(inputSchema, {
source: { kind: "inline", evidence: {} },
view: { kind: "summary" },
}),
).toBe(false);
expect(
ajv.validate(inputSchema, {
source: {
kind: "retained-evidence",
evidence_id: `ev_${"a".repeat(64)}`,
},
view: { kind: "summary", approval: true },
}),
).toBe(false);
const inspected = await client.callTool({
name: "inspect_binary_layout",
arguments: { path: layout.artifact.path },
});
expect(inspected.isError).not.toBe(true);
const parent = toolContract("inspect_binary_layout").outputSchema.parse(
inspected.structuredContent,
);
const response = await client.callTool(
{
name: "inspect_analysis_view",
arguments: {
source: {
kind: "retained-evidence",
evidence_id: parent.evidence_id,
},
view: {
kind: "item",
collection: "sections",
selector: { name: ".data" },
},
},
},
{ toolDefinition },
);
expect(response.isError).not.toBe(true);
const parsed = toolContract("inspect_analysis_view").outputSchema.parse(
response.structuredContent,
);
expect(parsed.normalized_result).toMatchObject({
kind: "item",
parent_evidence_id: parent.evidence_id,
item: { name: { display: ".data" } },
});
expect(session.evidenceById(parsed.evidence_id)).toEqual(
parseEvidence(parsed),
);
});
it("points omitted inline messages to the caller's parent without promising session recovery", async () => {
const { client, session } = await connect();
const messages = Array.from(
{ length: 65 },
(_, index) => `Limitation ${String(index).padStart(2, "0")}`,
).concat("z".repeat(300_000));
const parent = analysisViewLayoutEvidence({
...analysisViewLayoutFixture(),
limitations: messages,
});
expect(session.evidenceById(parent.evidence_id)).toBeUndefined();
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "inline", evidence: parent },
view: { kind: "summary" },
},
});
expect(response.isError).not.toBe(true);
const view = toolContract("inspect_analysis_view").outputSchema.parse(
response.structuredContent,
);
const projected = z
.object({ limitations: z.array(z.string()) })
.parse(view.normalized_result);
expect(projected.limitations).toEqual([
...messages.slice(0, 65),
`1 additional limitations omitted from this view; consult source parent Evidence ${parent.evidence_id} for the complete list (the caller-supplied record, or its retaining session).`,
]);
expect(session.evidenceById(parent.evidence_id)).toBeUndefined();
expect(session.evidenceById(view.evidence_id)).toEqual(parseEvidence(view));
});
it("reports a tampered inline Evidence ID at its full MCP source path", async () => {
const { client } = await connect();
const parent = analysisViewLayoutEvidence();
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: {
kind: "inline",
evidence: { ...parent, evidence_id: `ev_${"0".repeat(64)}` },
},
view: { kind: "summary" },
},
});
expect(parseMcpToolError(response).error).toMatchObject({
code: "invalid_request",
category: "invalid_input",
details: {
issues: [
{
path: ["source", "evidence", "evidence_id"],
reason: "invalid_value",
message: expect.stringMatching(/semantic identifier.*not match/iu),
},
],
},
});
});
it("reports empty retained layout selectors without index bounds", async () => {
const { client, session } = await connect();
const parent = analysisViewLayoutEvidence(binaryLayoutFixture());
expect(session.recordEvidence(parent).ok).toBe(true);
for (const collection of ["sections", "symbols"] as const) {
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
view: { kind: "item", collection, selector: { index: 0 } },
},
});
const error = parseMcpToolError(response).error;
expect(error).toMatchObject({
code: "invalid_request",
details: {
issues: [
{
path: ["view", "selector", "index"],
reason: "invalid_value",
message: expect.stringContaining(`No retained ${collection}`),
},
],
},
});
expect(error.details).not.toHaveProperty("issues.0.minimum");
expect(error.details).not.toHaveProperty("issues.0.maximum");
}
expect(session.evidenceById(parent.evidence_id)).toEqual(
parseEvidence(parent),
);
});
it("locates malformed PCAP results within inline and retained view sources", async () => {
const { client, session } = await connect();
const cases = [
{ result: {}, path: ["target"], reason: "missing_argument" },
{ result: { target: false }, path: ["target"], reason: "invalid_type" },
{
result: { target: { sha256: "c".repeat(64), bytes: 24 } },
path: ["target", "path"],
reason: "missing_argument",
},
] as const;
for (const { result, path, reason } of cases) {
// Authenticated fixture Evidence can still contain malformed operation data.
const evidence = createEvidence(
{
path: "/recordings/input.pcap",
format: "file",
sha256: "c".repeat(64),
},
{ id: "fixture", name: "Fixture", version: "1" },
{
operation: "inspect_pcap_capture",
parameters: { path: "/recordings/input.pcap" },
result,
authority: "historical-reference",
},
);
const recorded = session.recordEvidence(evidence);
if (!recorded.ok) throw recorded.error;
for (const source of [
{ kind: "inline", evidence },
{ kind: "retained-evidence", evidence_id: evidence.evidence_id },
]) {
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: { source, view: { kind: "summary" } },
});
expect(parseMcpToolError(response).error).toMatchObject({
code: "invalid_request",
details: {
issues: expect.arrayContaining([
expect.objectContaining({
path: ["source", "normalized_result", ...path],
reason,
}),
]),
},
});
}
}
});
it("rejects self-contained WASM and EVM Evidence views when the subject format differs", async () => {
const { client } = await connect();
const wasm = wasmArtifactFixture();
const evm = evmInterfaceFixture();
const cases = [
{
evidence: createEvidence(
{
path: wasm.artifact.path,
format: "elf",
sha256: wasm.artifact.sha256,
},
{ id: "fixture-wabt", name: "WABT", version: "1" },
{
operation: "inspect_wasm_artifact",
parameters: { path: wasm.artifact.path },
result: wasm,
},
),
},
{
evidence: createEvidence(
{
path: evm.artifact.path,
format: "elf",
sha256: evm.artifact.sha256,
},
{ id: "fixture-evm", name: "EVMole", version: "1" },
{
operation: "inspect_evm_interface",
parameters: { path: evm.artifact.path, encoding: "hex" },
result: evm,
},
),
},
] as const;
for (const { evidence } of cases) {
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "inline", evidence },
view: { kind: "summary" },
},
});
expect(parseMcpToolError(response).error).toMatchObject({
code: "invalid_request",
details: {
issues: [
expect.objectContaining({
path: ["source", "subject"],
reason: "invalid_value",
}),
],
},
});
}
});
it("admits portable captures before SDK Evidence parsing and preserves capture caveats", async () => {
// Reach portable-capture memory admission with the 100,000-header fixture;
// the lower transport default has separate coverage.
const { client } = await connect(undefined, undefined, 524_288);
const dense = analysisViewCaptureEvidence(analysisViewObjectDenseCapture());
const refused = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "inline", evidence: dense },
view: { kind: "api-surface" },
},
});
expect(parseMcpToolError(refused).error).toMatchObject({
code: "resource_constraint",
details: { resource: "memory" },
});
await client.ping();
const capture = analysisViewCaptureFixture();
capture.records = capture.records.slice(0, 1);
capture.total_records = 1;
const caveat = "Producer omitted exchanges before capture startup.";
capture.limitations = [caveat, caveat];
capture.records[0]!.reported = {
request: { method: "GET", url: "https://api.test/a" },
response: { status: 200, content: { mimeType: "\u00a0text/plain\u00a0" } },
};
const parent = analysisViewCaptureEvidence(capture);
expect(parent.limitations).not.toContain(caveat);
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "inline", evidence: parent },
view: { kind: "api-surface" },
},
});
const result = parseEvidence(response.structuredContent);
expect(result.limitations.filter((value) => value === caveat)).toEqual([
caveat,
]);
expect(result.normalized_result).toMatchObject({
groups: [{ content_types: [], flags: ["single-sample"] }],
limitations: expect.arrayContaining([caveat]),
unknowns: [expect.stringMatching(/unavailable status or content type/iu)],
});
});
it("rejects inconsistent portable coverage and accepts caller-ordered ordinal subsets", async () => {
const { client } = await connect();
for (const [total, ordinals] of [
[0, [0]],
[2, [0, 0]],
[2, [2]],
] as const) {
const capture = analysisViewCaptureFixture();
capture.total_records = total;
capture.records = ordinals.map((ordinal) => ({
...capture.records[0]!,
ordinal,
}));
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: {
kind: "inline",
evidence: analysisViewCaptureEvidence(capture),
},
view: { kind: "api-surface" },
},
});
expect(parseMcpToolError(response).error.code).toBe("invalid_request");
}
const capture = analysisViewCaptureFixture();
capture.records = [capture.records[8]!, capture.records[1]!];
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: {
kind: "inline",
evidence: analysisViewCaptureEvidence(capture),
},
view: { kind: "api-surface" },
},
});
expect(
parseEvidence(response.structuredContent).normalized_result,
).toMatchObject({
records: { examined: 2, total: 15 },
limitations: expect.arrayContaining([
"Parent contains an ordinal subset; the surface covers only retained records.",
]),
});
});
it("delivers a bounded native dossier view over MCP without a Ghidra provider or lost connection", async () => {
const { client, session } = await connect();
const original = functionDossierSchema.parse(ghidraFunctionDossier());
const parent = createEvidence(
{
path: "/fixtures/oversized-native.exe",
format: "pe",
sha256: "b".repeat(64),
},
{ id: "ghidra", name: "Ghidra", version: "12.1.4" },
{
operation: "analyze_function",
parameters: { address: "0x401000" },
result: { ...original, pseudocode: "X".repeat(11 * 1024 * 1024) },
},
);
expect(session.recordEvidence(parent).ok).toBe(true);
const advertised = (await client.listTools()).tools.find(
(tool) => tool.name === "inspect_analysis_view",
);
if (advertised?.outputSchema === undefined)
throw new Error("missing view schemas");
const ajv = schemaValidation.assertions;
const inputSchema: Record<string, unknown> = advertised.inputSchema;
const outputSchema: Record<string, unknown> = advertised.outputSchema;
const arguments_ = {
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
view: { kind: "native", facet: "pseudocode", offset: 0, limit: 500 },
};
expect(ajv.validateSchema(inputSchema)).toBe(true);
expect(ajv.validateSchema(outputSchema)).toBe(true);
expect(
ajv.validate(inputSchema, arguments_),
JSON.stringify(ajv.errors),
).toBe(true);
const response = await client.callTool(
{ name: "inspect_analysis_view", arguments: arguments_ },
{ toolDefinition: advertised },
);
expect(response.isError).not.toBe(true);
const parsed = toolContract("inspect_analysis_view").outputSchema.parse(
response.structuredContent,
);
expect(parsed.normalized_result).toMatchObject({
kind: "native",
parent_evidence_id: parent.evidence_id,
procedure_address: "0x401000",
coverage: { examined: 500, next_offset: 500, total: 11 * 1024 * 1024 },
});
expect(parsed.evidence_links).toEqual([parent.evidence_id]);
expect(parsed.locations).toEqual([
{ kind: "artifact-path", path: "/fixtures/oversized-native.exe" },
{ kind: "address", address: "0x401000" },
]);
expect(JSON.stringify(response.structuredContent).length).toBeLessThan(12000);
await client.ping();
});
it("retains an oversized selected observation and keeps subsequent views usable", async () => {
const { client, session } = await connect();
const analysis = analysisViewJavaScriptAnalysisWithSource();
const original = analysis.graph.nodes[0];
if (original === undefined) throw new Error("missing module");
const source = "\0".repeat(1_000_000);
const node = createJavaScriptApplicationNode({
kind: original.kind,
identity: original.identity,
observations: original.observations.map((observation) => ({
label: observation.label,
properties: { ...observation.properties, source },
evidence: observation.evidence,
})),
});
const graph = createJavaScriptApplicationGraph({
schema: "JavaScriptApplicationGraph",
root_node_ids: [node.node_id],
nodes: [node],
edges: [],
coverage: analysis.graph.coverage,
limitations: analysis.graph.limitations,
});
const parent = analysisViewJavaScriptEvidence(
analysisViewBindJavaScriptGraphs(analysis, graph),
);
expect(session.recordEvidence(parent).ok).toBe(true);
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
view: {
kind: "item",
collection: "modules",
selector: { node_id: node.node_id },
},
},
});
expect(response.isError).toBe(true);
const reference = z
.object({
error: z.object({
details: z.object({
reported_limits: z.object({
evidence_reference: z.object({
kind: z.literal("retained-evidence"),
evidence_id: z.string(),
}),
}),
}),
}),
})
.parse(parseMcpToolError(response)).error.details
.reported_limits.evidence_reference;
expect(
session.evidenceById(reference.evidence_id)?.normalized_result,
).toMatchObject({
item: {
observations: [
expect.objectContaining({
properties: expect.objectContaining({ source }),
}),
],
},
});
await client.ping();
const summary = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
view: { kind: "summary" },
},
});
expect(summary.isError).not.toBe(true);
});
it("retains an oversized native assembly row and permits a subsequent smaller view", async () => {
const { client, session } = await connect();
const row = "\0".repeat(1_000_000);
const parent = createEvidence(
{ path: "/fixtures/large-row.exe", format: "pe", sha256: "c".repeat(64) },
{ id: "ghidra", name: "Ghidra", version: "12.1.4" },
{
operation: "analyze_function",
parameters: {},
result: {
...functionDossierSchema.parse(ghidraFunctionDossier()),
assembly: [row],
},
},
);
expect(session.recordEvidence(parent).ok).toBe(true);
const source = { kind: "retained-evidence", evidence_id: parent.evidence_id };
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source,
view: { kind: "native", facet: "assembly", offset: 0, limit: 1 },
},
});
expect(response.isError).toBe(true);
const error = z
.object({
error: z.object({
details: z.object({
reported_limits: z.object({
evidence_reference: z.object({
kind: z.literal("retained-evidence"),
evidence_id: z.string(),
}),
}),
}),
}),
})
.parse(parseMcpToolError(response));
const retained = session.evidenceById(
error.error.details.reported_limits.evidence_reference.evidence_id,
);
expect(retained?.normalized_result).toMatchObject({
item: [row],
parent_evidence_id: parent.evidence_id,
});
const next = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source,
view: { kind: "native", facet: "pseudocode", offset: 0, limit: 12 },
},
});
expect(next.isError).not.toBe(true);
expect(
toolContract("inspect_analysis_view").outputSchema.parse(
next.structuredContent,
).normalized_result,
).toMatchObject({
item: { text: "int fixture_" },
parent_evidence_id: parent.evidence_id,
});
await client.ping();
});
it("reads successive native source pages directly from a completed-result transport error", async () => {
const pseudocode = "int fixture_add(int a, int b) { return a + b; }\n".repeat(
150_000,
);
const harness = await connectGhidraMcp(
"native-continuation",
async (operation) => {
if (operation !== "analyze_function")
throw new Error(`Unexpected provider operation: ${operation}`);
return ok({
value: {
...functionDossierSchema.parse(ghidraFunctionDossier()),
pseudocode,
},
limitations: [],
});
},
);
onTestFinished(() => harness.close());
const { mcp: client, session, calls } = harness;
// Complete delivery of an oversized dossier fails transport and points at the retained parent.
const failed = await client.callTool({
name: "analyze_function",
arguments: { procedure: "0x401000", detail: "complete" },
});
expect(failed.isError).toBe(true);
const limits = z
.object({
error: z.object({
details: z.object({ reported_limits: jsonObjectSchema }),
}),
})
.parse(parseMcpToolError(failed)).error.details.reported_limits;
const reference = z
.object({
kind: z.literal("retained-evidence"),
evidence_id: z.string(),
})
.parse(limits.evidence_reference);
const parent = parseEvidence(session.evidenceById(reference.evidence_id));
expect(parent.operation).toBe("analyze_function");
expect(parent.parameters).toMatchObject({ procedure: "0x401000" });
const call = z
.object({
name: z.literal("inspect_analysis_view"),
arguments: toolContract("inspect_analysis_view").inputSchema,
})
.parse(limits.continuation);
expect(call.arguments.source).toEqual({
kind: "retained-evidence",
evidence_id: parent.evidence_id,
});
const first = await client.callTool(call);
expect(first.isError).not.toBe(true);
const page = toolContract("inspect_analysis_view").outputSchema.parse(
first.structuredContent,
).normalized_result;
expect(page).toMatchObject({
parent_evidence_id: parent.evidence_id,
item: { text: pseudocode.slice(0, 64) },
coverage: { examined: 64, next_offset: 64, exhausted: false },
});
expect(Buffer.byteLength(JSON.stringify(first))).toBeLessThan(
STDIO_DEFAULT_MAX_BUFFER_SIZE,
);
if (page.coverage === null) throw new Error("Expected known coverage");
const second = await client.callTool({
name: call.name,
arguments: {
...call.arguments,
view: {
kind: "native",
facet: "pseudocode",
offset: page.coverage.next_offset,
limit: 64,
},
},
});
expect(second.isError).not.toBe(true);
expect(
toolContract("inspect_analysis_view").outputSchema.parse(
second.structuredContent,
).normalized_result,
).toMatchObject({ item: { text: pseudocode.slice(64, 128) } });
expect(
session.evidenceById(parent.evidence_id)?.normalized_result,
).toMatchObject({ pseudocode });
await client.ping();
expect(calls).toEqual(["analyze_function"]);
});
it("returns a JavaScript summary without graph payloads from a retained reference", async () => {
const { client, session } = await connect();
const parent = analysisViewJavaScriptEvidence();
expect(session.recordEvidence(parent).ok).toBe(true);
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: {
kind: "retained-evidence",
evidence_id: parent.evidence_id,
},
view: { kind: "summary" },
},
});
expect(response.isError).not.toBe(true);
const parsed = toolContract("inspect_analysis_view").outputSchema.parse(
response.structuredContent,
);
expect(parsed.normalized_result).toMatchObject({
kind: "summary",
parent_operation: "analyze_javascript_application",
summary: { format: "directory" },
});
expect(parsed.normalized_result).not.toHaveProperty("summary.semantic_graph");
const stale = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: {
kind: "retained-evidence",
evidence_id: `ev_${"e".repeat(64)}`,
},
view: { kind: "summary" },
},
});
expect(parseMcpToolError(stale)).toMatchObject({
error: { details: { reason: "missing" } },
});
});
it("accepts a transport-constraint retained reference as the view source", async () => {
const { client, session } = await connect();
const parent = analysisViewJavaScriptEvidence();
expect(session.recordEvidence(parent).ok).toBe(true);
const evidenceReference = {
kind: "retained-evidence" as const,
evidence_id: parent.evidence_id,
};
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: evidenceReference,
view: {
kind: "page",
collection: "modules",
offset: 0,
limit: 8,
},
},
});
expect(response.isError).not.toBe(true);
const parsed = toolContract("inspect_analysis_view").outputSchema.parse(
response.structuredContent,
);
expect(parsed.normalized_result).toMatchObject({
kind: "page",
parent_evidence_id: parent.evidence_id,
coverage: { exhausted: true },
});
if (parsed.normalized_result.kind !== "page")
throw new Error("expected page view");
expect(parsed.normalized_result.items).toEqual([
{
node_id: expect.any(String),
kind: "javascript-asset",
path: "renderer.js",
},
]);
});
it("projects an actual HAR capture retained by the public MCP workflow", async () => {
const root = await createTestTempDirectory("rea-surface-mcp-");
const path = join(root, "surface.har");
await writeFile(path, JSON.stringify(apiSurfaceHar()));
const service = new WebNetworkCaptureService({
inspect: async (input) => {
const bytes = await readFile(input.capture_path);
return ok({
...decodeHarCapture(bytes.toString("utf8"), input.sensitive_values),
artifact: {
path: input.capture_path,
sha256: createHash("sha256").update(bytes).digest("hex"),
bytes: bytes.length,
},
format: "har",
runtime_attribution: "unknown",
limitations: [],
});
},
});
const { client } = await connect(undefined, service);
const captureResponse = await client.callTool({
name: "inspect_web_network_capture",
arguments: { capture_path: path, format: "har" },
});
expect(captureResponse.isError).not.toBe(true);
const parent = parseEvidence(captureResponse.structuredContent);
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
view: { kind: "api-surface" },
},
});
expect(response.isError).not.toBe(true);
const evidence = parseEvidence(response.structuredContent);
expect(evidence.confidence).toBe("inferred");
expect(evidence.normalized_result).toMatchObject({
records: { examined: 13, total: 13, excluded: 0 },
coverage: { total: 12, exhausted: true },
groups: expect.arrayContaining([
expect.objectContaining({
path_template: "/users/{numeric}",
record_ordinals: [0, 1],
}),
]),
});
});
const PUBLISHED_EXAMPLES: readonly (readonly [
name: string,
example: {
readonly input: {
readonly source: { readonly evidence_id: string };
readonly view: Record<string, unknown>;
};
readonly output: { readonly artifact: { readonly path: string } };
},
fixture: () => unknown,
])[] = [
[
"API surface",
API_SURFACE_EXAMPLE,
() => {
const fixture = apiSurfaceHar();
fixture.log.entries = fixture.log.entries.slice(0, 2);
return fixture;
},
],
[
"environment manifest",
ENVIRONMENT_MANIFEST_EXAMPLE,
() => {
const fixture = environmentManifestHar();
fixture.log.entries = [10, 20, 27].map(
(index) => fixture.log.entries[index]!,
);
return fixture;
},
],
];
it.each(PUBLISHED_EXAMPLES)(
"reproduces the published %s example from decoded fixture bytes",
async (_name, example, fixture) => {
const bytes = Buffer.from(JSON.stringify(fixture()));
const path = example.output.artifact.path;
const service = new WebNetworkCaptureService({
inspect: async () =>
ok({
...decodeHarCapture(bytes.toString("utf8"), []),
artifact: {
path,
sha256: createHash("sha256").update(bytes).digest("hex"),
bytes: bytes.length,
},
format: "har",
runtime_attribution: "unknown",
limitations: [],
}),
});
const { client } = await connect(undefined, service);
const capture = await client.callTool({
name: "inspect_web_network_capture",
arguments: { capture_path: path, format: "har" },
});
expect(parseEvidence(capture.structuredContent).evidence_id).toBe(
example.input.source.evidence_id,
);
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: example.input,
});
expect(parseEvidence(response.structuredContent).normalized_result).toEqual(
example.output,
);
},
);
it.each([false, true])(
"keeps known chronology and unrelated facts with unknown delete completion %s through MCP",
async (unknownCompletion) => {
const { client, session } = await connect();
const entry = (
method: string,
path: string,
second: string,
body: JsonValue,
status = 200,
) => ({
startedDateTime: `2026-10-20T09:00:${second}Z`,
time: 0,
request: { method, url: `http://app.example${path}` },
response: {
status,
content: { mimeType: "application/json", text: JSON.stringify(body) },
},
});
const { time: _readDuration, ...laterRead } = entry(
"GET",
"/api/settings",
"02",
{ theme: "dark" },
);
const deletion = entry("DELETE", "/api/items/2", "03", "", 204);
const { time: _deleteDuration, ...unknownDeletion } = deletion;
const capture = environmentManifestCaptureFixture([
entry("GET", "/api/settings", "00", { theme: "light" }),
laterRead,
entry("PATCH", "/api/settings", "01", { theme: "dark" }),
entry("GET", "/api/health", "00.1", { healthy: true }),
entry("GET", "/api/version", "00.2", { version: "1" }),
entry("GET", "/api/items", "00.3", [{ id: 1 }, { id: 2 }]),
entry("GET", "/api/items/2", "00.4", { id: 2 }),
unknownCompletion ? unknownDeletion : deletion,
entry("GET", "/api/items/2", "04", null, 404),
]);
const parent = analysisViewCaptureEvidence(capture);
const before = structuredClone(parent);
expect(session.recordEvidence(parent).ok).toBe(true);
const response = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
view: { kind: "environment-state" },
},
});
expect(response.isError, JSON.stringify(response.content)).not.toBe(true);
const state = analysisViewResultSchema.parse(
parseEvidence(response.structuredContent).normalized_result,
);
expect(state).toMatchObject({
kind: "environment-state",
timeline: "recorded-start-time",
documents: expect.arrayContaining([
expect.objectContaining({
path: "/api/settings",
value: { theme: "light" },
}),
expect.objectContaining({
path: "/api/health",
value: { healthy: true },
}),
expect.objectContaining({
path: "/api/version",
value: { version: "1" },
}),
]),
writes: expect.arrayContaining([
expect.objectContaining({
tool: "delete_items_by_id",
served: !unknownCompletion,
}),
]),
limitations: expect.arrayContaining([
expect.stringMatching(
/request duration.*completion.*overlap.*unknown/iu,
),
]),
});
expect(parent).toEqual(before);
expect(session.evidenceById(parent.evidence_id)).toEqual(before);
},
);
it("advertises unserved learned clock rules when a retained capture has no global clock", async () => {
const { client, session } = await connect();
const { toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
const parents = [
timedCaptureEvidence(BOOK_ROWS),
timedCaptureEvidence([
...BOOK_ROWS,
["GET", "/api/health", { ready: true }, 200, undefined, -1],
]),
];
const states = [];
for (const parent of parents) {
const original = structuredClone(parent);
expect(session.recordEvidence(parent).ok).toBe(true);
const response = await client.callTool(
{
name: "inspect_analysis_view",
arguments: {
source: {
kind: "retained-evidence",
evidence_id: parent.evidence_id,
},
view: { kind: "environment-state" },
},
},
{ toolDefinition },
);
expect(response.isError, JSON.stringify(response.content)).not.toBe(true);
const state = analysisViewResultSchema.parse(
parseEvidence(response.structuredContent).normalized_result,
);
if (state.kind !== "environment-state")
throw new Error("Expected environment-state result");
states.push(state);
expect(parent).toEqual(original);
expect(session.evidenceById(parent.evidence_id)).toEqual(original);
}
const [baseline, unknown] = states;
if (baseline === undefined || unknown === undefined)
throw new Error("Expected both clock controls");
expect(baseline.write_clock).not.toBeNull();
expect(unknown.write_clock).toBeNull();
const clockPlans = baseline.writes.filter(
(plan) =>
plan.served &&
plan.rules.some((rule) =>
["clock", "held-clock", "nested-clock"].includes(rule.rule),
),
);
expect(clockPlans.length).toBeGreaterThan(0);
for (const plan of clockPlans)
expect(
unknown.writes.find((candidate) => candidate.tool === plan.tool),
).toEqual({ ...plan, served: false, reason: "unknown-clock" });
const independent = baseline.writes.find(
(plan) => plan.tool === "delete_books_by_id",
);
expect(independent).toMatchObject({ served: true });
expect(unknown.writes).toContainEqual(independent);
});
it("advertises Mach-O pages whose selected facet owns their exact rows", async () => {
const { client, session } = await connect();
const { ajv, outputSchema, toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
const coverage = <Row>(items: Row[]) => ({
items,
total: items.length,
exhaustive: true,
limitations: [],
});
const symbol = {
name: "_entry",
address: null,
weak: null,
reexport: null,
source: null,
};
const report = inspectMachoSchema.parse({
format: "mach-o",
selected_architecture: { name: "arm64", container_file_offset: 0 },
endian: "little",
word_size: 64,
file_type: "2",
flags: [],
uuid: null,
entrypoints: coverage([{ file_offset: 64 }]),
architectures: coverage([]),
build_metadata: coverage([]),
load_commands: coverage([]),
dependencies: coverage([]),
imports: coverage([
{
...symbol,
name: null,
raw_name: "_entry+0x4",
name_status: "ambiguous",
addend: null,
},
]),
exports: coverage([symbol]),
segments: coverage([]),
encryption: coverage([
{
architecture: "arm64",
cpu_type: 16777228,
cpu_subtype: 0,
container_file_offset: 0,
size: 4096,
status: "absent",
reason: null,
malformed_kind: null,
commands: [],
range: null,
},
]),
provenance: [],
limitations: [],
});
const { malformed_kind: _unrecorded, ...recordedEncryption } =
report.encryption.items[0]!;
const historicalEncryption = {
...recordedEncryption,
status: "malformed" as const,
reason: "slice has 3 encryption load commands",
};
const parent = createEvidence(
{ path: "/fixtures/tool", format: "mach-o", sha256: "a".repeat(64) },
{ id: "native", name: "Native fixture", version: "1" },
{
operation: "inspect_macho",
parameters: {},
result: { ...report, encryption: coverage([historicalEncryption]) },
},
);
const original = structuredClone(parent);
expect(session.recordEvidence(parent).ok).toBe(true);
for (const facet of [
"entrypoints",
"imports",
"exports",
"segments",
"encryption",
] as const) {
for (const offset of [0, 999]) {
const response = await client.callTool(
{
name: "inspect_analysis_view",
arguments: {
source: {
kind: "retained-evidence",
evidence_id: parent.evidence_id,
},
view: { kind: "macho", facet, offset, limit: 64 },
},
},
{ toolDefinition },
);
expect(response.isError, JSON.stringify(response.content)).not.toBe(true);
const delivered = parseEvidence(response.structuredContent);
const page = analysisViewResultSchema.parse(delivered.normalized_result);
if (page.kind !== "macho") throw new Error("Expected Mach-O page");
const rows =
facet === "encryption"
? [{ ...historicalEncryption, malformed_kind: "unrecorded" }]
: report[facet].items;
expect(page.item).toEqual(rows.slice(offset, offset + 64));
if (page.item.length > 0) {
const mismatched = {
...delivered,
normalized_result: {
...page,
view: {
...page.view,
facet: facet === "entrypoints" ? "exports" : "entrypoints",
},
},
};
expect(ajv.validate(outputSchema, mismatched)).toBe(false);
}
expect(
ajv.validate(outputSchema, {
...delivered,
normalized_result: {
...page,
item: undefined,
},
}),
).toBe(false);
}
}
expect(parent).toEqual(original);
expect(session.evidenceById(parent.evidence_id)).toEqual(original);
});
it("extracts an environment state identically from retained, portable and file MCP Evidence", async () => {
// Full inline capture conformance explicitly selects its transport allowance.
const { client, session } = await connect(undefined, undefined, 8_192);
const { ajv, inputSchema, toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
const capture = environmentStateCaptureFixture();
const parent = analysisViewCaptureEvidence(capture);
expect(session.recordEvidence(parent).ok).toBe(true);
const evidencePath = join(
await createTestTempDirectory("rea-state-file-mcp-"),
"capture.json",
);
await writeFile(evidencePath, JSON.stringify(parent));
const view = {
kind: "environment-state",
template_rules: ["after-uid-literal", "opaque-token", "sibling-variance"],
};
const outputs = [];
for (const source of [
{ kind: "inline", evidence: parent },
{ kind: "retained-evidence", evidence_id: parent.evidence_id },
{ kind: "evidence-file", path: evidencePath },
]) {
expect(ajv.validate(inputSchema, { source, view })).toBe(true);
const response = await client.callTool(
{
name: "inspect_analysis_view",
arguments: { source, view },
},
{ toolDefinition },
);
expect(response.isError).not.toBe(true);
const evidence = parseEvidence(response.structuredContent);
expect(evidence.confidence).toBe("inferred");
expect(evidence.normalized_result).toMatchObject({
kind: "environment-state",
views: expect.arrayContaining([
expect.objectContaining({
tool: "get_folders_by_uid",
shape: "item",
}),
]),
});
expect(session.evidenceById(evidence.evidence_id)).toEqual(evidence);
outputs.push(evidence.normalized_result);
}
expect(outputs[0]).toEqual(outputs[1]);
expect(outputs[2]).toEqual(outputs[0]);
const hidden = createEvidence(
{
path: capture.artifact.path,
sha256: capture.artifact.sha256!,
format: "file",
},
{ id: "fixture", name: "fixture", version: "1" },
{
operation: "inspect_web_network_capture",
parameters: { sensitive_value_count: 1 },
result: capture,
confidence: "observed",
},
);
const refused = await client.callTool({
name: "inspect_analysis_view",
arguments: { source: { kind: "inline", evidence: hidden }, view },
});
const hiddenError = parseMcpToolError(refused).error;
expect(hiddenError.code).toBe("unsupported_target");
expect(hiddenError.remediation.action).toContain("sensitivity declarations");
expect(hiddenError.remediation.action).toContain("capture or summary view");
expect(hiddenError.remediation.action).not.toContain("target format");
expect(JSON.stringify(refused)).not.toContain("probe folder");
await client.ping();
});
it("reports environment coverage identically from retained, portable and file MCP Evidence", async () => {
const { client, session } = await connect(undefined, undefined, 8_192);
const { ajv, inputSchema, toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
const parent = analysisViewCaptureEvidence(environmentStateCaptureFixture());
expect(session.recordEvidence(parent).ok).toBe(true);
const evidencePath = join(
await createTestTempDirectory("rea-coverage-file-mcp-"),
"capture.json",
);
await writeFile(evidencePath, JSON.stringify(parent));
const rules = ["after-uid-literal", "opaque-token", "sibling-variance"];
const outputs = [];
for (const source of [
{ kind: "inline", evidence: parent },
{ kind: "retained-evidence", evidence_id: parent.evidence_id },
{ kind: "evidence-file", path: evidencePath },
]) {
const view = { kind: "environment-coverage", template_rules: rules };
expect(ajv.validate(inputSchema, { source, view })).toBe(true);
const response = await client.callTool(
{
name: "inspect_analysis_view",
arguments: { source, view },
},
{ toolDefinition },
);
expect(response.isError).not.toBe(true);
const evidence = parseEvidence(response.structuredContent);
expect(evidence.confidence).toBe("inferred");
expect(evidence.normalized_result).toMatchObject({
kind: "environment-coverage",
reads: { state: expect.any(Number) },
writes: { served: expect.any(Array), withheld: expect.any(Array) },
});
outputs.push(evidence.normalized_result);
}
expect(outputs[1]).toEqual(outputs[0]);
expect(outputs[2]).toEqual(outputs[0]);
await client.ping();
});
it("accounts for every safe HTTP method in environment state and coverage", async () => {
const { client } = await connect();
const { toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
const entries = ["GET", "HEAD", "OPTIONS", "TRACE"].map((method) => ({
request: { method, url: "https://sample.test/api/items" },
response: {
status: 200,
content:
method === "GET"
? {
mimeType: "application/json",
text: '{"items":[{"id":"a"}]}',
size: 22,
}
: { mimeType: "application/json", size: 0 },
},
}));
const parent = analysisViewCaptureEvidence(
environmentManifestCaptureFixture(entries),
);
const results = [];
for (const kind of [
"environment-manifest",
"environment-state",
"environment-coverage",
]) {
const response = await client.callTool(
{
name: "inspect_analysis_view",
arguments: {
source: { kind: "inline", evidence: parent },
view: { kind, template_rules: [] },
},
},
{ toolDefinition },
);
expect(response.isError).not.toBe(true);
results.push(parseEvidence(response.structuredContent).normalized_result);
}
expect(results[0]).toMatchObject({
tools: expect.arrayContaining([
expect.objectContaining({ method: "GET" }),
expect.objectContaining({ method: "HEAD" }),
expect.objectContaining({ method: "OPTIONS" }),
expect.objectContaining({ method: "TRACE" }),
]),
});
expect(results[1]).toMatchObject({
views: expect.arrayContaining([
{ tool: "head_items", shape: "recorded", reason: "method-replay" },
{ tool: "options_items", shape: "recorded", reason: "method-replay" },
{ tool: "trace_items", shape: "recorded", reason: "method-replay" },
]),
});
expect(results[2]).toMatchObject({
reads: { state: 1, recorded: 3, recorded_reasons: { "method-replay": 3 } },
writes: { served: [], withheld: [] },
coverage: { examined: 4, total: 4, exhausted: true },
});
});
it("projects an environment manifest identically from retained, portable and file MCP Evidence", async () => {
const { client, session } = await connect(undefined, undefined, 8_192);
const { ajv, inputSchema, toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
const har = environmentManifestHar();
const request = har.log.entries.find(
(entry) => entry.request.postData,
)!.request;
request.postData!.text =
'{"__proto__":{"source":"recorded body value"},"constructor":"caller","name":1}';
request.bodySize = Buffer.byteLength(request.postData!.text);
const capture = environmentManifestCaptureFixture(har.log.entries);
const parent = analysisViewCaptureEvidence(capture);
expect(session.recordEvidence(parent).ok).toBe(true);
const evidencePath = join(
await createTestTempDirectory("rea-evidence-file-mcp-"),
"capture.json",
);
await writeFile(evidencePath, JSON.stringify(parent));
const view = {
kind: "environment-manifest",
template_rules: ["after-uid-literal", "opaque-token", "sibling-variance"],
};
const outputs = [];
for (const source of [
{ kind: "inline", evidence: parent },
{ kind: "retained-evidence", evidence_id: parent.evidence_id },
{ kind: "evidence-file", path: evidencePath },
]) {
expect(ajv.validate(inputSchema, { source, view })).toBe(true);
expect(
ajv.validate(inputSchema, {
source,
view: { ...view, template_rules: ["glob"] },
}),
).toBe(false);
const response = await client.callTool(
{
name: "inspect_analysis_view",
arguments: { source, view },
},
{ toolDefinition },
);
expect(response.isError).not.toBe(true);
const evidence = parseEvidence(response.structuredContent);
expect(evidence.confidence).toBe("inferred");
expect(evidence.normalized_result).toMatchObject({
kind: "environment-manifest",
name: "grafana-example",
templated_groups: 13,
tools: expect.arrayContaining([
expect.objectContaining({
body_shape: {
type: "object",
properties: {
["__proto__"]: "object",
constructor: "string",
name: "number",
},
},
}),
expect.objectContaining({
name: "get_plugins_settings_by_plugin_id",
path_template: "/api/plugins/{plugin_id}/settings",
}),
expect.objectContaining({
name: "get_folders_by_uid",
path_template: "/api/folders/{uid}",
}),
]),
});
expect(session.evidenceById(evidence.evidence_id)).toEqual(evidence);
for (const value of [
"probe folder",
"Main Org",
"JFIF",
"console.log",
"recorded body value",
])
expect(JSON.stringify(response)).not.toContain(value);
outputs.push(evidence.normalized_result);
}
expect(outputs[0]).toEqual(outputs[1]);
expect(outputs[2]).toEqual(outputs[0]);
// JSON Schema cannot express "absolute"; the tool refuses a relative path when called.
const relative = await client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "evidence-file", path: "capture.json" },
view,
},
});
expect(parseMcpToolError(relative).error.code).toBe("invalid_request");
await writeFile(evidencePath, JSON.stringify({ hello: 1 }));
const invalidFile = await client.callTool({
name: "inspect_analysis_view",
arguments: { source: { kind: "evidence-file", path: evidencePath }, view },
});
expect(parseMcpToolError(invalidFile).error).toMatchObject({
details: {
path: evidencePath,
reason: "wrong-kind",
content_issues: expect.arrayContaining([
{
path: ["evidence_id"],
reason: "missing_argument",
expected: "string",
},
]),
},
});
const hidden = createEvidence(
{
path: capture.artifact.path,
sha256: capture.artifact.sha256!,
format: "file",
},
{ id: "fixture", name: "fixture", version: "1" },
{
operation: "inspect_web_network_capture",
parameters: { sensitive_value_count: 1 },
result: capture,
confidence: "observed",
},
);
const refused = await client.callTool({
name: "inspect_analysis_view",
arguments: { source: { kind: "inline", evidence: hidden }, view },
});
const hiddenError = parseMcpToolError(refused).error;
expect(hiddenError.code).toBe("unsupported_target");
expect(hiddenError.remediation.action).toContain("sensitivity declarations");
expect(hiddenError.remediation.action).toContain("capture or summary view");
expect(hiddenError.remediation.action).not.toContain("target format");
expect(JSON.stringify(refused)).toContain("sensitive_values_unretained");
expect(JSON.stringify(refused)).not.toContain("/api/folders");
await client.ping();
});
it("pages retained raw array rows without losing the parent and refuses an oversized row", async () => {
const { client, session } = await connect();
const rows = [
{ from_address: "0x10", to_address: "0x20", source: "fixups" },
{ from_address: "0x18", to_address: "0x20", source: "fixups" },
{ from_address: "0x20", name: "x".repeat(1024 * 1024) },
];
const parent = createEvidence(
{ path: "/fixtures/raw-native", format: "mach-o", sha256: "e".repeat(64) },
{ id: "fixture", name: "Fixture", version: "1" },
{
operation: "xrefs",
parameters: { address: "0x20" },
result: ["0x10", "0x18", "0x20"],
rawResult: { references: { pointers: rows } },
},
);
expect(session.recordEvidence(parent).ok).toBe(true);
const call = (offset: number, limit: number) =>
client.callTool({
name: "inspect_analysis_view",
arguments: {
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
view: {
kind: "recorded-array",
path: ["references", "pointers"],
offset,
limit,
},
},
});
const first = await call(0, 10);
expect(first.isError).not.toBe(true);
const parsed = toolContract("inspect_analysis_view").outputSchema.parse(
first.structuredContent,
);
expect(parsed.normalized_result).toMatchObject({
kind: "recorded-array",
parent_evidence_id: parent.evidence_id,
source_provider: { id: "fixture", name: "Fixture", version: "1" },
source_analysis_profile_digest: null,
source_parameters: { address: "0x20" },
limitations: expect.arrayContaining([
expect.stringContaining(
"excluded from the parent operation's normalized result",
),
]),
rows: rows.slice(0, 2),
coverage: { examined: 2, total: 3, next_offset: 2 },
});
expect(parsed.evidence_links).toEqual([parent.evidence_id]);
const oversized = parseMcpToolError(await call(2, 1)).error;
expect(oversized.code).toBe("resource_constraint");
expect(oversized.remediation.action).toContain("1,048,576-byte");
expect((await call(0, 1)).isError).not.toBe(true);
});
it("directs oversized inline Evidence to a usable file source", async () => {
const { client } = await connect(undefined, undefined, 32);
const parent = analysisViewNativeEvidence();
const view = { kind: "native", facet: "procedure", offset: 0, limit: 1 };
const inline = await client.callTool({
name: "inspect_analysis_view",
arguments: { source: { kind: "inline", evidence: parent }, view },
});
const error = parseMcpToolError(inline).error;
expect(error.code).toBe("resource_constraint");
expect(error.remediation.action).toContain("evidence-file");
const root = await createTestTempDirectory("rea-view-input-capacity-");
const path = join(root, "evidence.json");
await writeFile(path, JSON.stringify(parent));
const fromFile = await client.callTool({
name: "inspect_analysis_view",
arguments: { source: { kind: "evidence-file", path }, view },
});
expect(fromFile.isError).not.toBe(true);
const parsed = toolContract("inspect_analysis_view").outputSchema.parse(
fromFile.structuredContent,
);
expect(parsed.normalized_result).toMatchObject({
parent_evidence_id: parent.evidence_id,
});
});
it.each([
{ queryBytes: 1024 * 1024, rowBytes: 0 },
{ queryBytes: 600_000, rowBytes: 600_000 },
])(
"pages a recorded row when its parent parameters do not fit",
async ({ queryBytes, rowBytes }) => {
const { client, session } = await connect();
const { toolDefinition } = await advertisedMcpToolSchemas(
client,
"inspect_analysis_view",
schemaValidation.assertions,
);
const parent = createEvidence(
{
path: "/fixtures/large-context",
format: "elf",
sha256: "f".repeat(64),
},
{ id: "fixture", name: "Fixture", version: "1" },
{
operation: "xrefs",
parameters: { query: "x".repeat(queryBytes) },
result: ["0x10"],
rawResult: {
values: [{ address: "0x10", data: "y".repeat(rowBytes) }],
},
},
);
expect(session.recordEvidence(parent).ok).toBe(true);
const response = await client.callTool(
{
name: "inspect_analysis_view",
arguments: {
source: {
kind: "retained-evidence",
evidence_id: parent.evidence_id,
},
view: {
kind: "recorded-array",
path: ["values"],
offset: 0,
limit: 1,
},
},
},
{ toolDefinition },
);
expect(response.isError).not.toBe(true);
const parsed = toolContract("inspect_analysis_view").outputSchema.parse(
response.structuredContent,
);
expect(parsed.normalized_result).toMatchObject({
kind: "recorded-array",
parent_evidence_id: parent.evidence_id,
source_provider: { id: "fixture", name: "Fixture", version: "1" },
source_parameters: null,
limitations: expect.arrayContaining([
expect.stringContaining("omitted to fit the page allowance"),
]),
rows: [{ address: "0x10", data: "y".repeat(rowBytes) }],
});
},
);