diff --git a/packages/local-runtime-v2/src/service/sandbox/backend/srt-macos.test.ts b/packages/local-runtime-v2/src/service/sandbox/backend/srt-macos.test.ts index dc60bad33..427d9f895 100644 --- a/packages/local-runtime-v2/src/service/sandbox/backend/srt-macos.test.ts +++ b/packages/local-runtime-v2/src/service/sandbox/backend/srt-macos.test.ts @@ -1487,6 +1487,17 @@ async function expectMandatoryDenySurface( } } +/** + * Probes must measure the sandbox, not the caller's shell. Every probe spawns a + * real process and resolves its command through `PATH`, so inheriting the + * ambient one lets a wrapper ahead of `/bin` decide what `rm` means — for + * example the recoverable-delete shim MCode installs into agent shells, whose + * trash move the sandbox then denies, turning a correct allow-probe into a + * reported sandbox regression. Pin the probes to the system binaries they + * actually use (`cat`, `rm`, `rmdir`, `find`, `mv`, `printf`, `git`, `true`). + */ +const PROBE_PATH = "/usr/bin:/bin"; + async function expectProbeResult( command: string, filesystem: SandboxInvocationFilesystemPolicy, @@ -1520,7 +1531,7 @@ async function runProbe( cwd: fixture.workspace, baseEnv: { HOME: process.env.HOME ?? "/var/empty", - PATH: process.env.PATH ?? "/usr/bin:/bin", + PATH: PROBE_PATH, }, sandboxTempDir: fixture.sessionTemp, commandId, @@ -1593,7 +1604,7 @@ function createGitProbeFixture(): GitProbeFixture { function gitProbeEnv(fixture: GitProbeFixture): Record { return { HOME: fixture.home, - PATH: process.env.PATH ?? "/usr/bin:/bin", + PATH: PROBE_PATH, GIT_CONFIG_NOSYSTEM: "1", GIT_AUTHOR_NAME: "probe", GIT_AUTHOR_EMAIL: "probe@example.invalid", @@ -1712,7 +1723,7 @@ async function wrapProfile( await profileBackend.wrap({ command: "true", cwd: profileFixture, - baseEnv: { PATH: process.env.PATH }, + baseEnv: { PATH: PROBE_PATH }, sandboxTempDir: profileFixture, commandId: opaqueId, commandText: opaqueId, diff --git a/test/byok.test.mjs b/test/byok.test.mjs index d02d010c5..d92c28412 100644 --- a/test/byok.test.mjs +++ b/test/byok.test.mjs @@ -22,10 +22,18 @@ import { parse as parseYaml, stringify as stringifyYaml } from "yaml"; import { withoutProxyEnvironment } from "./offline-environment.mjs"; const cli = process.env.MCODE_TEST_CLI ?? fileURLToPath(new URL("../dist/cli.js", import.meta.url)); +// This case is 30+ serial CLI spawns, each booting the whole runtime, so its +// wall-clock cost tracks machine speed rather than the transport it asserts. +// A flat budget sized for an idle laptop turns any busy runner (parallel build, +// shared CI host) into a `testTimeoutFailure` that reports a product failure +// while every assertion would have passed. Budget it the way smoke.test.mjs +// budgets runtime startup: a base allowance plus a Windows multiplier for +// slower process spawn, rather than a number that only holds on one machine. +const byokSerialTimeoutMs = process.platform === "win32" ? 360000 : 180000; // This fixture validates BYOK transport and real Runtime persistence, not model quality. test( "BYOK runs without managed login and resumes its saved conversation", - { timeout: 90000 }, + { timeout: byokSerialTimeoutMs }, async (t) => { const fixtureDir = mkdtempSync(path.join(tmpdir(), "minimax-code-byok-")); const dataDir = path.join(fixtureDir, "data");