Files
reverse-engineering-anything/tests/acceptance/analysisSnapshotDiagnostics.test.ts
T
gensokyo-devandgensokyo-dev 4ad1eb5beb fix(snapshot): locate entry diagnostics by collection and index
Each snapshot entry is validated alone, so its schema issue path started at
the entry. Prefix it with entries or workflow_entries and the entry index so
the reason names the entry to repair, and match the header case's issue
count without freezing the whole sentence.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:06:23 +01:00

76 lines
2.9 KiB
TypeScript

import { readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { TextReader, Uint8ArrayWriter, ZipWriter } from "@zip.js/zip.js";
import { expect } from "vitest";
import { z } from "zod";
import { analysisErrorProjectionSchema } from "../../src/contracts/errorSchemas.js";
import { parseMcpToolError } from "../fixtures/mcpToolError.js";
import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js";
import { cliTest } from "../support/cli/cliFixture.js";
cliTest(
"preserves selected snapshot schema reasons through compiled CLI and stdio MCP",
async ({ cli }) => {
const root = await createTestTempDirectory(
"rea-snapshot-diagnostic-boundary-",
);
const target = join(root, "target.zip");
const snapshot = join(root, "selected.json");
const writer = new ZipWriter(new Uint8ArrayWriter());
await writer.add("entry.txt", new TextReader("inert"), { level: 0 });
const targetBytes = await writer.close();
await writeFile(target, targetBytes);
const call = await cli.sharedMcpCall!();
for (const [document, field] of [
[{ entries: [], workflow_entries: [] }, "target"],
[{ entries: [{}], workflow_entries: [] }, "entries.0.query_id"],
[{ entries: [], workflow_entries: [{}] }, "workflow_entries.0.query_id"],
] as const) {
const encoded = JSON.stringify(document);
await writeFile(snapshot, encoded);
const output = await cli.run({
arguments: [
"analyze",
target,
"--snapshot",
snapshot,
"--format",
"json",
],
});
expect(output.exitCode, output.stderr).toBe(1);
const { error: description, ...projection } = z
.record(z.string(), z.unknown())
.parse(output.json);
expect(description).toBe("Analysis failed");
const cliError = analysisErrorProjectionSchema.parse(projection);
const response = await call("open_binary", {
path: target,
snapshot_path: snapshot,
});
const mcpError = parseMcpToolError(response).error;
for (const error of [cliError, mcpError]) {
expect(error).toMatchObject({
code: "evidence_integrity_mismatch",
category: "integrity_mismatch",
retryable: false,
details: { reason: expect.stringContaining(`at ${field}:`) },
});
expect(error).not.toHaveProperty("cause");
expect(error).not.toHaveProperty("stack");
if (field === "target")
expect(error.details?.reason).toMatch(
/ at target: .+ \(2 more issues\)$/,
);
}
// MCP adds open-session facts; the snapshot reason must match exactly.
expect(mcpError.details).toMatchObject(cliError.details ?? {});
expect(await readFile(snapshot, "utf8")).toBe(encoded);
}
expect(
Buffer.compare(await readFile(target), Buffer.from(targetBytes)),
).toBe(0);
},
);