mirror of
https://github.com/morluto/rea
synced 2026-10-25 22:08:11 -04:00
refactor(process): remove the redundant scenario parsing alias
Use the authoritative scenario schema directly in all 25 test consumers. Preserve unknown-input annotations and every lifecycle, permission, normalization, identity and cleanup assertion; retain the separate branded capture validation boundary.
This commit is contained in:
@@ -19,7 +19,7 @@ import { PROCESS_PROVIDER } from "../domain/process/processEvidenceProvider.js";
|
||||
import { parseProcessCapture } from "../domain/process/processCaptureParsing.js";
|
||||
import {
|
||||
digestProcessCommitment,
|
||||
parseProcessScenario,
|
||||
processScenarioSchema,
|
||||
processComparisonContract,
|
||||
processScenarioCommitment,
|
||||
} from "../domain/process/processScenario.js";
|
||||
@@ -169,7 +169,7 @@ describe("reconstruction obligation candidates", () => {
|
||||
});
|
||||
|
||||
it("does not bind an unknown process image to a packaged artifact obligation", () => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "/path/whose-launch-identity-is-unknown",
|
||||
});
|
||||
const base = emptyUnverifiedProcessCapture();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect, it } from "vitest";
|
||||
import {
|
||||
parseProcessScenario,
|
||||
processScenarioSchema,
|
||||
processScenarioCommitment,
|
||||
processComparisonContract,
|
||||
digestProcessCommitment,
|
||||
@@ -332,7 +332,7 @@ it.each([
|
||||
|
||||
it("refuses mixed terminal observation versions even with PID and port rules disabled", () => {
|
||||
const base = emptyCapture();
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "/usr/bin/true",
|
||||
normalization: { pids: false, ports: false },
|
||||
});
|
||||
|
||||
@@ -5,7 +5,6 @@ import { Ajv2020 } from "ajv/dist/2020.js";
|
||||
import { SESSION_TOOL_CONTRACTS } from "../../contracts/sessionToolContracts.js";
|
||||
import {
|
||||
digestProcessCommitment,
|
||||
parseProcessScenario,
|
||||
PROCESS_TERMINAL_CELL_BUDGET,
|
||||
processComparisonContract,
|
||||
processScenarioCommitment,
|
||||
@@ -32,7 +31,7 @@ it("advertises the same unsupported PTY environment name as runtime admission",
|
||||
});
|
||||
|
||||
it("defaults the finalization interval to zero without changing committed identity", () => {
|
||||
const scenario = parseProcessScenario(baseScenario);
|
||||
const scenario = processScenarioSchema.parse(baseScenario);
|
||||
|
||||
expect(scenario, "parsed scenario carries the default").toMatchObject({
|
||||
finalization_ms: 0,
|
||||
@@ -49,13 +48,13 @@ it("defaults the finalization interval to zero without changing committed identi
|
||||
|
||||
it("accepts an explicit zero finalization interval", () => {
|
||||
expect(
|
||||
parseProcessScenario({ ...baseScenario, finalization_ms: 0 }),
|
||||
processScenarioSchema.parse({ ...baseScenario, finalization_ms: 0 }),
|
||||
"zero is the immediate-kill default, not an invalid budget",
|
||||
).toMatchObject({ finalization_ms: 0 });
|
||||
});
|
||||
|
||||
it("commits a positive finalization interval in both identity projections", () => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
...baseScenario,
|
||||
finalization_ms: 500,
|
||||
});
|
||||
@@ -74,14 +73,14 @@ it.each([-1, 1.5, Number.MAX_SAFE_INTEGER + 1])(
|
||||
"rejects the finalization interval %j",
|
||||
(finalization_ms) => {
|
||||
expect(() =>
|
||||
parseProcessScenario({ ...baseScenario, finalization_ms }),
|
||||
processScenarioSchema.parse({ ...baseScenario, finalization_ms }),
|
||||
).toThrow();
|
||||
},
|
||||
);
|
||||
|
||||
it("accepts a combined lifecycle budget up to the safe-integer limit", () => {
|
||||
const limit = Number.MAX_SAFE_INTEGER;
|
||||
const accepted = parseProcessScenario({
|
||||
const accepted = processScenarioSchema.parse({
|
||||
...baseScenario,
|
||||
timeout_ms: limit - 100,
|
||||
idle_timeout_ms: 1,
|
||||
@@ -94,7 +93,7 @@ it("accepts a combined lifecycle budget up to the safe-integer limit", () => {
|
||||
"a total exactly at the representable limit is accepted",
|
||||
).toBe(limit);
|
||||
expect(
|
||||
parseProcessScenario(baseScenario),
|
||||
processScenarioSchema.parse(baseScenario),
|
||||
"the default scenario stays far below the limit",
|
||||
).toMatchObject({ timeout_ms: 30_000, settle_ms: 100, finalization_ms: 0 });
|
||||
});
|
||||
@@ -119,7 +118,11 @@ it.each([
|
||||
],
|
||||
])("rejects %s with a representability message", (_label, budget) => {
|
||||
const parse = () =>
|
||||
parseProcessScenario({ ...baseScenario, idle_timeout_ms: 1, ...budget });
|
||||
processScenarioSchema.parse({
|
||||
...baseScenario,
|
||||
idle_timeout_ms: 1,
|
||||
...budget,
|
||||
});
|
||||
|
||||
expect(parse, "the combined budget is rejected").toThrow(
|
||||
"timeout_ms + finalization_ms + settle_ms",
|
||||
@@ -130,7 +133,7 @@ it.each([
|
||||
});
|
||||
|
||||
it("keeps scenario identity without finalization while versioning corrected port semantics", () => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "/usr/bin/true",
|
||||
arguments: ["-x"],
|
||||
working_directory: "/tmp",
|
||||
@@ -172,7 +175,9 @@ it("keeps scenario identity without finalization while versioning corrected port
|
||||
});
|
||||
|
||||
it("admits the default and the exact combined terminal-cell budget", () => {
|
||||
expect(parseProcessScenario({ executable: "/bin/true" }).terminal).toEqual({
|
||||
expect(
|
||||
processScenarioSchema.parse({ executable: "/bin/true" }).terminal,
|
||||
).toEqual({
|
||||
columns: 80,
|
||||
rows: 24,
|
||||
scrollback: 1_000,
|
||||
|
||||
@@ -347,7 +347,3 @@ const eventsOutOfOrder = (
|
||||
|
||||
/** Parsed instructions and resource bounds for one process experiment. */
|
||||
export type ProcessScenario = z.infer<typeof processScenarioSchema>;
|
||||
|
||||
/** Parse untrusted process scenario input and apply safe default budgets. */
|
||||
export const parseProcessScenario = (input: unknown): ProcessScenario =>
|
||||
processScenarioSchema.parse(input);
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { expect, it } from "vitest";
|
||||
import { parseProcessScenario } from "../../domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../domain/process/processScenario.js";
|
||||
import { createTestTempDirectory } from "../../../tests/fixtures/temporaryDirectory.js";
|
||||
import { snapshotRoots } from "./FilesystemSnapshot.js";
|
||||
import { classifyFilesystemEffects } from "./ProcessFilesystemEffects.js";
|
||||
@@ -27,7 +27,7 @@ it.each(["after", "before"] as const)(
|
||||
await writeFile(join(root, "a1.txt"), "first");
|
||||
await writeFile(join(root, "a2.txt"), "second");
|
||||
await writeFile(join(root, "z.txt"), "target");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -68,7 +68,7 @@ it("preserves proven deletion in an exhausted root while another root is partial
|
||||
await writeFile(join(complete, "removed.txt"), "removed");
|
||||
await writeFile(join(partial, "first.txt"), "first");
|
||||
await writeFile(join(partial, "second.txt"), "second");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [complete, partial],
|
||||
@@ -88,7 +88,7 @@ it("preserves proven deletion in an exhausted root while another root is partial
|
||||
it("distinguishes unavailable content hashes from completed path enumeration", async () => {
|
||||
const root = await createTestTempDirectory("rea-fs-hash-coverage-");
|
||||
await writeFile(join(root, "removed.txt"), "larger than the byte budget");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -115,7 +115,7 @@ it.skipIf(process.platform === "win32")(
|
||||
await writeFile(visible, "visible");
|
||||
await mkdir(blocked);
|
||||
await chmod(blocked, 0);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -155,7 +155,7 @@ it.skipIf(process.platform === "win32")(
|
||||
await writeFile(unreadable, "permission denied");
|
||||
await writeFile(readable, "still observed");
|
||||
await chmod(unreadable, 0);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -219,7 +219,7 @@ it.each([
|
||||
const file = join(root, "b.txt");
|
||||
await writeFile(file, "before");
|
||||
if (beforeOmitted) await writeFile(budgetFile, "budget");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -255,7 +255,7 @@ it("preserves observed content and metadata changes without treating missing has
|
||||
const root = await createTestTempDirectory("rea-fs-observed-changes-");
|
||||
for (const name of ["changed", "stable", "unhashed", "retyped"])
|
||||
await writeFile(join(root, name), "before");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -276,7 +276,7 @@ it("preserves observed content and metadata changes without treating missing has
|
||||
expect(effects.find(({ path }) => path === "root_0:retyped")?.status).toBe(
|
||||
"modified",
|
||||
);
|
||||
const noHashes = parseProcessScenario({
|
||||
const noHashes = processScenarioSchema.parse({
|
||||
...scenario,
|
||||
limits: { file_bytes: 1 },
|
||||
});
|
||||
@@ -300,7 +300,7 @@ it.skipIf(process.platform === "win32")(
|
||||
const root = await createTestTempDirectory("rea-fs-mode-change-");
|
||||
const file = join(root, "file");
|
||||
await writeFile(file, "before", { mode: 0o600 });
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [file],
|
||||
@@ -324,7 +324,7 @@ it.skipIf(process.platform === "win32")(
|
||||
await writeFile(join(root, "b.txt"), "unused");
|
||||
await symlink("a.txt", join(root, "stable-link"));
|
||||
await symlink("a.txt", join(root, "moved-link"));
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -355,7 +355,7 @@ it.skipIf(process.platform === "win32")(
|
||||
// Equal length, so only the target spelling distinguishes the links;
|
||||
// "bbb" does not exist, so the replacement link is broken.
|
||||
await symlink("aaa/../target", join(root, "link"));
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -381,7 +381,7 @@ it.skipIf(process.platform === "win32")(
|
||||
it("preserves creation when the selected root was observed missing before capture", async () => {
|
||||
const root = await createTestTempDirectory("rea-fs-missing-root-");
|
||||
const file = join(root, "created.txt");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [file],
|
||||
@@ -410,7 +410,7 @@ it.skipIf(process.platform === "win32")(
|
||||
await mkdir(join(root, "denied"));
|
||||
await chmod(join(root, "denied"), 0);
|
||||
const scenarioFor = (path: string) =>
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [path],
|
||||
@@ -480,7 +480,7 @@ it.skipIf(process.platform === "win32")(
|
||||
await writeFile(join(listed, "child.txt"), "child");
|
||||
// Read without search permission: names enumerate, lookups are denied.
|
||||
await chmod(listed, 0o444);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -509,7 +509,7 @@ it.skipIf(process.platform === "win32")(
|
||||
"keeps an admitted root behind a symlink loop unobserved",
|
||||
async () => {
|
||||
const root = await createTestTempDirectory("rea-fs-root-loop-");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [join(root, "loop", "child")],
|
||||
@@ -532,7 +532,7 @@ it.skipIf(process.platform === "win32")(
|
||||
const link = join(root, "link");
|
||||
await mkdir(target);
|
||||
await symlink(target, link);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
filesystem_observation_paths: [link],
|
||||
});
|
||||
@@ -561,7 +561,7 @@ it.skipIf(process.platform === "win32")(
|
||||
|
||||
it("allocates the observer directory before baseline and excludes it before entry accounting", async () => {
|
||||
const root = await createTestTempDirectory("rea-observer-filesystem-");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
filesystem_observation_paths: [root],
|
||||
limits: { files: 1 },
|
||||
@@ -611,7 +611,7 @@ it.skipIf(process.platform === "win32")(
|
||||
"target",
|
||||
);
|
||||
await symlink(physicalParent, alias);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
filesystem_observation_paths: [join(alias, "root")],
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from "../../domain/analysisErrorBase.js";
|
||||
import { projectAnalysisError } from "../../domain/analysisErrorProjection.js";
|
||||
import { emptyProcessCapture } from "../../domain/process/processCapture.fixture.js";
|
||||
import { parseProcessScenario } from "../../domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../domain/process/processScenario.js";
|
||||
import { ProcessCaptureSnapshotFailure } from "./FilesystemSnapshot.js";
|
||||
import { prepareProcessCapture } from "./ProcessCaptureLifecycle.js";
|
||||
|
||||
@@ -54,7 +54,7 @@ it.each(["EACCES", "EPERM"] as const)(
|
||||
snapshot,
|
||||
cleanupLeases: [lease],
|
||||
});
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
filesystem_observation_paths: ["/fixture/absent", selected],
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { expect, it, vi } from "vitest";
|
||||
import type { IPty } from "@lydell/node-pty";
|
||||
|
||||
import { parseProcessScenario } from "../../domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../domain/process/processScenario.js";
|
||||
import type { ProcessCaptureFinalization } from "../../domain/process/processCapture.js";
|
||||
import { awaitTerminalExit } from "./ProcessCaptureLifecycle.js";
|
||||
import type { ProcessTimer } from "./ProcessTimer.js";
|
||||
@@ -75,7 +75,7 @@ const start = (
|
||||
) =>
|
||||
awaitTerminalExit({
|
||||
terminal: fake.terminal,
|
||||
scenario: parseProcessScenario({
|
||||
scenario: processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
idle_timeout_ms: 10_000,
|
||||
...scenario,
|
||||
|
||||
@@ -8,7 +8,7 @@ import { buildCaptureResult } from "./ProcessCaptureLifecycle.js";
|
||||
import { isInitializedPtyRoot } from "./ProcessSampling.js";
|
||||
import { readLinuxChildren } from "./LinuxProcessSampling.js";
|
||||
import { TerminalRenderer } from "./TerminalRenderer.js";
|
||||
import { parseProcessScenario } from "../../domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../domain/process/processScenario.js";
|
||||
import type { ProcessCapture } from "../../domain/process/processCaptureParsing.js";
|
||||
import type {
|
||||
FilesystemCoverage,
|
||||
@@ -143,7 +143,7 @@ it("preserves rendered observation order instead of timestamp sorting", () => {
|
||||
coverage: emptyFilesystemCoverage(),
|
||||
},
|
||||
truncationDetails: truncationDetails([], renderedFrames, []),
|
||||
scenario: parseProcessScenario(base),
|
||||
scenario: processScenarioSchema.parse(base),
|
||||
rootPid: 1,
|
||||
samplingPartial: false,
|
||||
renderedFrames,
|
||||
@@ -179,7 +179,7 @@ it("marks redacted scripted input as an interaction unknown", () => {
|
||||
coverage: emptyFilesystemCoverage(),
|
||||
},
|
||||
truncationDetails: truncationDetails([], [], []),
|
||||
scenario: parseProcessScenario({
|
||||
scenario: processScenarioSchema.parse({
|
||||
...base,
|
||||
events: [{ type: "input", at_ms: 0, data: "secret", sensitive: true }],
|
||||
}),
|
||||
@@ -278,7 +278,7 @@ it("cancels filesystem snapshots before traversing declared roots", async () =>
|
||||
const controller = new AbortController();
|
||||
controller.abort();
|
||||
const failure: unknown = await snapshotRoots(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
...base,
|
||||
filesystem_observation_paths: ["/tmp"],
|
||||
}),
|
||||
@@ -330,7 +330,7 @@ it.each(["symlink_not_followed", "observer_owned"] as const)(
|
||||
filesystem_before: coverage,
|
||||
filesystem_after: coverage,
|
||||
},
|
||||
scenario: parseProcessScenario({
|
||||
scenario: processScenarioSchema.parse({
|
||||
...base,
|
||||
filesystem_observation_paths: ["/selected"],
|
||||
}),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { expect, it } from "vitest";
|
||||
import type { IPty } from "@lydell/node-pty";
|
||||
|
||||
import { parseProcessScenario } from "../../domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../domain/process/processScenario.js";
|
||||
import { AnalysisResourceConstraintError } from "../../domain/analysisErrorCore.js";
|
||||
import { createProcessIdentifierLookup } from "./ProcessNormalization.js";
|
||||
import type {
|
||||
@@ -19,7 +19,7 @@ it("omits an expanding chunk whole and retains a later smaller normalized chunk"
|
||||
return { dispose: () => undefined };
|
||||
},
|
||||
} as unknown as IPty;
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
limits: { output_bytes: 1_000 },
|
||||
normalization: {
|
||||
@@ -78,7 +78,7 @@ it.each([false, true])(
|
||||
return { dispose: () => undefined };
|
||||
},
|
||||
} as unknown as IPty;
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
limits: { output_bytes: overBudget ? 4 : 1000 },
|
||||
normalization: {
|
||||
@@ -147,7 +147,7 @@ it("retains PTY chunk boundaries when two output messages arrive fragmented", ()
|
||||
return { dispose: () => undefined };
|
||||
},
|
||||
} as unknown as IPty;
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
normalization: { paths: false, pids: false, ports: false },
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
normalizeProcessSamples,
|
||||
normalizeProcessText,
|
||||
} from "./ProcessNormalization.js";
|
||||
import { parseProcessScenario } from "../../domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../domain/process/processScenario.js";
|
||||
|
||||
const rootPid = 41_010;
|
||||
const samples = Object.freeze(
|
||||
@@ -67,7 +67,7 @@ const scenario = (normalization: {
|
||||
readonly replacement: string;
|
||||
}[];
|
||||
}) =>
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: "/usr/bin/node",
|
||||
working_directory: "/workspace",
|
||||
normalization: {
|
||||
@@ -294,7 +294,7 @@ it("reuses matchers while observing the terminal PID after launch", () => {
|
||||
});
|
||||
|
||||
it("keeps equal-path priority and replacement aliases local to each capture", () => {
|
||||
const declared = parseProcessScenario({
|
||||
const declared = processScenarioSchema.parse({
|
||||
executable: "/selected/tool",
|
||||
working_directory: "/selected",
|
||||
filesystem_observation_paths: ["/selected", "<working-directory>"],
|
||||
@@ -485,7 +485,7 @@ it("normalizes representative process identities and preserves null, zero, and u
|
||||
});
|
||||
|
||||
it("normalizes nested paths once using the most specific selected identity", () => {
|
||||
const declared = parseProcessScenario({
|
||||
const declared = processScenarioSchema.parse({
|
||||
executable: "/workspace/project/bin/program",
|
||||
working_directory: "/workspace/project",
|
||||
filesystem_observation_paths: [
|
||||
@@ -507,7 +507,7 @@ it("normalizes nested paths once using the most specific selected identity", ()
|
||||
});
|
||||
|
||||
it("treats path metacharacters literally while preferring nested observed roots", () => {
|
||||
const declared = parseProcessScenario({
|
||||
const declared = processScenarioSchema.parse({
|
||||
executable: "/selected/[tool]+",
|
||||
working_directory: "/selected",
|
||||
filesystem_observation_paths: [
|
||||
@@ -529,7 +529,7 @@ it("treats path metacharacters literally while preferring nested observed roots"
|
||||
});
|
||||
|
||||
it("does not give a selected executable identity to a sibling filename", () => {
|
||||
const declared = parseProcessScenario({
|
||||
const declared = processScenarioSchema.parse({
|
||||
executable: "/tmp/process-paths/original/tool",
|
||||
working_directory: "/tmp/process-paths",
|
||||
normalization: { paths: true, pids: false, ports: false, patterns: [] },
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
resolveExecutable,
|
||||
resolveProcessScenarioRuntimePaths,
|
||||
} from "./ProcessScenarioRuntimeValidation.js";
|
||||
import { parseProcessScenario } from "../../domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../domain/process/processScenario.js";
|
||||
import { createTestTempDirectory } from "../../../tests/fixtures/temporaryDirectory.js";
|
||||
|
||||
it.skipIf(process.platform === "win32")(
|
||||
@@ -33,7 +33,7 @@ it.skipIf(process.platform === "win32")(
|
||||
await symlink(process.execPath, selected);
|
||||
await expect(resolveExecutable(command, root, bin)).resolves.toBe(selected);
|
||||
const resolved = await resolveProcessScenarioRuntimePaths(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: command,
|
||||
working_directory: root,
|
||||
environment: { PATH: bin },
|
||||
@@ -64,7 +64,7 @@ it("resolves a Windows executable through the canonical PATH spelling", async ()
|
||||
await mkdir(ambient);
|
||||
await writeFile(join(selected, "tool.exe"), "");
|
||||
await chmod(join(selected, "tool.exe"), 0o644);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "tool.exe",
|
||||
working_directory: root,
|
||||
environment: { Path: selected },
|
||||
@@ -200,12 +200,10 @@ const deniedFixture = async () => {
|
||||
return { root, denied, tool };
|
||||
};
|
||||
|
||||
const runtimePathOutcome = async (
|
||||
scenario: Parameters<typeof parseProcessScenario>[0],
|
||||
): Promise<unknown> => {
|
||||
const runtimePathOutcome = async (scenario: unknown): Promise<unknown> => {
|
||||
try {
|
||||
return await resolveProcessScenarioRuntimePaths(
|
||||
parseProcessScenario(scenario),
|
||||
processScenarioSchema.parse(scenario),
|
||||
);
|
||||
} catch (cause: unknown) {
|
||||
return cause;
|
||||
@@ -291,11 +289,13 @@ it.skipIf(SKIP_PERMISSIONS)(
|
||||
);
|
||||
|
||||
const runtimePathFailure = async (
|
||||
scenario: Parameters<typeof parseProcessScenario>[0],
|
||||
scenario: unknown,
|
||||
): Promise<AnalysisInputError> => {
|
||||
let failure: unknown;
|
||||
try {
|
||||
await resolveProcessScenarioRuntimePaths(parseProcessScenario(scenario));
|
||||
await resolveProcessScenarioRuntimePaths(
|
||||
processScenarioSchema.parse(scenario),
|
||||
);
|
||||
} catch (cause: unknown) {
|
||||
failure = cause;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from "./ProcessCaptureError.js";
|
||||
import { AnalysisResourceConstraintError } from "../../domain/analysisErrorCore.js";
|
||||
import { projectAnalysisError } from "../../domain/analysisErrorProjection.js";
|
||||
import { parseProcessScenario } from "../../domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../domain/process/processScenario.js";
|
||||
import {
|
||||
createProcessCaptureObservationBuffer,
|
||||
resolveProcessResult,
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import { createProcessTerminalFinalizer } from "./ProcessTerminalObservation.js";
|
||||
|
||||
const createTerminalCleanupFixture = () => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
terminal: { columns: 80, rows: 4 },
|
||||
normalization: { paths: false, ports: false },
|
||||
@@ -157,7 +157,7 @@ it("retains completed terminal facts and the typed capacity failure through fina
|
||||
state: "available",
|
||||
value: rendered,
|
||||
});
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
limits: { output_bytes: 4 },
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ import { expect, it, vi } from "vitest";
|
||||
import { TerminalRenderer } from "./TerminalRenderer.js";
|
||||
import { ProcessCaptureResourceScope } from "./ProcessCaptureLifecycle.js";
|
||||
import { createBoundedProcessTextNormalizer } from "./ProcessNormalization.js";
|
||||
import { parseProcessScenario } from "../../domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../domain/process/processScenario.js";
|
||||
import type { BoundedProcessTextNormalization } from "./ProcessNormalization.js";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
@@ -128,7 +128,7 @@ it("omits rendered frames with unknown expanded size and keeps later bounded sta
|
||||
scrollback: 0,
|
||||
maxBytes: 1_000,
|
||||
normalize: createBoundedProcessTextNormalizer(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
normalization: {
|
||||
paths: false,
|
||||
@@ -259,7 +259,7 @@ it.each([1024, 2048])(
|
||||
scrollback: 0,
|
||||
maxBytes,
|
||||
normalize: createBoundedProcessTextNormalizer(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
normalization: { paths: false, pids: false, ports: false },
|
||||
}),
|
||||
@@ -285,7 +285,7 @@ it.each([1024, 2048])(
|
||||
|
||||
it("renders retained chunks once after late PID knowledge, preserving event times and resize order", async () => {
|
||||
let identifiers: readonly number[] = [100];
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
normalization: {
|
||||
paths: false,
|
||||
@@ -333,7 +333,7 @@ it("renders retained chunks once after late PID knowledge, preserving event time
|
||||
});
|
||||
|
||||
it("renders a bounded sequence of retained chunks and resizes", async () => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "unused",
|
||||
normalization: { paths: false, ports: false, pids: true, patterns: [] },
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { expect, it } from "vitest";
|
||||
|
||||
import { emptyUnverifiedProcessCapture } from "../../../src/domain/process/processCapture.fixture.js";
|
||||
import { parseProcessCapture } from "../../../src/domain/process/processCaptureParsing.js";
|
||||
import { parseProcessScenario } from "../../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
||||
import { createProcessCaptureEvidence } from "../../../src/application/process/ProcessEvidence.js";
|
||||
import { observeSettlement } from "../../../src/process/capture/ProcessCaptureLifecycle.js";
|
||||
|
||||
@@ -14,7 +14,7 @@ it.each([
|
||||
] as const)(
|
||||
"interprets the executable name using the captured %s host",
|
||||
(platform, expectedName) => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "/fixtures/directory\\program.exe",
|
||||
working_directory: process.cwd(),
|
||||
events: [],
|
||||
@@ -32,7 +32,7 @@ it.each([
|
||||
);
|
||||
|
||||
it("stamps process Evidence from the capture manifest host", () => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: process.cwd(),
|
||||
events: [],
|
||||
|
||||
@@ -14,13 +14,13 @@ import { compareProcessCaptures } from "../../../src/domain/process/processCompa
|
||||
import { parseProcessCapture } from "../../../src/domain/process/processCaptureParsing.js";
|
||||
import {
|
||||
digestProcessCommitment,
|
||||
parseProcessScenario,
|
||||
processScenarioSchema,
|
||||
processComparisonContract,
|
||||
processScenarioCommitment,
|
||||
} from "../../../src/domain/process/processScenario.js";
|
||||
|
||||
const captureEvidenceForSensitiveInput = (data: string) => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "/bin/echo",
|
||||
working_directory: "/tmp",
|
||||
events: [{ type: "input", at_ms: 0, data, sensitive: true }],
|
||||
@@ -60,7 +60,7 @@ const captureEvidenceForSensitiveInput = (data: string) => {
|
||||
};
|
||||
|
||||
const captureEvidenceForEnvironmentSecret = async (value: string) => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: "/bin/echo",
|
||||
working_directory: "/tmp",
|
||||
environment: { API_TOKEN: value },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect } from "vitest";
|
||||
|
||||
import { parseProcessScenario } from "../../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
||||
import { captureProcessScenario } from "../../../src/process/capture/ProcessHarness.js";
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
import { itWithCaptureCapability } from "./processCaptureCapability.js";
|
||||
@@ -13,7 +13,7 @@ itWithCaptureCapability(
|
||||
const reason = { request: "cancel after cleanup completed" };
|
||||
let cleanupReported = false;
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: ["--eval", "console.log('completed capture')"],
|
||||
working_directory: root,
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
observeLaunchedExecutable,
|
||||
observeSelectedExecutable,
|
||||
} from "../../../src/process/capture/ProcessCaptureLifecycle.js";
|
||||
import { parseProcessScenario } from "../../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
||||
import { emptyProcessCapture } from "../../../src/domain/process/processCapture.fixture.js";
|
||||
import { processSourceTruncated } from "../../../src/domain/process/processCaptureCoverage.js";
|
||||
import type { ProcessCapture } from "../../../src/domain/process/processCaptureParsing.js";
|
||||
@@ -140,7 +140,7 @@ itWithCaptureCapability(
|
||||
await mkdir(join(root, "reports"));
|
||||
await writeFile(join(root, "reports", "final.json"), payload);
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [
|
||||
"-e",
|
||||
@@ -187,7 +187,7 @@ itWithCaptureCapability(
|
||||
}, 10_000);
|
||||
try {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "hang"],
|
||||
working_directory: dirname(processFixture),
|
||||
@@ -226,7 +226,7 @@ itWithCaptureCapability(
|
||||
vi.setSystemTime(new Date("2026-01-02T00:00:00.000Z"));
|
||||
try {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "partial"],
|
||||
working_directory: dirname(processFixture),
|
||||
@@ -282,7 +282,7 @@ itWithCaptureCapability(
|
||||
let unownedPid: number | undefined;
|
||||
try {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "detached-cleanup", pidMarker],
|
||||
working_directory: root,
|
||||
@@ -374,7 +374,7 @@ itWithCaptureCapability(
|
||||
rm(path, { recursive: true, force: true }),
|
||||
};
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "partial"],
|
||||
working_directory: dirname(processFixture),
|
||||
@@ -492,7 +492,7 @@ itWithCaptureCapability(
|
||||
.digest("hex");
|
||||
try {
|
||||
const capturePromise = captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable,
|
||||
arguments: [processFixture, "ready-hang", readyMarker],
|
||||
working_directory: root,
|
||||
@@ -541,7 +541,7 @@ itWithCaptureCapability(
|
||||
await symlink("/etc/passwd", join(root, "escape"));
|
||||
try {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: "/usr/bin/true",
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -578,7 +578,7 @@ itWithCaptureCapability(
|
||||
"distinguishes timeout from cancellation and cleans both runs",
|
||||
async () => {
|
||||
const timedOut = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "hang"],
|
||||
working_directory: dirname(processFixture),
|
||||
@@ -606,7 +606,7 @@ itWithCaptureCapability(
|
||||
const controller = new AbortController();
|
||||
let reachedRunning = false;
|
||||
const cancelled = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "hang"],
|
||||
working_directory: dirname(processFixture),
|
||||
@@ -665,7 +665,7 @@ const captureFinalizationFixture = async (
|
||||
): Promise<{ readonly result: CaptureRun; readonly root: string }> => {
|
||||
const root = await createTestTempDirectory("rea-finalization-");
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [finalizationFixture, mode, root],
|
||||
working_directory: root,
|
||||
@@ -958,7 +958,7 @@ itWithCaptureCapability(
|
||||
};
|
||||
const root = await createTestTempDirectory("rea-finalization-host-");
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [finalizationFixture, "ignoring", root],
|
||||
working_directory: root,
|
||||
@@ -1032,7 +1032,7 @@ itWithCaptureCapability(
|
||||
});
|
||||
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [path],
|
||||
@@ -1066,7 +1066,7 @@ itWithCaptureCapability(
|
||||
return snapshot;
|
||||
};
|
||||
const resultPromise = captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [snapshotCancellationFixture, root],
|
||||
working_directory: dirname(snapshotCancellationFixture),
|
||||
@@ -1116,7 +1116,7 @@ itWithCaptureCapability(
|
||||
};
|
||||
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [join(obstruction, "child")],
|
||||
@@ -1139,7 +1139,7 @@ itWithCaptureCapability(
|
||||
"captures input, Unicode, and resize across PTY startup",
|
||||
async () => {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "interactive"],
|
||||
working_directory: dirname(processFixture),
|
||||
@@ -1177,7 +1177,7 @@ itWithCaptureCapability(
|
||||
"dispatches an external signal without depending on child startup output",
|
||||
async () => {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "hang"],
|
||||
working_directory: dirname(processFixture),
|
||||
@@ -1202,7 +1202,7 @@ itWithCaptureCapability(
|
||||
"buffers newline input until a silent PTY fixture is ready to read it",
|
||||
async () => {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "silent-interactive"],
|
||||
working_directory: dirname(processFixture),
|
||||
@@ -1238,7 +1238,7 @@ itWithCaptureCapability(
|
||||
"samples and cleans a source-owned child and grandchild process tree",
|
||||
async () => {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, "tree"],
|
||||
working_directory: dirname(processFixture),
|
||||
|
||||
@@ -8,7 +8,7 @@ import { captureProcessScenario } from "../../../src/process/capture/ProcessHarn
|
||||
import { createProcessCaptureEvidence } from "../../../src/application/process/ProcessEvidence.js";
|
||||
import {
|
||||
digestProcessCommitment,
|
||||
parseProcessScenario,
|
||||
processScenarioSchema,
|
||||
} from "../../../src/domain/process/processScenario.js";
|
||||
import { parseProcessCapture } from "../../../src/domain/process/processCaptureParsing.js";
|
||||
import { compareProcessCaptures } from "../../../src/domain/process/processComparison.js";
|
||||
@@ -37,7 +37,7 @@ itWithCaptureCapability(
|
||||
const command = "selected\\node";
|
||||
const selected = join(bin, command);
|
||||
await symlink(process.execPath, selected);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: command,
|
||||
working_directory: root,
|
||||
environment: { PATH: bin },
|
||||
@@ -69,7 +69,7 @@ itWithCaptureCapability(
|
||||
score: 20,
|
||||
});
|
||||
const original = `${report}\nlisten:8080\n`;
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
arguments: ["-e", `process.stdout.write(${JSON.stringify(original)})`],
|
||||
@@ -119,7 +119,7 @@ itWithCaptureCapability.each([
|
||||
"preserves literal replacement $replacement and rejects legacy comparison semantics",
|
||||
async ({ pattern, replacement, expected }) => {
|
||||
const root = await createTestTempDirectory("rea-process-literal-");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: ["-e", 'process.stdout.write("AB")'],
|
||||
working_directory: root,
|
||||
@@ -173,7 +173,7 @@ itWithLinuxCaptureCapability.each([false, true])(
|
||||
async (pids) => {
|
||||
const root = await createTestTempDirectory("rea-process-identifiers-");
|
||||
const identityPath = join(root, "identity.json");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [processFixture, identityPath],
|
||||
working_directory: root,
|
||||
@@ -241,7 +241,7 @@ itWithCaptureCapability(
|
||||
await symlink(process.execPath, executable);
|
||||
await mkdir(observed);
|
||||
const original = `${executable}\n${observed}/result\n${root}/log`;
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [observed],
|
||||
@@ -317,7 +317,7 @@ itWithCaptureCapability(
|
||||
await mkdir(join(root, "original"), { recursive: true });
|
||||
await symlink(process.execPath, executable);
|
||||
const sibling = `${executable}-helper`;
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable,
|
||||
working_directory: root,
|
||||
arguments: ["-e", `process.stdout.write(${JSON.stringify(sibling)})`],
|
||||
@@ -339,7 +339,7 @@ itWithCaptureCapability.each([false, true])(
|
||||
"normalizes a sampled child in raw and rendered terminal projections, pids=%s",
|
||||
async (pids) => {
|
||||
const root = await createTestTempDirectory("rea-sampled-terminal-pids-");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
arguments: [
|
||||
|
||||
@@ -5,13 +5,13 @@ import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
import { itWithCaptureCapability } from "./processCaptureCapability.js";
|
||||
|
||||
import { captureProcessScenario } from "../../../src/process/capture/ProcessHarness.js";
|
||||
import { parseProcessScenario } from "../../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
||||
|
||||
itWithCaptureCapability(
|
||||
"normalizes wide terminal cells without inventing blank cells",
|
||||
async () => {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: ["-e", 'process.stdout.write("界")'],
|
||||
terminal: { columns: 4, rows: 1, scrollback: 0 },
|
||||
@@ -54,7 +54,7 @@ itWithCaptureCapability(
|
||||
);
|
||||
try {
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: [script],
|
||||
working_directory: root,
|
||||
|
||||
@@ -16,7 +16,7 @@ import { analysisCliErrorEnvelopeSchema } from "../../../src/contracts/errorSche
|
||||
import { parseEvidence } from "../../../src/domain/evidence.js";
|
||||
import { compareProcessCaptures } from "../../../src/domain/process/processComparison.js";
|
||||
import { parseProcessCapture } from "../../../src/domain/process/processCaptureParsing.js";
|
||||
import { parseProcessScenario } from "../../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
||||
import { FINALIZED_PROCESS_CAPTURE_EXAMPLE } from "../../../src/domain/process/processCaptureExample.js";
|
||||
import { createServer } from "../../../src/server/createServer.js";
|
||||
import { createTestBinarySession } from "../../fixtures/binarySession.js";
|
||||
@@ -207,7 +207,7 @@ it("documents a finalization scenario and exit record that match the contract",
|
||||
throw new Error("Missing finalization examples");
|
||||
|
||||
expect(
|
||||
parseProcessScenario(JSON.parse(scenario)).finalization_ms,
|
||||
processScenarioSchema.parse(JSON.parse(scenario)).finalization_ms,
|
||||
"the documented scenario is accepted and carries the interval",
|
||||
).toBe(1_500);
|
||||
expect(
|
||||
@@ -225,7 +225,7 @@ itWithCaptureCapability.each(["cli", "mcp"] as const)(
|
||||
?.match(/```json\n([\s\S]*?)\n```/u)?.[1];
|
||||
if (example === undefined)
|
||||
throw new Error("Missing report capture example");
|
||||
const scenario = parseProcessScenario(JSON.parse(example));
|
||||
const scenario = processScenarioSchema.parse(JSON.parse(example));
|
||||
const root = await createTestTempDirectory("rea-full-report-adapter-");
|
||||
const evidence = await (adapter === "cli" ? captureViaCli : captureViaMcp)({
|
||||
...scenario,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ProcessOwnershipEvidenceOwner } from "../../../src/process/ProcessOwnershipEvidence.js";
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import { parseProcessScenario } from "../../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
||||
import {
|
||||
createRunManifest,
|
||||
observeLaunchedExecutable,
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from "../../../src/process/capture/ProcessCaptureLifecycle.js";
|
||||
|
||||
it("uses one selected host identity for manifest and settlement", async () => {
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: process.cwd(),
|
||||
events: [],
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
snapshotRoots,
|
||||
} from "../../../src/process/capture/FilesystemSnapshot.js";
|
||||
import { prepareProcessCapture } from "../../../src/process/capture/ProcessCaptureLifecycle.js";
|
||||
import { parseProcessScenario } from "../../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
||||
import { emptyProcessCapture } from "../../../src/domain/process/processCapture.fixture.js";
|
||||
|
||||
const emptyFilesystemCoverage =
|
||||
@@ -28,7 +28,7 @@ it("prepares ownership inspection before snapshotting or allocating a target run
|
||||
|
||||
await expect(
|
||||
prepareProcessCapture(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: "/bin/true",
|
||||
working_directory: "/tmp",
|
||||
}),
|
||||
@@ -59,7 +59,7 @@ it("cleans the temporary root when cancellation arrives during identity capture"
|
||||
|
||||
await expect(
|
||||
prepareProcessCapture(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: "/bin/true",
|
||||
working_directory: "/tmp",
|
||||
}),
|
||||
@@ -98,7 +98,7 @@ it.each([false, true])(
|
||||
if (failing) throw new Error("controlled temporary-root removal denial");
|
||||
});
|
||||
const observed = await prepareProcessCapture(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: "/bin/true",
|
||||
filesystem_observation_paths: [path],
|
||||
}),
|
||||
|
||||
@@ -74,7 +74,7 @@ vi.mock("node:fs/promises", async (importOriginal) => {
|
||||
});
|
||||
|
||||
import { AnalysisCleanupLease } from "../../../src/artifacts/AnalysisCleanupLease.js";
|
||||
import { parseProcessScenario } from "../../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
||||
import {
|
||||
hashFile,
|
||||
snapshotRoots,
|
||||
@@ -97,7 +97,7 @@ type DirectoryReadCallback = (
|
||||
type DirectoryCloseCallback = (error?: NodeJS.ErrnoException | null) => void;
|
||||
|
||||
const scenarioFor = (root: string) =>
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
|
||||
@@ -54,7 +54,7 @@ vi.mock("node:fs/promises", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
import { parseProcessScenario } from "../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../src/domain/process/processScenario.js";
|
||||
import {
|
||||
hashFile,
|
||||
snapshotRoots,
|
||||
@@ -94,7 +94,7 @@ it.each(["hash", "snapshot"] as const)(
|
||||
operation === "hash"
|
||||
? hashFile(path, expected, 1_000, controller.signal)
|
||||
: snapshotRoots(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: directory,
|
||||
filesystem_observation_paths: [path],
|
||||
|
||||
@@ -104,7 +104,7 @@ vi.mock("node:fs/promises", async (importOriginal) => {
|
||||
});
|
||||
|
||||
import {
|
||||
parseProcessScenario,
|
||||
processScenarioSchema,
|
||||
type ProcessScenario,
|
||||
} from "../../src/domain/process/processScenario.js";
|
||||
import { classifyFilesystemEffects } from "../../src/process/capture/ProcessFilesystemEffects.js";
|
||||
@@ -178,7 +178,7 @@ const entryUnavailable = async (
|
||||
const link = join(root, "z-link");
|
||||
await writeFile(sibling, "retain this sibling");
|
||||
await symlink("missing-target", link);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -240,7 +240,7 @@ it.skipIf(process.platform === "win32")(
|
||||
const link = join(root, "z-link");
|
||||
await writeFile(sibling, "retain this sibling");
|
||||
await symlink("original-target", link);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -275,7 +275,7 @@ it("retains siblings and marks child absence unknown when directory revalidation
|
||||
await writeFile(sibling, "retain this sibling");
|
||||
await mkdir(directory);
|
||||
await writeFile(join(directory, "child"), "child observed before race");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -309,7 +309,7 @@ it.skipIf(process.platform === "win32")(
|
||||
withTemporaryRoot("rea-snapshot-cancel-race-", async (root) => {
|
||||
const link = join(root, "link");
|
||||
await symlink("missing-target", link);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -330,7 +330,7 @@ it.skipIf(process.platform === "win32")(
|
||||
withTemporaryRoot("rea-snapshot-cancel-missing-", async (root) => {
|
||||
const link = join(root, "link");
|
||||
await symlink("missing-target", link);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
@@ -350,7 +350,7 @@ it("observes cancellation after the selected directory handle closes", async ()
|
||||
const directory = join(root, "selected");
|
||||
await mkdir(directory);
|
||||
await writeFile(join(directory, "child"), "observed child");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [directory],
|
||||
@@ -374,7 +374,7 @@ it("releases buffered names after a failed directory revalidation before visitin
|
||||
await writeFile(join(firstRoot, "a-child"), "first");
|
||||
await writeFile(join(firstRoot, "b-child"), "second");
|
||||
await writeFile(join(secondRoot, "child"), "retain this root");
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: parent,
|
||||
filesystem_observation_paths: [firstRoot, secondRoot],
|
||||
@@ -398,7 +398,7 @@ it.skipIf(process.platform === "win32")(
|
||||
withTemporaryRoot("rea-snapshot-eio-control-", async (root) => {
|
||||
const link = join(root, "link");
|
||||
await symlink("missing-target", link);
|
||||
const scenario = parseProcessScenario({
|
||||
const scenario = processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
working_directory: root,
|
||||
filesystem_observation_paths: [root],
|
||||
|
||||
@@ -2,7 +2,7 @@ import { rm, stat, type FileHandle } from "node:fs/promises";
|
||||
import { afterEach, expect, it, vi } from "vitest";
|
||||
|
||||
import { captureProcessScenario } from "../../src/process/capture/ProcessHarness.js";
|
||||
import { parseProcessScenario } from "../../src/domain/process/processScenario.js";
|
||||
import { processScenarioSchema } from "../../src/domain/process/processScenario.js";
|
||||
import { emptyProcessCapture } from "../../src/domain/process/processCapture.fixture.js";
|
||||
|
||||
const control = vi.hoisted(() => ({
|
||||
@@ -100,7 +100,7 @@ it.each(["none", "before", "open", "final-stat", "close"] as const)(
|
||||
if (stage === "before") controller.abort(reason);
|
||||
const removed: string[] = [];
|
||||
const result = await captureProcessScenario(
|
||||
parseProcessScenario({
|
||||
processScenarioSchema.parse({
|
||||
executable: process.execPath,
|
||||
arguments: ["--eval", "process.exit(0)"],
|
||||
working_directory: process.cwd(),
|
||||
|
||||
Reference in New Issue
Block a user