Files
rea/tests/process-global/cliSelectedEnvironment.test.ts
morluto 63bf91405c refactor!: enforce canonical evidence and provider boundaries
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.
2026-10-09 20:18:52 +08:00

99 lines
3.4 KiB
TypeScript

import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import { createCli } from "../../src/cli.js";
import { parseEvidence } from "../../src/domain/evidence.js";
import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js";
const initialExitCode = process.exitCode;
afterEach(() => {
vi.unstubAllEnvs();
process.exitCode = initialExitCode;
});
const serve = async (
cli: ReturnType<typeof createCli>,
arguments_: string[],
) => {
let stdout = "";
await cli.serve([...arguments_, "--json"], {
env: {},
stdout: (text) => {
stdout += text;
},
exit: () => undefined,
});
const result: unknown = JSON.parse(stdout);
return result;
};
describe("CLI selected environment", () => {
it("retains the selected binary provider and launcher after caller and ambient environment changes", async () => {
vi.stubEnv("REA_ANALYSIS_PROVIDER", "ambient-provider");
vi.stubEnv("HOPPER_LAUNCHER_PATH", "/ambient/hopper");
const environment = {
REA_ANALYSIS_PROVIDER: "selected-provider",
HOPPER_LAUNCHER_PATH: process.execPath,
};
const cli = createCli(environment);
environment.REA_ANALYSIS_PROVIDER = "changed-provider";
environment.HOPPER_LAUNCHER_PATH = "/changed/hopper";
const root = await createTestTempDirectory("rea-cli-selected-env-");
const target = join(root, "fixture.hop");
await writeFile(target, "fixture");
for (const command of [
["decompile", target, "main"],
["read-bytes", target, "0x1000"],
]) {
const result = await serve(cli, command);
expect(result).toMatchObject({
code: "capability_unavailable",
details: { requested_provider_id: "selected-provider" },
});
}
for (const command of ["providers", "capabilities"]) {
const result = await serve(cli, [command]);
expect(result).toMatchObject({
analysis_provider_candidates: expect.arrayContaining([
expect.objectContaining({
provider: expect.objectContaining({ id: "hopper" }),
availability: expect.objectContaining({
diagnostics: expect.objectContaining({
launcher_path: process.execPath,
}),
}),
}),
]),
});
}
});
it("does not borrow invalid ambient settings or capture inherited environment in artifact Evidence", async () => {
vi.stubEnv("REA_GHIDRA_STARTUP_TIMEOUT_MS", "ambient-invalid-setting");
vi.stubEnv(
"REA_AMBIENT_CAPTURE_SENTINEL",
"ambient-value-must-not-be-captured",
);
const root = await createTestTempDirectory("rea-cli-isolated-artifact-");
const target = join(root, "empty.zip");
await writeFile(
target,
Buffer.from("504b0506000000000000000000000000000000000000", "hex"),
);
const cli = createCli({
REA_SELECTED_CAPTURE_SENTINEL: "selected-value-must-not-be-captured",
});
const result = await serve(cli, ["inspect-artifact", target]);
const evidence = parseEvidence(result);
expect(evidence.operation).toBe("inspect_artifact");
expect(evidence.subject?.local_path).toBe(target);
expect(evidence.environment).toBeNull();
const serialized = JSON.stringify(evidence);
expect(serialized).not.toContain("CAPTURE_SENTINEL");
expect(serialized).not.toContain("value-must-not-be-captured");
});
});