test(restart-chaos): count default-lifecycle Daytona sandboxes against the vCPU budget

With the remote warm default, an inheriting Daytona environment and an agent
with no lifecycle keep each task's sandbox for the idle window.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
DottaandClaude committed 2026-11-10 10:45:54 -06:00
1 parent db0e1b4dba
commit b7f6243d60
3 files changed
+6 -5

No files matched your search

+2 -2
View File
@@ -265,8 +265,8 @@ describe("Daytona options", () => {
const wave = (...extra: string[]) => parseCommand(["--env", "daytona", "--daytona-image", image, "--tasks", "20", "--concurrency", "4", ...extra]);
expect(() => wave("--daytona-warm")).toThrow(/--daytona-warm keeps each task's sandbox.*20 tasks/);
expect(() => wave("--daytona-inherit", "--lifecycle", "warm")).toThrow(/--daytona-inherit with --lifecycle warm keeps each task's sandbox/);
// --lifecycle default leaves the lifecycle unset everywhere, and a remote run then stays per-turn.
expect(wave("--daytona-inherit", "--lifecycle", "default")).toMatchObject({ mode: "wave" });
// --lifecycle default leaves the lifecycle unset everywhere; Daytona keeps reusable leases, so the run defaults to warm.
expect(() => wave("--daytona-inherit", "--lifecycle", "default")).toThrow(/--daytona-inherit with --lifecycle default keeps each task's sandbox/);
// The catalog agents pin per-turn, so an inheriting environment alone releases each sandbox after its turn.
expect(wave("--daytona-inherit")).toMatchObject({ mode: "wave", options: { daytonaInherit: true, tasks: 20 } });
expect(wave("--daytona-inherit", "--lifecycle", "per_turn")).toMatchObject({ mode: "wave" });
@@ -99,7 +99,7 @@ describe("ttft baseline statistics", () => {
expect(daytonaRetainsSandboxes({ warmEnvironment: true, inheritEnvironment: false, lifecycle: undefined })).toBe(true);
expect(daytonaRetainsSandboxes({ warmEnvironment: false, inheritEnvironment: true, lifecycle: undefined })).toBe(false);
expect(daytonaRetainsSandboxes({ warmEnvironment: false, inheritEnvironment: true, lifecycle: "per_turn" })).toBe(false);
expect(daytonaRetainsSandboxes({ warmEnvironment: false, inheritEnvironment: true, lifecycle: "default" })).toBe(false);
expect(daytonaRetainsSandboxes({ warmEnvironment: false, inheritEnvironment: true, lifecycle: "default" })).toBe(true);
expect(daytonaRetainsSandboxes({ warmEnvironment: false, inheritEnvironment: true, lifecycle: "warm" })).toBe(true);
expect(daytonaRetainsSandboxes({ warmEnvironment: false, inheritEnvironment: false, lifecycle: "warm" })).toBe(false);
});
+3 -2
View File
@@ -314,11 +314,12 @@ export function openShellExecutions(events: readonly BaselineEvent[], marker?: s
* Whether finished tasks keep their Daytona sandbox for the idle window. The warm
* fixture always does. An inheriting environment defers to the agent, whose catalog
* profile pins per_turn unless --lifecycle warm replaces it. --lifecycle default
* leaves the agent unset, and a remote run with no lifecycle anywhere is per-turn.
* leaves the agent unset; on Daytona, which keeps reusable leases, a measured
* harness with no lifecycle anywhere then defaults to warm.
*/
export function daytonaRetainsSandboxes(input: { warmEnvironment: boolean; inheritEnvironment: boolean; lifecycle: string | undefined }): boolean {
if (input.warmEnvironment) return true;
return input.inheritEnvironment && input.lifecycle === "warm";
return input.inheritEnvironment && (input.lifecycle === "warm" || input.lifecycle === "default");
}
/** Daytona sandboxes a TTFT baseline can hold at once, for the vCPU budget check. */