mirror of
https://github.com/morluto/rea.git
synced 2026-10-12 02:19:24 +00:00
Deliver complete Evidence directly through MCP with required nullable analysis profiles and immutable per-server delivery settings. Bind selected environments at construction and require typed cleanup outcomes with retained retry ownership. Remove test-only routing, duplicate session and snapshot metadata, producer-field repairs, and ambiguous provider arguments. Separate artifact byte identity from occurrence classification and retain typed source-map and partial native facts across CLI, MCP, and verifier consumers. BREAKING CHANGE: obsolete Evidence envelopes, session aliases, incomplete snapshots, and missing normalized producer facts are no longer accepted.
118 lines
4.3 KiB
TypeScript
118 lines
4.3 KiB
TypeScript
import { expect, it } from "vitest";
|
|
import {
|
|
webSourceLocationArgs as args,
|
|
webSourceLocationFixture,
|
|
webSourceMapDecoderFixture as decoder,
|
|
} from "../../tests/fixtures/webSourceLocation.js";
|
|
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
|
import { ok } from "../domain/result.js";
|
|
import { webSourceLocationResultSchema } from "../domain/webSourceLocation.js";
|
|
import { WebSourceLocationService } from "./WebSourceLocationService.js";
|
|
import type { WebSourceMapPort } from "./WebSourceLocationPorts.js";
|
|
|
|
const service = (data = webSourceLocationFixture(), port = decoder) =>
|
|
new WebSourceLocationService({ load: () => Promise.resolve(ok(data)) }, port);
|
|
it.each([
|
|
{ ...args, manifest_path: "relative.json" },
|
|
{ ...args, script_index: -1 },
|
|
{ ...args, source_map: { ...args.source_map, path: "relative.map" } },
|
|
{ ...args, source_map: { ...args.source_map, url: "relative.map" } },
|
|
{ ...args, generated_position: { line: 0, column: 0 } },
|
|
])(
|
|
"rejects invalid selected context before acquiring artifacts: %j",
|
|
async (input) => {
|
|
const response = await new WebSourceLocationService(
|
|
{
|
|
load: () => {
|
|
throw new Error("must not acquire");
|
|
},
|
|
},
|
|
decoder,
|
|
).trace(input);
|
|
if (response.ok) throw new Error("expected invalid input");
|
|
expect(projectAnalysisError(response.error).code).toBe("invalid_request");
|
|
},
|
|
);
|
|
it.each([
|
|
"file:///analysis/app.map",
|
|
"webpack:///bundle/app.map",
|
|
"https://selected-user:[email protected]/maps/app.map",
|
|
])(
|
|
"retains an absolute inert map context without fetching: %s",
|
|
async (url) => {
|
|
const fixture = webSourceLocationFixture();
|
|
const data = { ...fixture, sourceMap: { ...fixture.sourceMap, url } };
|
|
const response = await service(data).trace({
|
|
...args,
|
|
source_map: { ...args.source_map, url },
|
|
});
|
|
if (!response.ok) throw response.error;
|
|
expect(
|
|
webSourceLocationResultSchema.parse(response.value.normalized_result)
|
|
.url_context,
|
|
).toBe(url);
|
|
},
|
|
);
|
|
it.each(["source", "map", "map-path", "map-url"])(
|
|
"rejects changed artifact identity before decoding: %s",
|
|
async (variant) => {
|
|
const fixture = webSourceLocationFixture();
|
|
const data = {
|
|
...fixture,
|
|
source: variant === "source" ? "different" : fixture.source,
|
|
sourceMap: { ...fixture.sourceMap },
|
|
};
|
|
if (variant === "map") data.sourceMap.text += " ";
|
|
if (variant === "map-path") data.sourceMap.file.path = "/other.map";
|
|
if (variant === "map-url") data.sourceMap.url = "https://other.test/";
|
|
const response = await service(data, {
|
|
trace: () => {
|
|
throw new Error("must not decode");
|
|
},
|
|
}).trace(args);
|
|
if (response.ok) throw new Error("expected changed identity failure");
|
|
expect(response.error._tag).toBe("AnalysisOutputError");
|
|
},
|
|
);
|
|
it.each(["digest", "url", "point"])(
|
|
"rejects changed codec identity: %s",
|
|
async (variant) => {
|
|
const port: WebSourceMapPort = {
|
|
trace: async (input) => {
|
|
const decoded = await decoder.trace(input);
|
|
if (!decoded.ok) return decoded;
|
|
const report = decoded.value;
|
|
if (variant === "digest") report.source_map_sha256 = "f".repeat(64);
|
|
if (variant === "url") report.url_context = "https://other.test/";
|
|
if (variant === "point") report.lookup.requested.column += 1;
|
|
return Promise.resolve(ok(report));
|
|
},
|
|
};
|
|
const response = await service(undefined, port).trace(args);
|
|
if (response.ok) throw new Error("expected changed codec identity failure");
|
|
expect(response.error._tag).toBe("AnalysisOutputError");
|
|
},
|
|
);
|
|
it("honors cancellation both before acquisition and across decoder completion", async () => {
|
|
const first = new AbortController();
|
|
first.abort();
|
|
const response = await new WebSourceLocationService(
|
|
{
|
|
load: () => {
|
|
throw new Error("must not acquire");
|
|
},
|
|
},
|
|
decoder,
|
|
).trace(args, { signal: first.signal });
|
|
expect(response.ok).toBe(false);
|
|
const controller = new AbortController();
|
|
const late = await service(undefined, {
|
|
trace: (input) => {
|
|
controller.abort();
|
|
return decoder.trace(input);
|
|
},
|
|
}).trace(args, { signal: controller.signal });
|
|
if (late.ok) throw new Error("expected cancellation");
|
|
expect(late.error._tag).toBe("AnalysisCancelledError");
|
|
});
|