Files
PaperClipAI/tests/runner-e2e/live-fixtures.test.ts
T
DottaandPaperclip adb69e8f09 feat: default new Codex agents to Paperclip Runner on Linux and macOS (#15683)
## Thinking Path

> - Paperclip is the open source control plane for agent companies.
> - People choose a harness when creating an agent.
> - The server should resolve that harness to a qualified runner.
> - Codex is the first harness in the staged default rollout.
> - Saved agents must retain their execution choices.
> - New Codex agents therefore use Paperclip Runner on qualified
macOS/Linux targets, with an explicit Legacy override.

## Linked Issues or Issue Description

Refs #16028, #15555, #15673, #15422, #15631, #15926, #15932, #16149.

The runtime/install prerequisite and release repair are merged. This
slice owns Codex creation, setup, configuration and preservation. Other
harness defaults remain unchanged. It adds no database migration;
incoming master migrations, required maps and regression coverage are
retained.

## What Changed

- Resolve `runner: auto | paperclip | legacy` at the common creation
boundary across onboarding, API/CLI, hires, built-ins, plugins and
imports. Freeze pending hires and export resolved execution choices.
- Preserve existing runners on upgrades, unrelated edits and import
updates, including compatible accounts, workspace settings, Codex effort
and intentional clears.
- Use the underlying harness picker and branding; put the runner
override in Advanced. Use the shared dropdown and update
production-component stories and creation contracts.
- Support qualified Apple Silicon, Intel Mac, Linux x64 and Linux ARM64.
Linux requires GNU libc 2.39+. Disabled, external, unsupported and
unqualified combinations retain their applicable Legacy execution.
- Test the selected runtime/account/model/environment. Ordinary Connect
probes eligible immutable managed targets and refreshes scoped
discovery. Creation/discovery do not provision. Auth, dependency,
incompatible-setting and cleanup failures remain actionable without
changing runners.
- Keep setup probes read-only, preserve local/SSH isolation and resolve
packaged assets before staging credentials. Bound cleanup reads by the
remaining absolute deadline; physically close every owned ingress socket
before endpoint release. Unconfirmed cleanup retains recovery state.
- Preserve validated completed-onboarding callbacks through startup
recovery. First file-producing work belongs to the child task and uses
the existing dependency/block handoff and task-scoped registration.
- Reuse existing E2E fixtures, artifact checks, reporting and controls.
Keep Docker/Cargo/native compilation remote. Paperclip tarballs contain
no Codex payloads; official optional npm platform dependencies remain.

## Verification

Current tested head: `1c03a8815672d82c264a9b08d4ea1984e8fae107`.
**Merge-ready: required CI, fresh review, package qualification, Mac
core acceptance and Test task/follow-up acceptance pass.** The existing
attachment and native-continuity oracles independently verify both Test
downloads, run attribution and unchanged native/provider/workspace
identities. The maintainer authorized a code-owner-review exception for
this PR only. The first Test setup failure and normal Board
completion-review friction are retained below. Actual post-merge
packages and private Cloud distribution remain separate qualification
gates.

- [Current
CI](https://github.com/paperclipai/paperclip/actions/runs/38564241625):
all 48 ordinary jobs and required verify/E2E pass. Attempt 1 retained
six simultaneous host-shutdown cancellations. One failed-only retry
passes those six lanes and two aggregates, preserving 40 successes.
Actual integration checkout `53104c1` combines this head with master
`c80`; it is not relabeled as the branch tree. Fresh exact-head Greptile
5/5, 30 resolved threads, no actionable findings.
- [Exact-source package
qualification](https://github.com/paperclipai/paperclip/actions/runs/38565287239):
nine applicable jobs pass, nine conditional jobs skip. Four remote
native producers; Linux x64 clean install; Intel Mac, Apple Silicon and
Linux ARM64 native startup/physical cleanup controls. All 18
tarballs/four daemon source/hash/manifest bindings and 343 migrations
through 0344 verify. No Codex payload is packed. These hosted tarballs
are not a published npm canary.
- Normal Apple Silicon installation and credential-free native
startup/cleanup pass using the packaged daemon, with no source build or
provider turn. Fresh installed DB initialization passes. Upgrade
651a→1c03 preserves all three complete execution configs, accounts, ten
recorded run profiles, paused budgets, active incidents, cost summaries
and two historical unpriced events. Historical recovery state is
retained.
- Cleanup regressions: four delayed-read baseline failures become 15
passing deadline/authority controls. No-acknowledgement and prior-error
socket ownership regressions become 12 passing controls. Direct
runtime/server types, maps: 35 areas / 176 IDs, diff checks and
independent reviews pass. Permission/auth/reconnect policy and the
10-second setup budget remain intact.
- Existing source coverage includes creation/selection/imports, pending
approvals, recovery, account/lifecycle handling, mounted forms,
dropdowns and E2E support. Full typechecks/tests/build/token and
applicable Storybook checks pass in the recorded current CI; no
duplicate suite or weakened grader.
- Literal 9546 live Mac proof: ordinary Auto Codex onboarding, useful
document, real completed-child callback/reply, seven successful native
runs, manual follow-up and independently downloaded1,101-byte child
file. Existing Legacy title edit/reload preserves execution; two real
Legacy runs produce independently checked15/34-byte files. These remain
historical source records.
- Current literal 1c03 Mac core acceptance passes independent checks:
ordinary Auto native Codex onboarding without runner override; only
timeout 180 seconds/concurrency 1 saved; six successful native runs and
six serialized turns (maximum overlap 1); both same-task continuity
checks and five mechanical callback checks; actual rendered parent reply
and exact child downloads. The useful handoff advances from revision 1
to 2. Both files are 48 bytes, SHA-256
`8b742bd4e8123a7c078f0a8d9f3449fbfa8a320d7d90be641a2818db3c53d92c` and
`f42db9774fa06e804ab7d596fc8b922a2b638921c418b87d0111151d290a6afe`;
exactly one byte changes and old history remains. The agent is paused
with zero active runs/errors. Both artifact work products have
`isPrimary=false`, and descriptive titles fail a stricter title-helper
assumption; these retained results are scoped editorial follow-up, not
new merge gates. Six source-bound screenshots are uploaded and verified
in the private primary QA report.
- [Literal 9546 managed
proof](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-38485488621-1/index.html):
original 19 assertions and completed judge pass, four native turns,
child-bound240-byte file and session/workspace continuity. Checkout
reports a verified generated target-lock mutation; full final porcelain
was not retained. Signed execution-image identity remains separate from
Core source.
- Actual 651a Test deployment succeeds on one owned/pinned target. One
ordinary Auto API-key Connect then fails native cleanup before hire.
Controller turn/drain/suspend completion and service-recorded
environment cleanup are observed; they do not certify physical deletion
or native authority retirement. Failure/recovery/unknown holds are
retained. No Legacy switch or unchanged paid retry. The two source
repairs above require actual treatment.
- [Current immutable Core
preview](https://github.com/paperclipai/paperclip/actions/runs/38570365725)
and matching DB/shared artifacts pass. One owned, pinned Test target
serves exact `1c03`; identical migration history correctly skips the
migrator. Ordinary Auto Codex Connect succeeds and hires native; saved
native selection and QA bounds survive reload. The initial child
preparation attempt fails before provider work, with actual stdout
identifying `renewal_deadline`; its trigger remains unknown and the
failure is retained. Normal Board **Try again** and **Resume** recover
the child to Done, producing a browser-verified 44-byte file, SHA-256
`0a8458b1efcc2d7a0d815689458c4caab039a46c7c7a3e5805de6bc8b1a96ecc`. The
actual parent callback reports the completed child document/file. The
existing validator requires a parent-owned attachment, so recovery
enters normal Review; after byte checking, normal **Approve completion**
reaches parent Done. No forced status or duplicate parent file is used.
The validator is unchanged from integrated and current master.
Autonomous initial callback-to-Done is not proven. The same-child
follow-up completes document revision 2 and publishes a second
independently downloaded 44-byte file, SHA-256
`22022257300fae762784632d08d3bbe0bab61e2ce81f91864a14dcd7aa464591`; only
the revision digit changes. The unchanged existing native-continuity and
attachment oracles pass. All ten recorded runs are terminal: nine native
successes and the retained pre-provider setup failure. The QA agent is
paused with zero active runs. The pre-existing parent evidence scope
mismatch is a separate follow-up, with ordinary completion review
exercised rather than a forced status or relaxed validation. This
unsigned Core preview remains distinct from post-merge private Cloud
composition.

## Risks

- Saved agents are not migrated. Explicit runner changes use normal
configuration/session rules; historical runs retain their recorded
execution.
- Native readiness depends on verified assets and server-owned target
qualification. A Legacy probe, HTTP200 or successful account save cannot
prove native readiness.
- Recovery exceptions remain restricted to validated
completed-onboarding reports; process-loss, ownership and terminal-state
safeguards remain active. Unexecuted live journeys stay open.
- Linux ARM paid tasks, Windows, Alpine and 32-bit ARM remain deferred.
Cold Cargo cache misses are recorded; no warm-cache speedup is claimed.
- Historical invoices/physical cleanup remain unconfirmed and held.
After merge, exact published npm canary, signed standard image/migrator,
private composition and serving/live acceptance still require
qualification. Production deployment/default promotion is not
authorized.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tools, code execution and
parallel agents. Exact serving snapshot and context-window size are not
exposed.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used with available version and
capability details
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have linked public issues or PRs above
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
ticket id
- [x] I have run the stated focused tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented risks
- [x] All Paperclip CI gates are green on the current candidate
- [x] Greptile is 5/5 with no open findings on the current candidate
- [x] I will address all reviewer comments before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-14 11:33:02 -05:00

429 lines
21 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { RunnerApi } from "./api.js";
import { buildRuntimeUsage } from "./billing.js";
import { runnerMatrix } from "./catalog.js";
import { setupLiveFixtures, selectFixtureRuntimeLeases, fixtureRuntimeCostCoverage } from "./live-fixtures.js";
describe("live runner fixtures", () => {
it.each(["runner-codex", "runner-acpx-claude", "runner-opencode"].flatMap(profile =>
["hire-reuse", "delegate-feedback"].map(task => [profile, task]))) (
"applies %s %s budget stops in actual setup with a nonce and only its selected credential", async (profile, task) => {
const execution = runnerMatrix.find(row => row.id === `everyday-workflows.${profile}.local.${task}`)!;
let agentBody: any;
let companyBody: any;
const api = {
async get() { return [{ id: "local", driver: "local" }]; },
async postSensitive(url: string) { return url.endsWith("/ai-connections") ? { connectionId: "account" } : { id: "secret" }; },
async post(url: string, data: any) {
if (url === "/api/companies") { companyBody = data; return { id: "company", name: "Test" }; }
if (url.endsWith("/agents")) { agentBody = data; return { id: "lead", ...data }; }
throw new Error(`Unexpected POST ${url}`);
},
} as unknown as RunnerApi;
const fixtures = await setupLiveFixtures({ api, execution, executionNonce: "random-nonce", workspacePath: "/tmp/test",
credentials: { [execution.profile.credential]: "test-value" } });
expect(companyBody.budgetMonthlyCents).toBe(1_000);
expect(agentBody.budgetMonthlyCents).toBe(1_000);
await fixtures.teardown();
},
);
it.each(["runner-codex", "runner-acpx-claude", "runner-opencode"])(
"sets both connection-guidance budget stops for %s before execution", async profile => {
const execution = runnerMatrix.find(row => row.suite.id === "native-connection-guidance" && row.profile.id === profile)!;
let companyBudget: unknown;
let agentBudget: unknown;
const api = {
async get() { return [{ id: "local", driver: "local" }]; },
async postSensitive() { return { id: "secret" }; },
async post(url: string, data: any) {
if (url === "/api/companies") { companyBudget = data.budgetMonthlyCents; return { id: "company", name: "Test" }; }
if (url.endsWith("/agents")) { agentBudget = data.budgetMonthlyCents; return { id: "lead", ...data }; }
throw new Error("Unexpected POST " + url);
},
} as unknown as RunnerApi;
const fixtures = await setupLiveFixtures({ api, execution, executionNonce: "nonce", workspacePath: "/tmp/test",
credentials: { [execution.profile.credential]: "test-value" } });
expect(companyBudget).toBe(1_000);
expect(agentBudget).toBe(1_000);
await fixtures.teardown();
},
);
it.each(["runner-codex", "legacy-codex", "runner-acpx-claude", "legacy-opencode"])(
"creates a production-default %s hire with company and agent budget stops", async (profile) => {
const execution = runnerMatrix.find(row => row.suite.id === "stock-harness" && row.profile.id === profile)!;
let agentBody: any;
const api = {
async get() { return [{ id: "local", driver: "local" }]; },
async postSensitive() { return { id: "secret" }; },
async post(url: string, data: any) {
if (url === "/api/companies") {
expect(data.budgetMonthlyCents).toBe(1_000);
return { id: "company", name: "Fixture" };
}
if (url.endsWith("/agents")) { agentBody = data; return { id: "agent", ...data }; }
throw new Error(`Unexpected POST ${url}`);
},
} as unknown as RunnerApi;
const fixtures = await setupLiveFixtures({ api, execution, executionNonce: "nonce", workspacePath: "/tmp/fixture",
credentials: { [execution.profile.credential]: "fixture-key" } });
expect(agentBody).not.toHaveProperty("instructionsBundle");
expect(agentBody.budgetMonthlyCents).toBe(1_000);
expect(agentBody.adapterConfig.env[execution.profile.credential]).toEqual({ type: "secret_ref", secretId: "secret", version: "latest" });
await fixtures.teardown();
},
);
it("anchors extended file validation to a public project workspace for local and remote copy-back", async () => {
const execution = runnerMatrix.find(e => e.id === "extended-harnesses.runner-acpx-pi.local.file-edit-validate")!;
let projectBody: any;
const api = {
async get() { return [{ id: "local", driver: "local" }]; },
async postSensitive() { return { id: "secret" }; },
async post(url: string, data: any) {
if (url === "/api/companies") return { id: "company", name: "Test" };
if (url.endsWith("/agents")) return { id: "agent", ...data };
if (url.endsWith("/projects")) { projectBody = data; return { id: "project", ...data }; }
throw new Error(`Unexpected POST ${url}`);
},
} as unknown as RunnerApi;
const fixtures = await setupLiveFixtures({ api, execution, executionNonce: "nonce", workspacePath: "/tmp/fixture-workspace", credentials: { OPENROUTER_API_KEY: "fixture-key" } });
expect(fixtures.project?.id).toBe("project");
expect(projectBody).toMatchObject({ executionWorkspacePolicy: { environmentId: "local", workspaceStrategy: { type: "project_primary" } }, workspace: { cwd: "/tmp/fixture-workspace", sourceType: "local_path" } });
});
it.each([
["runner-codex", "hiring-templates", "hire-coder-template-reuse"],
["runner-acpx-claude", "hiring-templates", "hire-coder-template-reuse"],
["runner-codex", "everyday-workflows", "hire-reuse"],
["runner-acpx-claude", "everyday-workflows", "hire-reuse"],
["runner-opencode", "everyday-workflows", "hire-reuse"],
["runner-codex", "agent-chat-hardening", "hire-delegate-reuse"],
["runner-acpx-claude", "agent-chat-hardening", "hire-delegate-reuse"],
])(
"gives %s %s/%s a personal managed account without env overrides",
async (profile, suite, task) => {
const execution = runnerMatrix.find(
(e) =>
e.suite.id === suite &&
e.task.id === task &&
e.profile.id === profile &&
e.environment.id === "local",
)!;
const provider =
profile === "runner-acpx-claude" ? "anthropic" : profile === "runner-opencode" ? "openrouter" : "openai";
let connected = false;
let agentBody: any;
const api = {
async post(url: string, data: any) {
if (url === "/api/companies") return { id: "company", name: "Test" };
if (url.endsWith("/agents")) {
agentBody = data;
return { id: "lead", ...data };
}
throw new Error(`Unexpected POST ${url}`);
},
async postSensitive(url: string, data: any) {
if (url.endsWith("/ai-connections")) {
expect(data).toMatchObject({
provider,
method: "api_key",
ownership: "personal",
apiKey: "test-value",
agentIds: [],
allAgents: false,
});
connected = true;
return { connectionId: "managed-account" };
}
return { id: "secret" };
},
async get() {
return [{ id: "local", driver: "local" }];
},
} as unknown as RunnerApi;
const fixtures = await setupLiveFixtures({
api,
execution,
executionNonce: "nonce",
workspacePath: "/tmp/test",
credentials: {
[execution.profile.credential]: "test-value",
},
});
expect(connected).toBe(true);
expect(agentBody.adapterConfig.env).toBeUndefined();
expect(agentBody.runtimeConfig.aiConnection).toEqual({
provider,
method: "api_key",
mode: "responsible_user",
});
expect((fixtures as any).aiConnection.connectionId).toBe(
"managed-account",
);
},
);
it.each(["legacy-codex", "runner-acpx-claude", "runner-opencode"])("installs Daytona before its %s environment without adding a Codex qualification probe", async profile => {
const calls: string[] = [];
const api = {
async post(path: string, data?: Record<string, unknown>) {
calls.push(`POST ${path}`);
if (path === "/api/plugins/install") {
expect(data).toMatchObject({ isLocalPath: true });
expect(data?.packageName).toEqual(
expect.stringContaining(
"packages/plugins/sandbox-providers/daytona",
),
);
return {
id: "plugin-daytona",
pluginKey: "paperclip.daytona-sandbox-provider",
status: "ready",
};
}
if (path === "/api/companies") {
return { id: "company-1", name: "Runner E2E" };
}
if (path.endsWith("/environments")) {
expect(calls).toContain("POST /api/plugins/install");
return { id: "environment-1", driver: "sandbox", config: data?.config };
}
if (path.endsWith("/agents")) {
return { id: "agent-1", name: "Agent", companyId: "company-1" };
}
throw new Error(`Unexpected POST ${path}`);
},
async postSensitive(path: string, data?: Record<string, unknown>) {
calls.push(`POST ${path}`);
return { id: `secret-${String(data?.key).toLowerCase()}` };
},
async delete(path: string) {
calls.push(`DELETE ${path}`);
},
} as unknown as RunnerApi;
const execution = runnerMatrix.find(
(candidate) =>
candidate.id ===
`core-compatibility.${profile}.daytona.message-marker`,
);
expect(execution).toBeDefined();
const fixtures = await setupLiveFixtures({
api,
execution: execution!,
executionNonce: "nonce",
workspacePath: "/tmp/workspace",
credentials: {
[execution!.profile.credential]: "provider-test-value",
DAYTONA_API_KEY: "daytona-test-value",
},
daytonaImage:
"ghcr.io/paperclip/image@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
});
expect(calls.indexOf("POST /api/plugins/install")).toBeLessThan(
calls.indexOf("POST /api/companies/company-1/environments"),
);
expect(calls.some(call => call.includes("/probe"))).toBe(false);
await fixtures.teardown();
expect(calls).toContain(
"DELETE /api/environments/environment-1?destroyReusableSandboxLeases=true",
);
});
it.each(["explicit", "auto"])("qualifies the immutable Codex image once before %s agent creation", async mode => {
const original = runnerMatrix.find(row => row.id === "core-compatibility.runner-codex.daytona.message-marker")!;
const execution = { ...original, profile: { ...original.profile, buildAgent(input: Parameters<typeof original.profile.buildAgent>[0]) {
const payload = original.profile.buildAgent(input);
return { ...payload, adapterType: mode === "auto" ? "codex_local" : "paperclip_runner",
runner: mode === "auto" ? "auto" : "paperclip" };
} } };
const calls: string[] = [];
const api = {
async get(path: string) {
calls.push(`GET ${path}`);
return [{ type: "codex_local", defaultRunner: "paperclip", supportedRunners: ["paperclip", "legacy"] }];
},
async post(path: string, data: any, options: any) {
calls.push(`POST ${path}`);
if (path === "/api/plugins/install") return { id: "plugin", status: "ready" };
if (path === "/api/companies") return { id: "company", name: "Fixture" };
if (path.endsWith("/environments")) return { id: "environment", driver: "sandbox", config: data.config };
if (path === "/api/environments/environment/probe?companyId=company") {
expect(options).toEqual({ timeout: 330_000 });
return { ok: true, details: { platformQualificationRecorded: true, leaseId: "setup-probe" } };
}
if (path.endsWith("/agents")) {
expect(calls).toContain("POST /api/environments/environment/probe?companyId=company");
expect(data.adapterType).toBe(mode === "auto" ? "codex_local" : "paperclip_runner");
expect(data.runner).toBe(mode === "auto" ? "auto" : "paperclip");
if (mode === "auto") expect(calls).toContain("GET /api/adapters?companyId=company&environmentId=environment");
return { id: "agent", companyId: "company", ...data };
}
throw new Error(`Unexpected POST ${path}`);
},
async postSensitive() { return { id: "secret" }; },
async delete() {},
} as unknown as RunnerApi;
const fixtures = await setupLiveFixtures({ api, execution, executionNonce: "nonce", workspacePath: "/tmp/fixture",
credentials: { OPENAI_API_KEY: "fixture-key", DAYTONA_API_KEY: "fixture-provider-key" },
daytonaImage: `registry.example.test/runtime@sha256:${"a".repeat(64)}` });
expect(fixtures.setupProbe).toMatchObject({ leaseId: "setup-probe", ...(mode === "auto" ? { defaultRunner: "paperclip" } : {}) });
expect(calls.filter(call => call.includes("/probe?"))).toHaveLength(1);
expect(calls.filter(call => call.startsWith("GET"))).toHaveLength(mode === "auto" ? 1 : 0);
await fixtures.teardown();
});
it.each(["probe-failed", "not-recorded", "wrong-default"])("stops before automatic Codex creation when image qualification is %s", async failure => {
const original = runnerMatrix.find(row => row.id === "core-compatibility.runner-codex.daytona.message-marker")!;
const execution = { ...original, profile: { ...original.profile, buildAgent(input: Parameters<typeof original.profile.buildAgent>[0]) {
return { ...original.profile.buildAgent(input), adapterType: "codex_local", runner: "auto" };
} } };
const calls: string[] = [];
const api = {
async get() { return [{ type: "codex_local", defaultRunner: "legacy", supportedRunners: ["legacy"] }]; },
async post(path: string, data: any) {
calls.push(path);
if (path === "/api/plugins/install") return { id: "plugin", status: "ready" };
if (path === "/api/companies") return { id: "company", name: "Fixture" };
if (path.endsWith("/environments")) return { id: "environment", driver: "sandbox", config: data.config };
if (path.includes("/probe?")) return { ok: failure !== "probe-failed",
details: { platformQualificationRecorded: failure !== "not-recorded", leaseId: "setup-probe" } };
throw new Error(`Unexpected POST ${path}`);
},
async postSensitive() { return { id: "secret" }; },
async delete(path: string) { calls.push(`DELETE ${path}`); },
} as unknown as RunnerApi;
await expect(setupLiveFixtures({ api, execution, executionNonce: "nonce", workspacePath: "/tmp/fixture",
credentials: { OPENAI_API_KEY: "fixture-key", DAYTONA_API_KEY: "fixture-provider-key" },
daytonaImage: `registry.example.test/runtime@sha256:${"a".repeat(64)}` })).rejects.toThrow(failure === "wrong-default" ? "server-owned default" : "not recorded");
expect(calls.some(call => call.endsWith("/agents"))).toBe(false);
expect(calls.filter(call => call.includes("/probe?"))).toHaveLength(1);
expect(calls).toContain("DELETE /api/environments/environment?destroyReusableSandboxLeases=true");
});
it("includes the owned setup probe in existing runtime estimates while excluding unrelated leases", () => {
const lease = (id: string, duration: number, heartbeatRunId?: string) => ({ id, provider: "daytona", heartbeatRunId,
acquiredAt: "2026-10-12T00:00:00Z", releasedAt: new Date(Date.parse("2026-10-12T00:00:00Z") + duration).toISOString(),
metadata: { cpu: 4, memory: 4, disk: 10 } });
const leases = [lease("task", 20_000, "selected-run"), lease("setup-probe", 10_000), lease("unrelated", 600_000, "other-run")];
const selected = selectFixtureRuntimeLeases({ leases, runIds: ["selected-run"], setupProbeLeaseId: "setup-probe" });
expect(selected.map(value => value.id)).toEqual(["task", "setup-probe"]);
const usage = buildRuntimeUsage({ environmentId: "daytona", runs: [], leases: selected });
expect(usage.leaseCount).toBe(2);
expect(usage.leaseDurationMs).toBe(30_000);
expect(usage.costStatus).toBe("estimated");
expect(usage.estimatedListCostUsd).toBeGreaterThan(0);
expect(selectFixtureRuntimeLeases({ leases, runIds: ["selected-run"] }).map(value => value.id)).toEqual(["task"]);
});
it("creates a primary project workspace for reusable Daytona scope", async () => {
const calls: string[] = [];
const api = {
async post(path: string, data?: Record<string, unknown>) {
calls.push(`POST ${path}`);
if (path === "/api/plugins/install") {
return {
id: "plugin-daytona",
pluginKey: "paperclip.daytona-sandbox-provider",
status: "ready",
};
}
if (path === "/api/companies") {
return { id: "company-1", name: "Runner E2E" };
}
if (path.endsWith("/environments")) {
return { id: "environment-1", driver: "sandbox", config: data?.config };
}
if (path.endsWith("/agents")) {
return { id: "agent-1", name: "Agent", companyId: "company-1" };
}
if (path.startsWith("/api/environments/environment-1/probe?")) {
return { ok: true, details: { platformQualificationRecorded: true, leaseId: "setup-probe" } };
}
if (path.endsWith("/projects")) {
expect(data).toMatchObject({
executionWorkspacePolicy: {
enabled: true,
defaultMode: "shared_workspace",
environmentId: "environment-1",
},
workspace: {
sourceType: "local_path",
cwd: "/tmp/workspace",
isPrimary: true,
},
});
return {
id: "project-1",
name: data?.name,
primaryWorkspace: {
id: "project-workspace-1",
cwd: "/tmp/workspace",
},
};
}
throw new Error(`Unexpected POST ${path}`);
},
async get() { return [{ type: "codex_local", defaultRunner: "paperclip", supportedRunners: ["paperclip", "legacy"] }]; },
async postSensitive(_path: string, data?: Record<string, unknown>) {
return { id: `secret-${String(data?.key).toLowerCase()}` };
},
async delete() {},
} as unknown as RunnerApi;
const execution = runnerMatrix.find(
(candidate) =>
candidate.id ===
"daytona-warm-continuity.runner-codex.daytona.warm-three-turn",
)!;
const fixtures = await setupLiveFixtures({
api,
execution,
executionNonce: "nonce",
workspacePath: "/tmp/workspace",
credentials: {
[execution!.profile.credential]: "provider-test-value",
DAYTONA_API_KEY: "daytona-test-value",
},
daytonaImage:
"ghcr.io/paperclip/image@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
});
expect(fixtures.project?.primaryWorkspace?.id).toBe("project-workspace-1");
expect(
calls.indexOf("POST /api/companies/company-1/environments"),
).toBeLessThan(calls.indexOf("POST /api/companies/company-1/projects"));
await fixtures.teardown();
});
});
describe("owned browser setup lease accounting", () => {
it("includes both exact setup IDs and task runs while excluding unrelated leases", () => {
const leases = [{ id: "platform", provider: "daytona" }, { id: "adapter", provider: "daytona" },
{ id: "task", provider: "daytona", heartbeatRunId: "run" }, { id: "unrelated", provider: "daytona" }];
expect(selectFixtureRuntimeLeases({ leases, runIds: ["run"], setupLeaseIds: ["platform", "adapter"] }).map(lease => lease.id)).toEqual(["platform", "adapter", "task"]);
expect(selectFixtureRuntimeLeases({ leases, runIds: [], setupLeaseIds: ["platform"] }).map(lease => lease.id)).toEqual(["platform"]);
expect(selectFixtureRuntimeLeases({ leases, runIds: [], setupLeaseIds: [] })).toEqual([]);
});
});
describe("managed setup runtime cost coverage", () => {
it("prices both exact setup windows with task usage and keeps missing attribution unknown", () => {
const leases = ["platform", "adapter", "task", "unrelated"].map((id, index) => ({ id, provider: "daytona", heartbeatRunId: id === "task" ? "run" : null,
acquiredAt: "2026-10-13T00:00:00Z", releasedAt: `2026-10-13T00:00:0${index + 1}Z`, metadata: { cpu: 4, memory: 4, disk: 10 } }));
const selected = selectFixtureRuntimeLeases({ leases, runIds: ["run"], setupLeaseIds: ["platform", "adapter"] });
const usage = buildRuntimeUsage({ environmentId: "daytona", runs: [], leases: selected });
expect(usage.leaseCount).toBe(3);
expect(usage.leaseDurationMs).toBe(6000);
expect(usage.estimatedListCostUsd).toBeGreaterThan(0);
expect(fixtureRuntimeCostCoverage(usage, {})).toEqual(usage);
const incomplete = fixtureRuntimeCostCoverage(usage, { setupLeaseAccountingIncomplete: true });
expect(incomplete.costStatus).toBe("unavailable");
expect(incomplete.costSource).toBe("provider_cost_unavailable");
expect(incomplete).not.toHaveProperty("estimatedListCostUsd");
expect(incomplete.leaseCount).toBe(3);
});
});