Files
PaperClipAI/server/src/services/native-runtime/native-session-resume.test.ts
T
DottaandPaperclip 4857799a88 feat(connections): deliver saved instructions to authorized agent turns (#15216)
Persist optional connection instructions and deliver authorized snapshots to agent execution prompts. Keep provider templates with each app definition, preserve edits and opt-outs, and replace sessions when guidance or access changes.

Use shared production settings across setup and Permissions, with source visibility in agent Instructions. Add the initial memory-provider defaults and managed Honcho workspace configuration. Include migration 0298 and regression coverage for generic providers, runtime delivery, authorization, and catalog regeneration.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-05 18:16:00 -05:00

2726 lines
91 KiB
TypeScript

import { createHash, randomUUID } from "node:crypto";
import { existsSync, readFileSync } from "node:fs";
import {
chmod,
mkdir,
mkdtemp,
readFile,
readdir,
rm,
writeFile,
} from "node:fs/promises";
import { createServer } from "node:http";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { eq, sql } from "drizzle-orm";
import {
agents,
companies,
completionContracts,
createDb,
heartbeatRunEvents,
heartbeatRuns,
issues,
nativeRunResults,
} from "@paperclipai/db";
import { describe, expect, it, vi } from "vitest";
import {
CodexAppServerDriver,
HarnessDriverBackend,
createCodexTaskEnvelope,
createRunnerdCodexTransport as createCapabilityRunnerdCodexTransport,
} from "@paperclipai/paperclip-runner";
import {
getEmbeddedPostgresTestSupport,
startEmbeddedPostgresTestDatabase,
} from "../../__tests__/helpers/embedded-postgres.js";
import {
canonicalNativeRuntimeContextDigest,
defaultCapabilityRunnerdBinary,
executeNativeSession,
parseNativeExecutionInput,
type NativeExecutionInput,
type NativeSession,
} from "../../vendor/paperclip-runner/index.js";
import {
runnerPrpWebSocketInternals,
setupRunnerPrpWebSocketServer,
} from "../../realtime/runner-prp-ws.js";
import {
appendRetainedNativeCleanupEvent,
createRunnerdBackend,
retainedNativeCleanupJournalMatches,
} from "./native-session-executor.js";
import * as publicationSignals from "../chat-publication-reconciliation.js";
import { PaperclipControlPlanePort } from "./paperclip-control-plane-port.js";
import {
LIST_CHAT_ATTACHMENTS_TOOL_DEFINITION,
REUSE_CHAT_ATTACHMENT_TOOL_DEFINITION,
} from "./chat-attachment-reuse.js";
import { buildNativeExecutionInput } from "./native-execution-input.js";
import {
buildNativeExecutionWithCheckpoint,
findNativeSessionResumeRun,
NATIVE_TOOL_CONTRACT_FINGERPRINT,
isUnusedLegacyNativeRetryReplacement,
nativeToolContractFingerprintForTarget,
nativeSessionIdForBootstrapPersistence,
nativeSessionProviderEvidence,
prepareNativeSessionBootstrapPersistence,
rebindNativeSessionCheckpoint,
selectNativeSessionResumeRun,
} from "./native-session-resume.js";
import { nativeRuntimeContextFixture } from "./runtime-context.test-fixture.js";
const companyId = "10000000-0000-4000-8000-000000000001";
const issueId = "20000000-0000-4000-8000-000000000002";
const agentId = "30000000-0000-4000-8000-000000000003";
const previousRunId = "40000000-0000-4000-8000-000000000004";
const currentRunId = "50000000-0000-4000-8000-000000000005";
const normalizedSessionId = "60000000-0000-4000-8000-000000000006";
const CONDITIONAL_READER_TOOL_CONTRACT_FINGERPRINT = `sha256:${createHash(
"sha256",
)
.update(
JSON.stringify({
schema: "paperclip.native-tool-contract.v1",
tools: [
{ name: "register_deliverable", version: 1 },
{
name: "read_current_wake_comments",
semanticContract: "paperclip.server-current-wake-comments.v1",
version: 1,
},
],
}),
)
.digest("hex")}`;
const PRE_CHAT_ATTACHMENT_REUSE_TOOL_CONTRACT_FINGERPRINT = `sha256:${createHash(
"sha256",
)
.update(
JSON.stringify({
schema: "paperclip.native-tool-contract.v2",
executionTargetKind: "local",
advertisementPolicy: {
readCurrentWakeComments: "always_advertised_binding_gated.v1",
registerDeliverable: "local_workspace_only.v1",
},
tools: [
{ name: "register_deliverable", version: 1 },
{
name: "read_current_wake_comments",
semanticContract: "paperclip.server-current-wake-comments.v1",
version: 1,
},
],
}),
)
.digest("hex")}`;
const PRE_CHAT_ATTACHMENT_READ_TOOL_CONTRACT_FINGERPRINT = `sha256:${createHash(
"sha256",
)
.update(
JSON.stringify({
schema: "paperclip.native-tool-contract.v3",
executionTargetKind: "local",
advertisementPolicy: {
readCurrentWakeComments: "always_advertised_binding_gated.v1",
historicalChatAttachments:
"always_advertised_conversation_binding_gated.v1",
registerDeliverable: "local_workspace_only.v1",
},
tools: [
{ name: "register_deliverable", version: 1 },
{
name: "read_current_wake_comments",
semanticContract: "paperclip.server-current-wake-comments.v1",
version: 1,
},
{
name: "list_chat_attachments",
semanticContract: "paperclip.server-chat-attachment-reuse.v1",
version: 1,
},
{
name: "reuse_chat_attachment",
semanticContract: "paperclip.server-chat-attachment-reuse.v1",
version: 1,
},
],
}),
)
.digest("hex")}`;
const PRE_STRUCTURED_HUMAN_INPUT_TOOL_CONTRACT_FINGERPRINT = `sha256:${createHash(
"sha256",
)
.update(
JSON.stringify({
schema: "paperclip.native-tool-contract.v4",
executionTargetKind: "local",
advertisementPolicy: {
readCurrentWakeComments: "always_advertised_binding_gated.v1",
historicalChatAttachments:
"always_advertised_conversation_binding_gated.v1",
registerDeliverable: "local_workspace_only.v1",
readChatAttachment: "always_advertised_run_scope_local_staging.v1",
},
tools: [
{ name: "register_deliverable", version: 1 },
{
name: "read_current_wake_comments",
semanticContract: "paperclip.server-current-wake-comments.v1",
version: 1,
},
{
name: "list_chat_attachments",
semanticContract: "paperclip.server-chat-attachment-reuse.v1",
version: 1,
},
{
name: "reuse_chat_attachment",
semanticContract: "paperclip.server-chat-attachment-reuse.v1",
version: 1,
},
{
name: "read_chat_attachment",
semanticContract: "paperclip.server-chat-attachment-read.v1",
version: 1,
},
],
}),
)
.digest("hex")}`;
const PRE_RESPONSE_WAKE_YIELD_TOOL_CONTRACT_FINGERPRINT = `sha256:${createHash(
"sha256",
)
.update(
JSON.stringify({
schema: "paperclip.native-tool-contract.v5",
executionTargetKind: "local",
advertisementPolicy: {
readCurrentWakeComments: "always_advertised_binding_gated.v1",
historicalChatAttachments:
"always_advertised_conversation_binding_gated.v1",
registerDeliverable: "local_workspace_only.v1",
readChatAttachment: "always_advertised_run_scope_local_staging.v1",
structuredHumanInput:
"always_advertised_run_issue_agent_binding_gated.v1",
},
tools: [
{ name: "register_deliverable", version: 1 },
{
name: "read_current_wake_comments",
semanticContract: "paperclip.server-current-wake-comments.v1",
version: 1,
},
{
name: "list_chat_attachments",
semanticContract: "paperclip.server-chat-attachment-reuse.v1",
version: 1,
},
{
name: "reuse_chat_attachment",
semanticContract: "paperclip.server-chat-attachment-reuse.v1",
version: 1,
},
{
name: "read_chat_attachment",
semanticContract: "paperclip.server-chat-attachment-read.v1",
version: 1,
},
{ name: "request_human_input", version: 1 },
],
}),
)
.digest("hex")}`;
const PRE_EXPLICIT_CHAT_ATTACHMENT_GUIDANCE_TOOL_CONTRACT_FINGERPRINT = `sha256:${createHash(
"sha256",
)
.update(
JSON.stringify({
schema: "paperclip.native-tool-contract.v7",
executionTargetKind: "local",
advertisementPolicy: {
readCurrentWakeComments: "always_advertised_binding_gated.v1",
historicalChatAttachments:
"always_advertised_conversation_binding_gated.v1",
registerDeliverable: "local_workspace_only.v1",
readChatAttachment: "always_advertised_run_scope_local_staging.v1",
structuredHumanInput:
"always_advertised_run_issue_agent_binding_gated.v1",
semanticCompletion: "finish_response_wake_concrete_object.v2",
},
tools: [
{ name: "register_deliverable", version: 1 },
{
name: "read_current_wake_comments",
semanticContract: "paperclip.server-current-wake-comments.v1",
version: 1,
},
{
name: "list_chat_attachments",
semanticContract: "paperclip.server-chat-attachment-reuse.v1",
version: 1,
},
{
name: "reuse_chat_attachment",
semanticContract: "paperclip.server-chat-attachment-reuse.v1",
version: 1,
},
{
name: "read_chat_attachment",
semanticContract: "paperclip.server-chat-attachment-read.v1",
version: 1,
},
{ name: "request_human_input", version: 1 },
],
}),
)
.digest("hex")}`;
function execution(
runId: string,
cwd = "/workspace",
workMode = "standard",
workspace: {
id?: string;
repoUrl?: string | null;
repoRef?: string | null;
branchName?: string | null;
} = {},
) {
return buildNativeExecutionInput({
companyId,
runId,
issue: {
id: issueId,
identifier: "DOT-2",
title: "Test",
description: null,
workMode,
},
taskPrompt: "Only the current turn",
agentId,
workspace: {
id: workspace.id ?? runId,
cwd,
repoUrl: workspace.repoUrl ?? null,
repoRef: workspace.repoRef ?? null,
branchName: workspace.branchName ?? null,
},
normalizedSessionId,
provider: "codex",
completionContract: {
id: "70000000-0000-4000-8000-000000000007",
sha256: `sha256:${"a".repeat(64)}`,
schemaVersion: "paperclip.run-result.v1",
contract: {
revision: "1",
objective: "Test session resumption",
criteria: [{ id: "objective", requirement: "Answer the current turn" }],
},
},
runtimeContext: nativeRuntimeContextFixture(),
});
}
function planningExecution(runId: string, revisionId: string) {
return buildNativeExecutionInput({
companyId,
runId,
issue: {
id: issueId,
identifier: "DOT-2",
title: "Test",
description: null,
workMode: "planning",
},
taskPrompt: "Revise the plan",
agentId,
workspace: {
id: runId,
cwd: "/workspace",
repoUrl: null,
repoRef: null,
branchName: null,
},
normalizedSessionId,
provider: "codex",
executionMode: "plan",
planningContext: {
documentId: "80000000-0000-4000-8000-000000000008",
baseRevisionId: revisionId,
baseRevisionNumber: revisionId.endsWith("9") ? 9 : 8,
markdown: `Plan at ${revisionId}`,
sha256: `sha256:${"b".repeat(64)}`,
reviewContext: {},
},
completionContract: execution(runId).completionContract,
runtimeContext: nativeRuntimeContextFixture(),
});
}
function previousRun(overrides: Record<string, unknown> = {}) {
return {
id: previousRunId,
companyId,
agentId,
nativeSessionId: normalizedSessionId,
runnerProfileJson: {
nativeToolContractFingerprint: NATIVE_TOOL_CONTRACT_FINGERPRINT,
nativeExecutionInput: execution(previousRunId),
sessionCheckpoint: {
backendKind: "runner",
driverKind: "codex_app_server",
sessionId: "provider-thread-123",
providerSessionId: "provider-thread-123",
cursor: "42",
identity: {
runId: previousRunId,
sessionId: normalizedSessionId,
companyId,
issueId,
agentId,
},
semanticResult: {
schema: "paperclip.run-result.v1",
reportedWorkDisposition: "done",
summary: "old",
},
terminal: {
schema: "paperclip.prp.terminal.v1",
turnTerminalState: "completed",
runTerminalState: "succeeded",
reportedWorkDisposition: "done",
},
activeTurnId: "old-turn",
terminalTurns: [{ turnId: "old-turn", state: "completed" }],
pendingRuntimeRequests: [{ requestId: "old-request" }],
lineage: [{ threadId: "provider-thread-123" }],
},
...overrides,
},
};
}
describe("capability-gated connection tool refresh", () => {
it("retains the exact provider session for an MCP-only change when the harness supports it", () => {
const current = execution(currentRunId);
current.runtimeContext.mcp.digest = "b".repeat(64);
current.runtimeContext.aggregateDigest = canonicalNativeRuntimeContextDigest(current.runtimeContext);
const rebound = rebindNativeSessionCheckpoint({ previousRun: previousRun(), currentExecution: current, toolRefreshOnResume: true, refreshTools: true });
expect(rebound).toMatchObject({ sessionId: "provider-thread-123", providerSessionId: "provider-thread-123", identity: { runId: currentRunId }, providerRecoveryPolicy: "allow_replacement_after_resume_failure" });
expect(rebindNativeSessionCheckpoint({ previousRun: previousRun(), currentExecution: current })).toBeNull();
expect(rebindNativeSessionCheckpoint({ previousRun: previousRun(), currentExecution: current, refreshTools: true, toolRefreshOnResume: false })).toBeNull();
});
it.each(["add", "edit", "remove"])("replaces sessions when connection instructions %s, even with live tool refresh", (change) => {
const block = (text: string) => ({ text, digest: createHash("sha256").update(text).digest("hex") });
const previous = execution(previousRunId);
const current = execution(currentRunId);
if (change !== "add") previous.runtimeContext.connectionInstructions = block("Prior connection instructions.");
if (change !== "remove") current.runtimeContext.connectionInstructions = block("Current connection instructions.");
previous.runtimeContext.aggregateDigest = canonicalNativeRuntimeContextDigest(previous.runtimeContext);
current.runtimeContext.aggregateDigest = canonicalNativeRuntimeContextDigest(current.runtimeContext);
const prior = previousRun({ nativeExecutionInput: previous });
expect(rebindNativeSessionCheckpoint({ previousRun: prior, currentExecution: current, toolRefreshOnResume: true, refreshTools: true })).toBeNull();
current.runtimeContext = previous.runtimeContext;
expect(rebindNativeSessionCheckpoint({ previousRun: prior, currentExecution: current })).not.toBeNull();
});
it("preserves instruction and identity fences even during a supported refresh", () => {
const current = execution(currentRunId);
current.runtimeContext.instructions.bundle.digest = "b".repeat(64);
current.runtimeContext.aggregateDigest = canonicalNativeRuntimeContextDigest(current.runtimeContext);
expect(rebindNativeSessionCheckpoint({ previousRun: previousRun(), currentExecution: current, toolRefreshOnResume: true, refreshTools: true })).toBeNull();
current.binding.agentId = randomUUID();
expect(rebindNativeSessionCheckpoint({ previousRun: previousRun(), currentExecution: current, toolRefreshOnResume: true, refreshTools: true })).toBeNull();
});
it("rebuilds the bootstrap when refresh requires a fresh session", () => {
const buildExecution = vi.fn(({ normalizedSessionId: sessionId, resumedSession }) => {
const built = execution(currentRunId);
built.session.normalizedSessionId = sessionId;
built.task.prompt = resumedSession ? "wake delta" : "original goal and complete handoff";
return built;
});
const result = buildNativeExecutionWithCheckpoint({ previousRun: previousRun(), normalizedSessionId, refreshTools: true, toolRefreshOnResume: false, buildExecution });
expect(result.checkpoint).toBeNull();
expect(result.normalizedSessionId).not.toBe(normalizedSessionId);
expect(result.execution.task.prompt).toContain("complete handoff");
expect(buildExecution).toHaveBeenLastCalledWith({ normalizedSessionId: result.normalizedSessionId, resumedSession: false });
});
});
it("wires exact-session recovery and guarded selected identity into heartbeat persistence", () => {
const source = readFileSync(
new URL("../heartbeat.ts", import.meta.url),
"utf8",
);
expect(source).toContain("await findNativeSessionResumeRun(db,");
expect(source).toContain(
"await prepareNativeSessionBootstrapPersistence(tx,",
);
expect(source).toContain("nativeSessionId: persistedNativeSessionId,");
expect(source).toContain("lockedProfile.sessionCheckpoint != null");
const build = source.slice(
source.indexOf("const nativeExecutionWithCheckpoint ="),
source.indexOf("const nativeSandboxLifecycle ="),
);
expect(build).toContain("previousRun: previousNativeRun,");
});
const embeddedSupport = await getEmbeddedPostgresTestSupport();
const recoveryFakeCodex = resolve(
import.meta.dirname,
"../../../../packages/paperclip-runner/test/fixtures/fake-final-burst-codex-app-server.mjs",
);
(embeddedSupport.supported && existsSync(defaultCapabilityRunnerdBinary())
? it
: it.skip)(
"keeps actual normalized driver events separate from raw maintenance receipts",
async () => {
const database = await startEmbeddedPostgresTestDatabase(
"native-cleanup-topology-",
);
const db = createDb(database.connectionString);
const scratch = await mkdtemp(join(tmpdir(), "native-cleanup-topology-"));
const root = join(scratch, "state");
const home = join(scratch, "home");
const workspace = join(scratch, "workspace");
const companyId = randomUUID(),
agentId = randomUUID(),
issueId = randomUUID(),
runId = randomUUID();
const runnerInstanceId = randomUUID(),
normalizedSessionId = randomUUID();
let session: NativeSession | undefined;
const signal = vi.spyOn(
publicationSignals,
"publishChatPublicationCommitSignal",
);
let bundle:
ReturnType<typeof createCapabilityRunnerdCodexTransport> | undefined;
try {
await mkdir(home);
await mkdir(workspace);
await db
.insert(companies)
.values({
id: companyId,
name: "Cleanup topology",
issuePrefix: "NCT",
});
await db
.insert(agents)
.values({
id: agentId,
companyId,
name: "Fixture",
status: "active",
adapterType: "paperclip_runner",
});
await db
.insert(issues)
.values({
id: issueId,
companyId,
title: "Exact topology",
assigneeAgentId: agentId,
status: "in_progress",
});
await db
.insert(heartbeatRuns)
.values({
id: runId,
companyId,
agentId,
status: "running",
runtimeMode: "native",
nativeIssueId: issueId,
nativeSessionId: normalizedSessionId,
runnerInstanceId,
});
bundle = createCapabilityRunnerdCodexTransport({
stateDirectory: root,
sourceCodexHome: home,
// The packaged runnerd does not imply local Rust test binaries exist.
// Reuse the credential-free provider fixture available in every checkout.
codexCommand: process.execPath,
codexArgs: [recoveryFakeCodex, join(scratch, "fake.json"), "16"],
prpIdentity: {
runId,
runnerInstanceId,
normalizedSessionId,
environmentLeaseId: runId,
turnId: `turn-${runId}`,
itemId: `item-${runId}`,
},
});
const backend = new HarnessDriverBackend(
new CodexAppServerDriver({
runnerInstanceId,
approvalPolicy: "never",
taskEnvelope: createCodexTaskEnvelope({
objective: "Open only the fixture session",
}),
transportFactory: () => bundle!.transport,
environment: { HOME: home, CODEX_HOME: home },
requireProviderSessionIdentity: true,
}),
);
session = await backend.openSession({
identity: {
companyId,
issueId,
agentId,
runId,
sessionId: normalizedSessionId,
},
workingDirectory: workspace,
});
const stream = session.events()[Symbol.asyncIterator]();
const normalized = (await stream.next()).value;
expect(normalized).toMatchObject({
sourceInstanceId: runnerInstanceId,
sourceSeq: 1,
});
expect(normalized.sourceEventId).toBe(`${runnerInstanceId}:${runId}:1`);
expect(normalized.payload).not.toHaveProperty("processId");
const port = new PaperclipControlPlanePort(db, {
companyId,
issueId,
agentId,
runId,
sessionId: normalizedSessionId,
sourceInstanceId: runnerInstanceId,
controlPlaneSourceInstanceId: `${runnerInstanceId}:control`,
completionContractId: randomUUID(),
completionContractSha256: "fixture-contract",
});
await port.appendEvent(normalized);
const original = await db
.select()
.from(heartbeatRunEvents)
.where(eq(heartbeatRunEvents.runId, runId));
expect(original).toHaveLength(1);
const control = JSON.parse(
await readFile(
join(root, "control-plane/control-plane-state.json"),
"utf8",
),
);
const raw = control.committedEvents
.map(
(entry: { envelope: { payload: Record<string, unknown> } }) =>
entry.envelope.payload,
)
.find((event: Record<string, unknown>) =>
["session.started", "session.resumed"].includes(
String(event.eventType),
),
);
expect(raw).toMatchObject({
sourceInstanceId: runnerInstanceId,
sourceSeq: 1,
payload: {
providerSessionId: normalized.payload.driverSessionId,
providerAccountSessionId: normalized.payload.providerSessionId,
},
});
expect(raw.payload.processId).toBeGreaterThan(0);
expect(raw.sourceEventId).not.toBe(normalized.sourceEventId);
// The original normalized seq=1 is already durable. Reusing that
// namespace for the raw wire seq=1 must remain an integrity violation.
await expect(port.appendEvent(raw)).rejects.toMatchObject({
code: "native_event_replay_conflict",
});
signal.mockClear();
const input = {
companyId,
agentId,
runId,
nativeSessionId: normalizedSessionId,
runnerInstanceId,
requestId: `fixture:${randomUUID()}`,
event: raw,
};
await appendRetainedNativeCleanupEvent(db, input);
await appendRetainedNativeCleanupEvent(db, input);
const rows = await db
.select()
.from(heartbeatRunEvents)
.where(eq(heartbeatRunEvents.runId, runId));
expect(rows).toHaveLength(2);
expect(rows.find((row) => row.id === original[0]!.id)).toEqual(
original[0],
);
const receipt = rows.find(
(row) => row.eventType === "native.cleanup.event",
)!;
expect(receipt.sourceSeq).toBe(1);
expect(receipt.sourceInstanceId).not.toBe(runnerInstanceId);
expect(receipt.payload).not.toHaveProperty("prpEvent");
expect(
Object.keys(
receipt.payload!.nativeCleanupEvent as Record<string, unknown>,
).sort(),
).toEqual([
"rawCanonicalSha256",
"rawEventType",
"rawSourceEventId",
"rawSourceInstanceId",
"rawSourceSeq",
"requestId",
"schema",
]);
await expect(
appendRetainedNativeCleanupEvent(db, {
...input,
event: {
...raw,
payload: {
...raw.payload,
privateData: "MUST_NOT_REACH_MAINTENANCE_RECEIPTS",
},
},
}),
).rejects.toMatchObject({ code: "native_event_replay_conflict" });
expect(
await db
.select()
.from(heartbeatRunEvents)
.where(eq(heartbeatRunEvents.runId, runId)),
).toHaveLength(2);
expect(JSON.stringify(receipt.payload)).not.toContain("MUST_NOT_REACH");
expect(signal).not.toHaveBeenCalled();
} finally {
signal.mockRestore();
await session
?.close({ reason: "Dispose exact test session" })
.catch(() => undefined);
await bundle?.transport.close().catch(() => undefined);
await database.cleanup();
await rm(scratch, { recursive: true, force: true });
}
},
30_000,
);
(embeddedSupport.supported &&
existsSync(defaultCapabilityRunnerdBinary()) &&
existsSync(recoveryFakeCodex)
? it
: it.skip)(
"archives a damaged prior epoch before completing guarded same-task replacement with real runnerd",
async () => {
const database = await startEmbeddedPostgresTestDatabase(
"native-damaged-resume-",
);
const db = createDb(database.connectionString);
const scratch = await mkdtemp(join(tmpdir(), "native-damaged-resume-"));
const stateBase = join(scratch, "sessions");
const bin = join(scratch, "bin");
const workspace = join(scratch, "workspace");
const sourceHome = join(scratch, "source-home");
const previousStateBase = process.env.PAPERCLIP_RUNNER_STATE_DIR;
const server = createServer();
let firstSession: NativeSession | undefined;
const runnerDiagnostics: string[] = [];
const onRunnerLog = async (_stream: "stdout" | "stderr", chunk: string) => {
runnerDiagnostics.push(chunk.slice(-4_096));
if (runnerDiagnostics.length > 32) runnerDiagnostics.shift();
};
process.env.PAPERCLIP_RUNNER_STATE_DIR = stateBase;
try {
await Promise.all(
[bin, workspace, sourceHome].map((path) =>
mkdir(path, { recursive: true }),
),
);
// Only the provider boundary is synthetic; driver, runnerd, authority
// rotation, prior-owner DB checks and archive/replacement are real.
const quote = (value: string) => `'${value.replaceAll("'", "'\\''")}'`;
const command = join(bin, "codex");
await writeFile(
command,
`#!/bin/sh\nexec ${quote(process.execPath)} ${quote(recoveryFakeCodex)} "$CODEX_HOME/fake-state.json" 16\n`,
);
await chmod(command, 0o700);
await new Promise<void>((done) => server.listen(0, "127.0.0.1", done));
const address = server.address();
if (!address || typeof address === "string")
throw new Error("Missing test listener");
setupRunnerPrpWebSocketServer(server, {
apiUrl: `http://127.0.0.1:${address.port}`,
});
const makeExecution = (runId: string): NativeExecutionInput => {
const { runtimeContext: _runtimeContext, ...value } = execution(
runId,
workspace,
);
return {
...value,
schema: "paperclip.native-execution-input.v2",
provider: { kind: "codex", model: "gpt-5.6-luna" },
completionContract: {
...value.completionContract,
contract: {
revision: "burst-v1",
objective: "Complete a fresh response after guarded recovery",
criteria: [
{ id: "burst", requirement: "Complete the new response" },
],
},
},
};
};
const firstExecution = makeExecution(previousRunId);
const currentExecution = makeExecution(currentRunId);
expect(() => parseNativeExecutionInput(firstExecution)).not.toThrow();
const runnerInstanceId = randomUUID();
const environment = {
PATH: `${bin}:${process.env.PATH ?? "/usr/bin:/bin"}`,
HOME: sourceHome,
CODEX_HOME: sourceHome,
};
await db.insert(companies).values({
id: companyId,
name: "Damaged recovery",
issuePrefix: "DNR",
});
await db.insert(agents).values({
id: agentId,
companyId,
name: "Recovery runner",
status: "active",
adapterType: "paperclip_runner",
});
await db.insert(issues).values({
id: issueId,
companyId,
title: "Preserve the same task",
assigneeAgentId: agentId,
status: "in_progress",
});
await db.insert(completionContracts).values({
id: currentExecution.completionContract.id,
companyId,
issueId,
revision: 1,
schemaVersion: "paperclip.completion-contract.v1",
policyVersion: "damaged-recovery-v1",
risk: "standard",
completionAuthority: "server_arbiter",
incompleteCriteriaPolicy: "preserve_non_terminal",
contractJson: { ...currentExecution.completionContract.contract },
canonicalSha256: currentExecution.completionContract.sha256,
createdByActorType: "system",
createdByActorId: "test",
});
await db.insert(heartbeatRuns).values([
{
id: previousRunId,
companyId,
agentId,
status: "running",
runtimeMode: "native",
nativeIssueId: issueId,
nativeSessionId: normalizedSessionId,
runnerInstanceId,
completionContractId: firstExecution.completionContract.id,
completionContractSha256: firstExecution.completionContract.sha256,
runnerProfileJson: { nativeExecutionInput: firstExecution },
},
{
id: currentRunId,
companyId,
agentId,
status: "running",
runtimeMode: "native",
nativeIssueId: issueId,
nativeSessionId: normalizedSessionId,
runnerInstanceId,
completionContractId: currentExecution.completionContract.id,
completionContractSha256: currentExecution.completionContract.sha256,
runnerProfileJson: { nativeExecutionInput: currentExecution },
},
]);
const firstBackend = await createRunnerdBackend({
db,
execution: firstExecution,
runnerInstanceId,
runnerEnvironment: environment,
onLog: onRunnerLog,
});
firstSession = await firstBackend.openSession({
identity: {
companyId,
issueId,
agentId,
runId: previousRunId,
sessionId: normalizedSessionId,
},
workingDirectory: workspace,
});
const checkpoint = await firstSession.snapshot();
expect(checkpoint.identity).toEqual({
companyId,
issueId,
agentId,
runId: previousRunId,
sessionId: normalizedSessionId,
});
await firstSession.close({
reason: "Establish a suspended test-only historical root",
});
firstSession = undefined;
const [stateKey] = (await readdir(stateBase)).filter((name) =>
/^[a-f0-9]{64}$/.test(name),
);
expect(stateKey).toBeDefined();
const root = join(stateBase, stateKey!);
const runnerPath = join(root, "runner", "runner-state.json");
const providerPath = join(root, "runner", "codex-provider-state.json");
const runner = JSON.parse(await readFile(runnerPath, "utf8"));
const provider = JSON.parse(await readFile(providerPath, "utf8"));
expect(runner.lifecycle).toBe("suspended");
// Reproduce only in a generated disposable root the historical failure:
// an unacknowledged input whose digest predates bounded sanitization.
const badPayload = {
semantic_tool: {
schema: "paperclip.prp.semantic_tool.v1",
schemaVersion: 1,
phase: "input",
input: { summary: "bounded historical answer" },
content: { digest: `sha256:${"0".repeat(64)}` },
},
};
const envelope = {
protocol: "paperclip.runner",
version: 1,
kind: "event",
runnerInstanceId: runner.runnerInstanceId,
environmentLeaseId: runner.environmentLeaseId,
runId: previousRunId,
normalizedSessionId,
turnId: runner.turnId,
itemId: runner.itemId,
payload: {
schema: "paperclip.prp.event.v1",
sourceEventId: "historical-bad-input-44",
sourceSeq: 44,
sourceInstanceId: runner.runnerInstanceId,
sourceKind: "runner",
runId: previousRunId,
normalizedSessionId,
turnId: runner.turnId,
itemId: runner.itemId,
eventType: "semantic_tool.input",
schemaVersion: 1,
priority: 0,
emittedAt: "2026-09-08T00:00:00.000Z",
payload: badPayload,
},
};
runner.ackedSourceSeq = 43;
runner.nextSourceSeq = 45;
runner.outbox = [
{
sourceSeq: 44,
priority: 0,
eventType: "semantic_tool.input",
envelope,
byteSize: Buffer.byteLength(JSON.stringify(envelope)),
},
];
provider.pendingEvents = [
{
executorEventId: "codex_provider_0000000000000044",
eventType: "semantic_tool.input",
priority: "p0",
payload: badPayload,
},
];
provider.nextProviderEventSeq = 45;
await writeFile(runnerPath, JSON.stringify(runner));
await writeFile(providerPath, JSON.stringify(provider));
const damagedRunnerBytes = await readFile(runnerPath);
const damagedProviderBytes = await readFile(providerPath);
await expect(
createRunnerdBackend({
db,
execution: currentExecution,
runnerInstanceId,
runnerEnvironment: environment,
}),
).rejects.toThrow("runner_state_identity_mismatch");
expect(await readFile(runnerPath, "utf8")).toBe(
damagedRunnerBytes.toString(),
);
expect(await readdir(root)).not.toContain("authority-epochs");
const source = previousRun({
nativeExecutionInput: firstExecution,
sessionCheckpoint: checkpoint,
});
await db
.update(heartbeatRuns)
.set({ status: "failed", runnerProfileJson: source.runnerProfileJson })
.where(eq(heartbeatRuns.id, previousRunId));
const selected = await findNativeSessionResumeRun(db, {
companyId,
agentId,
issueId,
normalizedSessionId,
currentRunId,
beforeCreatedAt: new Date(),
});
expect(selected?.id).toBe(previousRunId);
const rebound = rebindNativeSessionCheckpoint({
previousRun: selected!,
currentExecution,
});
expect(rebound).toMatchObject({
cursor: null,
semanticResult: null,
activeTurnId: null,
providerRecoveryPolicy: "allow_replacement_after_resume_failure",
});
expect(rebound?.identity).toEqual({
companyId,
issueId,
agentId,
runId: currentRunId,
sessionId: normalizedSessionId,
});
const backend = await createRunnerdBackend({
db,
execution: currentExecution,
runnerInstanceId,
runnerEnvironment: environment,
onLog: onRunnerLog,
});
let continuity: Record<string, unknown> | undefined;
const controlPlaneInstanceId = randomUUID();
const port = new PaperclipControlPlanePort(db, {
companyId,
issueId,
runId: currentRunId,
agentId,
sessionId: normalizedSessionId,
completionContractId: currentExecution.completionContract.id,
completionContractSha256: currentExecution.completionContract.sha256,
sourceInstanceId: runnerInstanceId,
controlPlaneSourceInstanceId: controlPlaneInstanceId,
});
await expect(
executeNativeSession({
input: currentExecution,
backend,
persistedSession: rebound!,
runnerInstanceId,
controlPlaneInstanceId,
timeoutMs: 20_000,
controlPlane: port,
async onContinuityBreak(value) {
continuity = value;
},
}).catch(async (error: unknown) => {
const eventRows = await db
.select({
eventType: heartbeatRunEvents.eventType,
payload: heartbeatRunEvents.payload,
})
.from(heartbeatRunEvents)
.where(eq(heartbeatRunEvents.runId, currentRunId));
const eventCodes = eventRows.slice(-32).map((event) => ({
eventType: event.eventType,
code: event.payload?.code ?? null,
}));
const fakeProvider = await readFile(
join(root, "codex-home", "fake-state.json"),
"utf8",
).then(JSON.parse, () => null);
throw new Error(
`${error instanceof Error ? error.message : String(error)}\nDisposable recovery fixture runner diagnostics:\n${runnerDiagnostics.join("").slice(-12_000)}\nPersisted event codes: ${JSON.stringify(eventCodes)}\nFake provider state: ${JSON.stringify(fakeProvider)}`,
{ cause: error },
);
}),
).resolves.toMatchObject({
result: {
summary: "Fixture complete.",
reportedWorkDisposition: "done",
},
terminal: { runTerminalState: "succeeded" },
normalizedSessionId,
});
expect(continuity).toMatchObject({
// The daemon can reject the damaged retained input during startup,
// before attach gets a chance to reject the unsettled provider session.
// Both refusal paths must preserve the exact archived evidence below.
reason: expect.stringMatching(
/run\.attach requires a settled Codex provider session|semantic tool input content digest does not match its transmitted input/,
),
previousDriverSessionId: checkpoint.sessionId,
});
const [epoch] = await readdir(join(root, "authority-epochs"));
const digest = (value: Buffer) =>
createHash("sha256").update(value).digest("hex");
expect(
digest(
await readFile(
join(root, "authority-epochs", epoch!, "runner-state.json"),
),
),
).toBe(digest(damagedRunnerBytes));
const [continuityArchive] = await readdir(
join(root, "continuity-breaks"),
);
const archivedProvider = JSON.parse(
await readFile(
join(
root,
"continuity-breaks",
continuityArchive!,
"runner",
"codex-provider-state.json",
),
"utf8",
),
);
// Restoration may append a lifecycle notice, but must neither consume
// nor rewrite the old semantic input to make attachment succeed.
expect(
archivedProvider.pendingEvents.filter(
(event: { eventType: string }) =>
event.eventType === "semantic_tool.input",
),
).toEqual(JSON.parse(damagedProviderBytes.toString()).pendingEvents);
const completedProvider = JSON.parse(
await readFile(join(root, "codex-home", "fake-state.json"), "utf8"),
);
expect(completedProvider.nextTurn).toBe(1);
expect(completedProvider.turns["final-burst-turn-1"]).toMatchObject({
status: "completed",
deltaCount: 16,
});
const priorProvider = JSON.parse(
await readFile(
join(
root,
"continuity-breaks",
continuityArchive!,
"codex-home",
"fake-state.json",
),
"utf8",
),
);
expect(priorProvider.nextTurn).toBe(0);
const results = await db
.select()
.from(nativeRunResults)
.where(eq(nativeRunResults.runId, currentRunId));
expect(results).toHaveLength(1);
// Prove the maintenance anchor against an actual completed composition:
// the DB owns normalized driver events and the accepted result, whereas
// the retained controller owns distinct raw provider/tool event IDs.
const [completedRun] = await db
.select()
.from(heartbeatRuns)
.where(eq(heartbeatRuns.id, currentRunId));
const anchorEvents = await db
.select()
.from(heartbeatRunEvents)
.where(eq(heartbeatRunEvents.runId, currentRunId));
const control = JSON.parse(
await readFile(
join(root, "control-plane", "control-plane-state.json"),
"utf8",
),
);
const rawIdentity = control.committedEvents
.map(
(entry: { envelope: { payload: Record<string, unknown> } }) =>
entry.envelope.payload,
)
.find((event: Record<string, unknown>) =>
["session.started", "session.resumed"].includes(
String(event.eventType),
),
);
expect(rawIdentity).toBeDefined();
expect(
retainedNativeCleanupJournalMatches({
run: completedRun!,
execution: currentExecution,
accepted: results[0]!,
control,
providerSessionId: rawIdentity.payload.providerSessionId,
providerAccountSessionId:
rawIdentity.payload.providerAccountSessionId,
persistedEvents: anchorEvents,
}),
).toBe(true);
expect(results[0]).toMatchObject({
companyId,
issueId,
runId: currentRunId,
schemaStatus: "accepted",
resultJson: {
result: { summary: "Fixture complete." },
terminal: { runTerminalState: "succeeded" },
},
});
const sourceResults = await db
.select({ id: nativeRunResults.id })
.from(nativeRunResults)
.where(eq(nativeRunResults.runId, previousRunId));
expect(sourceResults).toHaveLength(0);
const persistedEvents = await db
.select({ sourceEventId: heartbeatRunEvents.sourceEventId })
.from(heartbeatRunEvents)
.where(eq(heartbeatRunEvents.runId, currentRunId));
expect(persistedEvents.length).toBeGreaterThan(0);
expect(persistedEvents.map((event) => event.sourceEventId)).not.toContain(
"historical-bad-input-44",
);
const [task] = await db
.select({ id: issues.id, assigneeAgentId: issues.assigneeAgentId })
.from(issues)
.where(eq(issues.id, issueId));
expect(task).toEqual({ id: issueId, assigneeAgentId: agentId });
} finally {
await firstSession
?.close({ reason: "Recovery fixture cleanup" })
.catch(() => undefined);
runnerPrpWebSocketInternals.resetForTests();
server.closeAllConnections();
await new Promise<void>((done) => server.close(() => done()));
if (previousStateBase === undefined)
delete process.env.PAPERCLIP_RUNNER_STATE_DIR;
else process.env.PAPERCLIP_RUNNER_STATE_DIR = previousStateBase;
await database.cleanup();
await rm(scratch, { recursive: true, force: true });
}
},
60_000,
);
(embeddedSupport.supported ? describe : describe.skip)(
"native session recovery database orchestration",
() => {
it("uses scoped latest checkpoints, preserves progress barriers, and guards bootstrap persistence after the row lock", async () => {
const database = await startEmbeddedPostgresTestDatabase(
"paperclip-native-resume-selection-",
);
const db = createDb(database.connectionString);
try {
const otherCompany = randomUUID(),
otherAgent = randomUUID(),
otherIssue = randomUUID();
await db.insert(companies).values([
{ id: companyId, name: "Session recovery", issuePrefix: "NRS" },
{ id: otherCompany, name: "Other company", issuePrefix: "OTHER" },
]);
await db.insert(agents).values([
{ id: agentId, companyId, name: "Native runner" },
{ id: otherAgent, companyId: otherCompany, name: "Other agent" },
]);
await db.insert(issues).values([
{ id: issueId, companyId, title: "Retain this task" },
{ id: otherIssue, companyId, title: "Other task" },
]);
const at = (second: number) =>
new Date(Date.UTC(2026, 8, 8, 0, 0, second));
const source = {
...previousRun(),
runtimeMode: "native",
nativeIssueId: issueId,
status: "failed",
createdAt: at(0),
runnerInstanceId: randomUUID(),
};
const unused = {
companyId,
agentId,
runtimeMode: "native",
nativeIssueId: issueId,
nativeSessionId: normalizedSessionId,
status: "failed",
runnerProfileJson: {},
};
const bootstrapId = randomUUID();
const futureId = randomUUID();
await db.insert(heartbeatRuns).values([
source,
{ ...unused, id: bootstrapId, createdAt: at(2) },
{
...unused,
id: currentRunId,
status: "running",
createdAt: at(10),
},
{
...unused,
id: randomUUID(),
companyId: otherCompany,
createdAt: at(3),
status: "running",
},
{
...unused,
id: randomUUID(),
agentId: otherAgent,
createdAt: at(4),
status: "running",
},
{
...unused,
id: randomUUID(),
nativeIssueId: otherIssue,
createdAt: at(5),
status: "running",
},
{
...unused,
id: randomUUID(),
nativeSessionId: randomUUID(),
createdAt: at(6),
status: "running",
},
{
...unused,
id: futureId,
createdAt: at(11),
},
]);
const selection = {
companyId,
agentId,
issueId,
normalizedSessionId,
currentRunId,
beforeCreatedAt: at(10),
};
expect((await findNativeSessionResumeRun(db, selection))?.id).toBe(
previousRunId,
);
await db
.update(heartbeatRuns)
.set({ runnerProfileJson: source.runnerProfileJson })
.where(eq(heartbeatRuns.id, futureId));
expect(await findNativeSessionResumeRun(db, selection)).toBeNull();
await db
.update(heartbeatRuns)
.set({ runnerProfileJson: {}, status: "running" })
.where(eq(heartbeatRuns.id, futureId));
expect(await findNativeSessionResumeRun(db, selection)).toBeNull();
await db
.update(heartbeatRuns)
.set({ status: "failed" })
.where(eq(heartbeatRuns.id, futureId));
expect((await findNativeSessionResumeRun(db, selection))?.id).toBe(
previousRunId,
);
await db.insert(heartbeatRunEvents).values({
companyId,
agentId,
runId: bootstrapId,
seq: 1,
eventType: "session.started",
});
expect(await findNativeSessionResumeRun(db, selection)).toBeNull();
const incompatibleId = randomUUID();
await db.insert(heartbeatRuns).values({
...unused,
id: incompatibleId,
createdAt: at(7),
runnerProfileJson: {
...source.runnerProfileJson,
nativeToolContractFingerprint: "stale",
},
});
const incompatible = await findNativeSessionResumeRun(db, selection);
expect(incompatible?.id).toBe(incompatibleId);
expect(
rebindNativeSessionCheckpoint({
previousRun: incompatible!,
currentExecution: execution(currentRunId),
}),
).toBeNull();
const fresh = buildNativeExecutionWithCheckpoint({
previousRun: null,
normalizedSessionId,
buildExecution: ({ normalizedSessionId: selected }) => {
const current = execution(currentRunId);
return {
...current,
session: { ...current.session, normalizedSessionId: selected },
};
},
});
await db.transaction(async (tx) => {
const [locked] = await tx
.select()
.from(heartbeatRuns)
.where(eq(heartbeatRuns.id, currentRunId))
.for("update");
const selected = await prepareNativeSessionBootstrapPersistence(tx, {
run: locked,
selectedSessionId: fresh.normalizedSessionId,
execution: fresh.execution,
restoringCheckpoint: false,
});
await tx
.update(heartbeatRuns)
.set({
nativeSessionId: selected,
runnerProfileJson: { nativeExecutionInput: fresh.execution },
})
.where(eq(heartbeatRuns.id, locked.id));
});
const [persisted] = await db
.select()
.from(heartbeatRuns)
.where(eq(heartbeatRuns.id, currentRunId));
expect(persisted.nativeSessionId).toBe(fresh.normalizedSessionId);
expect(persisted.nativeSessionId).not.toBe(normalizedSessionId);
await expect(
db.transaction(async (tx) => {
const [locked] = await tx
.select()
.from(heartbeatRuns)
.where(eq(heartbeatRuns.id, currentRunId))
.for("update");
return prepareNativeSessionBootstrapPersistence(tx, {
run: locked,
selectedSessionId: fresh.normalizedSessionId,
execution: fresh.execution,
restoringCheckpoint: false,
});
}),
).resolves.toBe(fresh.normalizedSessionId);
await expect(
db.transaction(async (tx) => {
const [locked] = await tx
.select()
.from(heartbeatRuns)
.where(eq(heartbeatRuns.id, currentRunId))
.for("update");
const changedExecution = structuredClone(fresh.execution);
changedExecution.task.prompt = "Changed admission";
return prepareNativeSessionBootstrapPersistence(tx, {
run: locked,
selectedSessionId: fresh.normalizedSessionId,
execution: changedExecution,
restoringCheckpoint: false,
});
}),
).rejects.toThrow("native_execution_input_persisted_binding_mismatch");
const [preserved] = await db
.select()
.from(heartbeatRuns)
.where(eq(heartbeatRuns.id, previousRunId));
expect(preserved.runnerProfileJson).toEqual(source.runnerProfileJson);
const lateId = randomUUID();
await db
.insert(heartbeatRuns)
.values({ ...unused, id: lateId, createdAt: at(11) });
expect((await nativeSessionProviderEvidence(db, [lateId])).size).toBe(
0,
);
let unlock!: () => void;
let locked!: () => void;
const lockAcquired = new Promise<void>((resolve) => {
locked = resolve;
});
const release = new Promise<void>((resolve) => {
unlock = resolve;
});
const writer = db.transaction(async (tx) => {
await tx
.select()
.from(heartbeatRuns)
.where(eq(heartbeatRuns.id, lateId))
.for("update");
locked();
await release;
await tx.insert(heartbeatRunEvents).values({
companyId,
agentId,
runId: lateId,
seq: 1,
eventType: "session.started",
});
});
let attempt: Promise<unknown> | undefined;
try {
await lockAcquired;
const applicationName = `native-resume-lock-${randomUUID()}`;
attempt = db
.transaction(async (tx) => {
await tx.execute(
sql`select set_config('application_name', ${applicationName}, true)`,
);
const [row] = await tx
.select()
.from(heartbeatRuns)
.where(eq(heartbeatRuns.id, lateId))
.for("update");
return prepareNativeSessionBootstrapPersistence(tx, {
run: row,
selectedSessionId: randomUUID(),
execution: execution(lateId),
restoringCheckpoint: false,
});
})
.then(
() => null,
(error: unknown) => error,
);
await expect
.poll(async () => {
const rows = await db.execute<{ blocked: boolean }>(sql`
select exists (
select 1 from pg_stat_activity
where application_name = ${applicationName}
and wait_event_type = 'Lock'
and cardinality(pg_blocking_pids(pid)) > 0
) as blocked
`);
return rows[0]?.blocked;
})
.toBe(true);
unlock();
await writer;
expect(await attempt).toMatchObject({
message: "native_session_bootstrap_identity_conflict",
});
const [unchanged] = await db
.select()
.from(heartbeatRuns)
.where(eq(heartbeatRuns.id, lateId));
expect(unchanged.nativeSessionId).toBe(normalizedSessionId);
} finally {
unlock();
await Promise.all([writer, attempt]);
}
} finally {
await database.cleanup();
}
}, 60_000);
},
);
describe("rebindNativeSessionCheckpoint", () => {
it("rotates a carried session id when no checkpoint source exists", () => {
const calls: boolean[] = [];
const result = buildNativeExecutionWithCheckpoint({
previousRun: null,
normalizedSessionId,
buildExecution: (options) => {
calls.push(options.resumedSession);
const current = execution(currentRunId);
return {
...current,
session: {
...current.session,
normalizedSessionId: options.normalizedSessionId,
},
task: {
...current.task,
prompt: options.resumedSession
? "Compact delta"
: "Full task context",
},
};
},
});
expect(calls.every((resumed) => !resumed)).toBe(true);
expect(result.checkpoint).toBeNull();
expect(result.normalizedSessionId).not.toBe(normalizedSessionId);
expect(result.execution.session.normalizedSessionId).toBe(
result.normalizedSessionId,
);
expect(result.execution.task.prompt).toBe("Full task context");
expect(
nativeSessionIdForBootstrapPersistence({
run: {
nativeSessionId: normalizedSessionId,
processPid: null,
processGroupId: null,
processStartedAt: null,
runnerProfileJson: {},
},
selectedSessionId: result.normalizedSessionId,
hasProviderEvents: false,
}),
).toBe(result.normalizedSessionId);
});
it("does not rotate an admitted or authority-bearing session id", () => {
const unused = {
nativeSessionId: normalizedSessionId,
processPid: null,
processGroupId: null,
processStartedAt: null,
runnerProfileJson: {},
};
for (const run of [
{
...unused,
runnerProfileJson: { nativeExecutionInput: execution(currentRunId) },
},
{ ...unused, runnerProfileJson: { sessionCheckpoint: {} } },
{ ...unused, processPid: 123 },
{ ...unused, processGroupId: 123 },
{ ...unused, processStartedAt: new Date() },
]) {
expect(() =>
nativeSessionIdForBootstrapPersistence({
run,
selectedSessionId: previousRunId,
hasProviderEvents: false,
}),
).toThrow("native_session_bootstrap_identity_conflict");
}
expect(() =>
nativeSessionIdForBootstrapPersistence({
run: unused,
selectedSessionId: previousRunId,
hasProviderEvents: true,
}),
).toThrow("native_session_bootstrap_identity_conflict");
expect(
nativeSessionIdForBootstrapPersistence({
run: {
...unused,
runnerProfileJson: { nativeExecutionInput: execution(currentRunId) },
},
selectedSessionId: normalizedSessionId,
hasProviderEvents: true,
}),
).toBe(normalizedSessionId);
});
it("recovers the latest exact checkpoint past only unused bootstrap failures", () => {
const source = {
...previousRun(),
nativeIssueId: issueId,
runtimeMode: "native",
status: "failed",
createdAt: new Date(0),
processPid: null,
processGroupId: null,
processStartedAt: null,
};
const unusedFailure = {
...source,
id: "failed-bootstrap",
runnerProfileJson: {
nativeExecutionInput: execution("failed-bootstrap"),
},
};
const original = structuredClone(source);
const selected = selectNativeSessionResumeRun({
runs: [unusedFailure, source],
companyId,
agentId,
issueId,
normalizedSessionId,
currentRunId,
beforeCreatedAt: new Date(100),
providerEvidenceRunIds: new Set(),
});
expect(selected).toBe(source);
expect(
rebindNativeSessionCheckpoint({
previousRun: selected!,
currentExecution: execution(currentRunId),
}),
).toMatchObject({
sessionId: "provider-thread-123",
identity: { runId: currentRunId, sessionId: normalizedSessionId },
});
expect(source).toEqual(original);
});
it("never skips a newer provider authority or incompatible checkpoint", () => {
const source = {
...previousRun(),
nativeIssueId: issueId,
runtimeMode: "native",
status: "succeeded",
createdAt: new Date(0),
processPid: null as number | null,
processGroupId: null,
processStartedAt: null,
};
const newer = { ...source, id: "newer", runnerProfileJson: {} };
const select = (
candidate: typeof source | typeof newer,
hasEvents = false,
) =>
selectNativeSessionResumeRun({
runs: [candidate, source],
companyId,
agentId,
issueId,
normalizedSessionId,
currentRunId,
beforeCreatedAt: new Date(100),
providerEvidenceRunIds: new Set(hasEvents ? [candidate.id] : []),
});
expect(select(newer, true)).toBeNull();
expect(select({ ...newer, processPid: 123 })).toBeNull();
expect(select({ ...newer, status: "running" })).toBeNull();
const incompatible = {
...source,
id: "newer",
runnerProfileJson: {
...source.runnerProfileJson,
nativeToolContractFingerprint: "stale",
},
};
expect(select(incompatible)).toBe(incompatible);
expect(
rebindNativeSessionCheckpoint({
previousRun: select(incompatible)!,
currentExecution: execution(currentRunId),
}),
).toBeNull();
});
it("does not borrow checkpoints across company, agent, issue, or normalized session", () => {
const source = {
...previousRun(),
nativeIssueId: issueId,
runtimeMode: "native",
status: "succeeded",
createdAt: new Date(0),
processPid: null,
processGroupId: null,
processStartedAt: null,
};
for (const changed of [
{ companyId: currentRunId },
{ agentId: currentRunId },
{ nativeIssueId: currentRunId },
{ nativeSessionId: currentRunId },
{ id: currentRunId },
]) {
expect(
selectNativeSessionResumeRun({
runs: [{ ...source, ...changed }],
companyId,
agentId,
issueId,
normalizedSessionId,
currentRunId,
beforeCreatedAt: new Date(100),
providerEvidenceRunIds: new Set(),
}),
).toBeNull();
}
});
it("does not resume across a work-mode tool-surface change", () => {
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun(),
currentExecution: execution(currentRunId, "/workspace", "ask"),
}),
).toBeNull();
});
it.each(["External chat message received", "issue_comment_added"])(
"rebuilds full task context when a %s checkpoint is corrupt",
(reason) => {
const calls: boolean[] = [];
const result = buildNativeExecutionWithCheckpoint({
previousRun: previousRun({ sessionCheckpoint: {} }),
normalizedSessionId,
buildExecution: (options) => {
calls.push(options.resumedSession);
return buildNativeExecutionInput({
companyId,
runId: currentRunId,
issue: {
id: issueId,
identifier: "DOT-2",
title: "Current task",
description: "Full task instructions",
workMode: "standard",
},
taskPrompt: options.resumedSession
? "Compact context"
: "Full task instructions",
wakePayload: {
reason,
issue: {
id: issueId,
title: "Current task",
workMode: "standard",
},
},
resumedSession: options.resumedSession,
agentId,
workspace: {
id: currentRunId,
cwd: "/workspace",
repoUrl: null,
repoRef: null,
branchName: null,
},
normalizedSessionId: options.normalizedSessionId,
provider: "codex",
completionContract: execution(currentRunId).completionContract,
runtimeContext: nativeRuntimeContextFixture(),
});
},
});
expect(calls).toEqual([true, false]);
expect(result.checkpoint).toBeNull();
expect(result.execution.session.normalizedSessionId).not.toBe(
normalizedSessionId,
);
expect(result.execution.task.prompt).toContain("Full task instructions");
expect(result.execution.task.prompt).not.toContain(
"Paperclip Resume Delta",
);
expect(result.execution.task.prompt).not.toContain("Compact context");
},
);
it.each([
["paperclip.native-execution-input.v4", "paperclip.native-execution-input.v5"],
["paperclip.native-execution-input.v5", "paperclip.native-execution-input.v4"],
] as const)("retains a recoverable %s session when the constructor defaults to %s", (priorSchema, currentSchema) => {
const prior = previousRun();
const profile = prior.runnerProfileJson as Record<string, unknown>;
profile.nativeExecutionInput = { ...execution(previousRunId), schema: priorSchema };
const checkpoint = profile.sessionCheckpoint as Record<string, unknown>;
checkpoint.goal = { status: "paused", objective: "Preserve the existing durable work" };
const before = structuredClone(prior);
const result = buildNativeExecutionWithCheckpoint({
previousRun: prior,
normalizedSessionId,
buildExecution: ({ normalizedSessionId: sessionId, resumedSession }) => parseNativeExecutionInput({
...execution(currentRunId), schema: currentSchema,
session: { ...execution(currentRunId).session, normalizedSessionId: sessionId },
continuationPrompt: resumedSession ? "New direction only; do not replay completed actions" : null,
}),
});
expect(result.execution.schema).toBe(priorSchema);
expect(result.normalizedSessionId).toBe(normalizedSessionId);
expect(result.checkpoint).toMatchObject({
providerSessionId: "provider-thread-123",
providerRecoveryPolicy: "same_session_only",
goal: { status: "paused", objective: "Preserve the existing durable work" },
});
expect(prior).toEqual(before);
});
it("keeps a valid checkpoint and does not rebuild the resumed task", () => {
const calls: boolean[] = [];
const result = buildNativeExecutionWithCheckpoint({
previousRun: previousRun(),
normalizedSessionId,
buildExecution: (options) => {
calls.push(options.resumedSession);
return execution(currentRunId);
},
});
expect(calls).toEqual([true]);
expect(result.checkpoint?.sessionId).toBe("provider-thread-123");
expect(result.execution.session.normalizedSessionId).toBe(
normalizedSessionId,
);
});
it("rebuilds full context when the persisted provider tool contract is stale", () => {
const calls: boolean[] = [];
const result = buildNativeExecutionWithCheckpoint({
previousRun: previousRun({
nativeToolContractFingerprint: "sha256:stale",
}),
normalizedSessionId,
buildExecution: (options) => {
calls.push(options.resumedSession);
const current = execution(currentRunId);
return {
...current,
session: {
...current.session,
normalizedSessionId: options.normalizedSessionId,
},
task: {
...current.task,
prompt: options.resumedSession
? "Paperclip Resume Delta"
: "Full task instructions",
},
};
},
});
expect(calls).toEqual([true, false]);
expect(result.checkpoint).toBeNull();
expect(result.execution.task.prompt).toBe("Full task instructions");
expect(result.normalizedSessionId).not.toBe(normalizedSessionId);
});
it.each([
{
contract: "completion descriptions",
// Deployed v8 / finish_response_wake_concrete_object.v2 local catalog.
retainedFingerprint:
"sha256:5b7b302db36f7ed6686f9ea1ba70bbf79ebd7fabf86953b548d966a2bc38b648",
},
{
contract: "native completion tool guidance",
// Deployed v13 local catalog before canonical finish/block descriptions.
retainedFingerprint:
"sha256:68a51d34e091c55ee5d0d2b563153454dd727d72db16e6a27c358d342ae489c9",
},
{
contract: "task-bound human-input description",
// Deployed v9 still advertises the generic mock-task question description.
retainedFingerprint:
"sha256:b64efcd063a575925aa95dbd2a20953386eaa760f05b0e0e73b4ae04a97679b0",
},
])(
"refreshes retained $contract without changing the Paperclip task or prior history",
({ retainedFingerprint }) => {
expect(NATIVE_TOOL_CONTRACT_FINGERPRINT).not.toBe(retainedFingerprint);
const prior = previousRun({
nativeToolContractFingerprint: retainedFingerprint,
});
const priorSnapshot = structuredClone(prior);
const modes: boolean[] = [];
const result = buildNativeExecutionWithCheckpoint({
previousRun: prior,
normalizedSessionId,
buildExecution: (options) => {
modes.push(options.resumedSession);
const current = execution(currentRunId);
return {
...current,
session: {
...current.session,
normalizedSessionId: options.normalizedSessionId,
},
task: {
...current.task,
prompt: options.resumedSession
? "Paperclip Resume Delta"
: "Full context for the same Paperclip task",
},
};
},
});
expect(modes).toEqual([true, false]);
expect(result.checkpoint).toBeNull();
expect(result.normalizedSessionId).not.toBe(normalizedSessionId);
expect(result.execution.binding).toMatchObject({
companyId,
issueId,
agentId,
runId: currentRunId,
});
expect(result.execution.workspace).toEqual(
execution(currentRunId).workspace,
);
expect(result.execution.task.prompt).toBe(
"Full context for the same Paperclip task",
);
// No deletion/reset of the existing provider checkpoint or Paperclip history.
expect(prior).toEqual(priorSnapshot);
expect(prior.runnerProfileJson.sessionCheckpoint.sessionId).toBe(
"provider-thread-123",
);
},
);
it("rotates a provider thread created while the current-wake reader was conditionally advertised", () => {
expect(CONDITIONAL_READER_TOOL_CONTRACT_FINGERPRINT).not.toBe(
NATIVE_TOOL_CONTRACT_FINGERPRINT,
);
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun({
nativeToolContractFingerprint:
CONDITIONAL_READER_TOOL_CONTRACT_FINGERPRINT,
}),
currentExecution: execution(currentRunId),
}),
).toBeNull();
});
it("rotates a provider thread that predates same-conversation attachment reuse", () => {
expect(PRE_CHAT_ATTACHMENT_REUSE_TOOL_CONTRACT_FINGERPRINT).not.toBe(
NATIVE_TOOL_CONTRACT_FINGERPRINT,
);
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun({
nativeToolContractFingerprint:
PRE_CHAT_ATTACHMENT_REUSE_TOOL_CONTRACT_FINGERPRINT,
}),
currentExecution: execution(currentRunId),
}),
).toBeNull();
});
it("binds the provider tool catalog to the local or remote execution target", () => {
const remoteFingerprint = nativeToolContractFingerprintForTarget("remote");
expect(remoteFingerprint).not.toBe(NATIVE_TOOL_CONTRACT_FINGERPRINT);
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun(),
currentExecution: execution(currentRunId),
executionTargetKind: "remote",
}),
).toBeNull();
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun({
nativeToolContractFingerprint: remoteFingerprint,
}),
currentExecution: execution(currentRunId),
executionTargetKind: "remote",
}),
).not.toBeNull();
});
it("rotates provider threads whose retained catalog cannot inspect historical files", () => {
expect(PRE_CHAT_ATTACHMENT_READ_TOOL_CONTRACT_FINGERPRINT).not.toBe(
NATIVE_TOOL_CONTRACT_FINGERPRINT,
);
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun({
nativeToolContractFingerprint:
PRE_CHAT_ATTACHMENT_READ_TOOL_CONTRACT_FINGERPRINT,
}),
currentExecution: execution(currentRunId),
}),
).toBeNull();
});
it("rotates direct provider threads whose retained catalog cannot ask structured questions", () => {
expect(PRE_STRUCTURED_HUMAN_INPUT_TOOL_CONTRACT_FINGERPRINT).not.toBe(
NATIVE_TOOL_CONTRACT_FINGERPRINT,
);
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun({
nativeToolContractFingerprint:
PRE_STRUCTURED_HUMAN_INPUT_TOOL_CONTRACT_FINGERPRINT,
}),
currentExecution: execution(currentRunId),
}),
).toBeNull();
});
it("rotates direct provider threads whose retained completion tool cannot yield for a response", () => {
expect(PRE_RESPONSE_WAKE_YIELD_TOOL_CONTRACT_FINGERPRINT).not.toBe(
NATIVE_TOOL_CONTRACT_FINGERPRINT,
);
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun({
nativeToolContractFingerprint:
PRE_RESPONSE_WAKE_YIELD_TOOL_CONTRACT_FINGERPRINT,
}),
currentExecution: execution(currentRunId),
}),
).toBeNull();
});
it("rotates provider threads whose retained attachment tools lack explicit invocation guidance", () => {
expect(LIST_CHAT_ATTACHMENTS_TOOL_DEFINITION.description).toContain(
"Call with {}",
);
expect(LIST_CHAT_ATTACHMENTS_TOOL_DEFINITION.description).toContain(
"1 through 50",
);
expect(REUSE_CHAT_ATTACHMENT_TOOL_DEFINITION.description).toContain(
"All four arguments are required",
);
expect(REUSE_CHAT_ATTACHMENT_TOOL_DEFINITION.description).toContain(
"same key unchanged on every retry",
);
expect(
PRE_EXPLICIT_CHAT_ATTACHMENT_GUIDANCE_TOOL_CONTRACT_FINGERPRINT,
).not.toBe(NATIVE_TOOL_CONTRACT_FINGERPRINT);
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun({
nativeToolContractFingerprint:
PRE_EXPLICIT_CHAT_ATTACHMENT_GUIDANCE_TOOL_CONTRACT_FINGERPRINT,
}),
currentExecution: execution(currentRunId),
}),
).toBeNull();
});
it("permits legacy retry rebinding only before the replacement acquired authority", () => {
const source = {
runtimeMode: "native",
status: "interrupted",
nativeSessionId: normalizedSessionId,
};
const replacement = {
processPid: null,
processGroupId: null,
processStartedAt: null,
runnerProfileJson: {},
};
expect(
isUnusedLegacyNativeRetryReplacement({
source,
replacement,
hasProviderEvents: false,
}),
).toBe(true);
expect(
isUnusedLegacyNativeRetryReplacement({
source,
replacement: { ...replacement, processPid: 123 },
hasProviderEvents: false,
}),
).toBe(false);
expect(
isUnusedLegacyNativeRetryReplacement({
source,
replacement,
hasProviderEvents: true,
}),
).toBe(false);
expect(
isUnusedLegacyNativeRetryReplacement({
source,
replacement: {
...replacement,
runnerProfileJson: {
sessionCheckpoint: { providerSessionId: "claimed" },
},
},
hasProviderEvents: false,
}),
).toBe(false);
});
it("retains provider identity but clears prior turn and event state", () => {
const rebound = rebindNativeSessionCheckpoint({
previousRun: previousRun(),
currentExecution: execution(currentRunId),
});
expect(rebound).toMatchObject({
sessionId: "provider-thread-123",
providerSessionId: "provider-thread-123",
driverKind: "codex_app_server",
cursor: null,
semanticResult: null,
terminal: null,
activeTurnId: null,
terminalTurns: [],
pendingRuntimeRequests: [],
providerRecoveryPolicy: "allow_replacement_after_resume_failure",
identity: {
runId: currentRunId,
sessionId: normalizedSessionId,
companyId,
issueId,
agentId,
},
});
});
it("allows a provider replacement only after a durable response wake", () => {
const source = previousRun();
const profile = source.runnerProfileJson as Record<string, unknown>;
const checkpoint = profile.sessionCheckpoint as Record<string, unknown>;
checkpoint.semanticResult = {
schema: "paperclip.run_result.v1",
reportedWorkDisposition: "yielded",
summary: "Waiting for a response.",
continuation: {
kind: "response_wake",
idempotencyKey: "interaction-response:one",
},
};
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: execution(currentRunId),
}),
).toMatchObject({
providerRecoveryPolicy: "allow_replacement_after_governed_wait",
semanticResult: null,
activeTurnId: null,
});
});
it("requires exact provider continuity for an unfinished session goal", () => {
const source = previousRun();
const profile = source.runnerProfileJson as Record<string, unknown>;
const checkpoint = profile.sessionCheckpoint as Record<string, unknown>;
checkpoint.goal = {
threadId: "provider-thread-123",
objective: "Keep this paused goal on its original provider session.",
status: "paused",
tokenBudget: null,
tokensUsed: 321,
timeUsedSeconds: 12,
};
checkpoint.semanticResult = {
schema: "paperclip.run_result.v1",
reportedWorkDisposition: "yielded",
summary: "Paused at a quiescent boundary.",
continuation: {
kind: "same_agent",
idempotencyKey: "goal:paused:one",
},
};
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: execution(currentRunId),
}),
).toMatchObject({
providerRecoveryPolicy: "same_session_only",
semanticResult: null,
activeTurnId: null,
goal: {
objective: "Keep this paused goal on its original provider session.",
status: "paused",
},
});
});
it("refuses to resume when the workspace changes", () => {
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun(),
currentExecution: execution(currentRunId, "/different-workspace"),
}),
).toBeNull();
});
it("requires the exact managed execution-workspace identity", () => {
const managedWorkspaceId = "90000000-0000-4000-8000-000000000009";
const source = previousRun({
nativeExecutionInput: execution(
previousRunId,
"/shared-workspace",
"standard",
{ id: managedWorkspaceId },
),
});
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: execution(
currentRunId,
"/shared-workspace",
"standard",
{ id: managedWorkspaceId },
),
}),
).not.toBeNull();
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: execution(
currentRunId,
"/shared-workspace",
"standard",
{ id: "a0000000-0000-4000-8000-00000000000a" },
),
}),
).toBeNull();
});
it("permits per-run projectless placeholders only for an identical workspace descriptor", () => {
const source = previousRun({
nativeExecutionInput: execution(
previousRunId,
"/projectless",
"standard",
{
repoUrl: "https://example.test/repo.git",
repoRef: "refs/heads/main",
branchName: "main",
},
),
});
const matching = execution(currentRunId, "/projectless", "standard", {
repoUrl: "https://example.test/repo.git",
repoRef: "refs/heads/main",
branchName: "main",
});
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: matching,
}),
).not.toBeNull();
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: {
...matching,
workspace: { ...matching.workspace, repoRef: "refs/heads/next" },
},
}),
).toBeNull();
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: execution(currentRunId, "/projectless", "standard", {
id: "b0000000-0000-4000-8000-00000000000b",
repoUrl: "https://example.test/repo.git",
repoRef: "refs/heads/main",
branchName: "main",
}),
}),
).toBeNull();
});
it("rotates when assigned context changes but permits a fresh run-scoped MCP binding", () => {
const reboundCredential = execution(currentRunId);
reboundCredential.runtimeContext.mcp.bindingId = "native-mcp:fresh-run";
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun(),
currentExecution: reboundCredential,
}),
).not.toBeNull();
const changedAssignment = execution(currentRunId);
const withoutAggregate = {
prompt: changedAssignment.runtimeContext.prompt,
instructions: changedAssignment.runtimeContext.instructions,
skills: changedAssignment.runtimeContext.skills,
mcp: {
assignmentSetId: `sha256:${"1".repeat(64)}`,
digest: "1".repeat(64),
bindingId: "native-mcp:fresh-run",
},
};
changedAssignment.runtimeContext = {
...withoutAggregate,
aggregateDigest: canonicalNativeRuntimeContextDigest(withoutAggregate),
};
expect(
rebindNativeSessionCheckpoint({
previousRun: previousRun(),
currentExecution: changedAssignment,
}),
).toBeNull();
});
it("refuses a checkpoint whose prior-run binding was rewritten", () => {
const source = previousRun();
const profile = source.runnerProfileJson as Record<string, unknown>;
const checkpoint = profile.sessionCheckpoint as Record<string, unknown>;
checkpoint.identity = {
...(checkpoint.identity as Record<string, unknown>),
runId: currentRunId,
};
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: execution(currentRunId),
}),
).toBeNull();
});
it("reuses plan mode across canonical revisions but never across a mode change", () => {
const source = previousRun({
nativeExecutionInput: planningExecution(previousRunId, "revision-8"),
});
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: planningExecution(currentRunId, "revision-9"),
}),
).not.toBeNull();
expect(
rebindNativeSessionCheckpoint({
previousRun: source,
currentExecution: execution(currentRunId),
}),
).toBeNull();
});
});
describe("buildNativeExecutionInput wake projection", () => {
it("uses compact Slack input only after provider resume, preserving fresh bootstrap fallback", () => {
const base = execution(currentRunId);
const issue = { id: issueId, identifier: "DOT-2", title: "Old greeting", description: null, workMode: "standard" };
const message = { id: "wake", body: "NEW_SLACK_MESSAGE", authorType: "user", authorId: "board", sourceTrust: "user", createdByRunId: null };
const input = buildNativeExecutionInput({
companyId, runId: currentRunId, agentId, issue,
taskPrompt: "FULL_BOOTSTRAP_WITH_FILE_AND_AUTHORIZATION_INSTRUCTIONS",
resumedSession: true,
previousTurn: { runId: previousRunId, task: issue },
wakePayload: {
reason: "External chat message received", issue,
externalChatProvider: "slack", checkedOutByHarness: true,
comments: [{ ...message, author: { type: "user", id: "board" } }], commentIds: [message.id], latestCommentId: message.id,
commentWindow: { requestedCount: 1, includedCount: 1, missingCount: 0 },
executionContinuation: { version: 1, objective: message.body, messages: [message], resumeDelta: { baseRunId: previousRunId, messages: [message] } },
},
workspace: { id: currentRunId, ...base.workspace }, normalizedSessionId,
provider: "codex", completionContract: base.completionContract,
runtimeContext: nativeRuntimeContextFixture(),
});
expect(input.continuationPrompt).toContain(message.body);
expect(input.continuationPrompt).not.toContain("FULL_BOOTSTRAP");
expect(input.task.prompt).toContain("FULL_BOOTSTRAP");
expect(input.task.prompt).toContain(message.body);
});
it("uses a neutral turn title for authenticated external-chat follow-ups", () => {
const staleRootTitle = "Reply with exactly STALE-ROOT-MARKER";
const input = buildNativeExecutionInput({
companyId,
runId: currentRunId,
issue: {
id: issueId,
identifier: "CHAT-4",
title: staleRootTitle,
description: "Started from Telegram.",
workMode: "standard",
},
taskPrompt: [
"Paperclip task context:",
`- Title: ${JSON.stringify(staleRootTitle)}`,
"Latest wake comment:",
"```text",
"Quick question: what is 55 + 8?",
"```",
].join("\n"),
wakePayload: {
reason: "External chat message received",
externalChatProvider: "telegram",
checkedOutByHarness: true,
issue: {
id: issueId,
identifier: "CHAT-4",
title: staleRootTitle,
description: "Started from Telegram.",
descriptionTruncated: false,
status: "in_progress",
workMode: "standard",
},
commentWindow: {
requestedCount: 1,
includedCount: 1,
missingCount: 0,
},
commentIds: ["comment-current"],
latestCommentId: "comment-current",
comments: [
{
id: "comment-current",
issueId,
body: "Quick question: what is 55 + 8?",
bodyTruncated: false,
authorType: "user",
},
],
fallbackFetchNeeded: false,
},
agentId,
workspace: {
id: currentRunId,
cwd: "/workspace",
repoUrl: null,
repoRef: null,
branchName: null,
},
normalizedSessionId,
provider: "codex",
completionContract: {
id: "70000000-0000-4000-8000-000000000007",
sha256: `sha256:${"a".repeat(64)}`,
schemaVersion: "paperclip.run-result.v1",
contract: {
revision: "2",
objective: "Respond to the latest comment",
criteria: [
{
id: "objective",
requirement: "Quick question: what is 55 + 8?",
},
],
},
},
runtimeContext: nativeRuntimeContextFixture(),
});
expect(input.task.title).toBe("External chat follow-up");
expect(input.task.description).toBeNull();
expect(input.task.prompt).toContain(staleRootTitle);
expect(input.task.prompt).toContain("Quick question: what is 55 + 8?");
expect(input.completionContract.contract).toMatchObject({
objective: "Respond to the latest comment",
criteria: [
{
id: "objective",
requirement: "Quick question: what is 55 + 8?",
},
],
});
});
it("preserves the canonical task title outside the authenticated chat shortcut", () => {
const input = execution(currentRunId);
expect(input.task.title).toBe("Test");
});
it("writes native v4 and pins every provider's complete effective configuration", () => {
const common = {
companyId,
runId: currentRunId,
issue: {
id: issueId,
identifier: "DOT-4",
title: "Permissions",
description: null,
workMode: "standard",
},
taskPrompt: "Verify permissions",
agentId,
workspace: {
id: currentRunId,
cwd: "/workspace",
repoUrl: null,
repoRef: null,
branchName: null,
},
normalizedSessionId,
completionContract: execution(currentRunId).completionContract,
runtimeContext: nativeRuntimeContextFixture(),
} as const;
const codex = buildNativeExecutionInput({
...common,
provider: "codex",
codexApprovalPolicy: "on-request",
});
const opencode = buildNativeExecutionInput({
...common,
provider: "opencode",
model: "openrouter/z-ai/glm-5.2",
opencodePermissionMode: "ask",
});
const acpx = buildNativeExecutionInput({
...common,
provider: "acpx",
acpxAgent: "claude",
model: "claude-sonnet-5",
acpxPermissionMode: "deny-all",
});
const claudeManaged = buildNativeExecutionInput({
...common,
provider: "claude_managed",
model: "claude-sonnet-5",
managedProfile: {
profileId: "managed-profile",
anthropicAgentId: "agent-remote",
agentVersion: "7",
environmentId: "environment-remote",
betaVersion: "managed-agents-2026-04-01",
},
maxSessionListCostUsd: 0.75,
});
const agentCore = buildNativeExecutionInput({
...common,
provider: "aws_agentcore",
model: "global.anthropic.claude-sonnet-4-6",
agentCoreProfile: {
profileId: "agentcore-profile",
region: "us-east-1",
accountId: "123456789012",
harnessArn:
"arn:aws:bedrock-agentcore:us-east-1:123456789012:harness/h-1",
harnessVersion: "3",
endpointArn:
"arn:aws:bedrock-agentcore:us-east-1:123456789012:endpoint/e-1",
endpointQualifier: "prod",
agentRuntimeArn:
"arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1",
memoryArn:
"arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1",
memoryId: "m-1",
invocationRoleArn: "arn:aws:iam::123456789012:role/invoke",
contextBucket: "paperclip-context",
contextPrefix: "runner/",
contextKmsKeyArn: "arn:aws:kms:us-east-1:123456789012:key/key-1",
qualificationRevision: "aws-agentcore-harness-context-v2",
eventExpiryDays: 90,
},
maxEstimatedSessionCostUsd: 1.25,
invocationLimits: {
maxIterations: 8,
maxOutputTokens: 4_096,
timeoutSeconds: 300,
},
});
const defaultOpenCode = buildNativeExecutionInput({
...common,
provider: "opencode",
model: "openrouter/z-ai/glm-5.2",
});
const defaultAcpx = buildNativeExecutionInput({
...common,
provider: "acpx",
model: "gpt-5.6-sol",
});
expect(codex).toMatchObject({
schema: "paperclip.native-execution-input.v5",
provider: { kind: "codex", approvalPolicy: "on-request" },
});
expect(opencode).toMatchObject({
schema: "paperclip.native-execution-input.v5",
provider: { kind: "opencode", permissionMode: "ask" },
});
expect(acpx).toMatchObject({
schema: "paperclip.native-execution-input.v5",
provider: { kind: "acpx", permissionMode: "deny-all" },
});
expect(claudeManaged).toMatchObject({
session: { driverKind: "claude_managed_agents_api" },
provider: {
kind: "claude_managed",
managedProfile: { profileId: "managed-profile" },
maxSessionListCostUsd: 0.75,
},
});
expect(agentCore).toMatchObject({
session: { driverKind: "aws_agentcore_harness_api" },
provider: {
kind: "aws_agentcore",
agentCoreProfile: {
profileId: "agentcore-profile",
eventExpiryDays: 90,
},
maxEstimatedSessionCostUsd: 1.25,
},
});
expect(defaultOpenCode).toMatchObject({
provider: { kind: "opencode", permissionMode: "allow" },
});
expect(defaultAcpx).toMatchObject({
provider: {
kind: "acpx",
agent: "codex",
permissionMode: "approve-all",
},
});
expect(
JSON.stringify([codex, opencode, claudeManaged, agentCore, acpx]),
).not.toMatch(
/OPENAI_API_KEY|ANTHROPIC_API_KEY|AWS_SECRET_ACCESS_KEY|PAPERCLIP_API_KEY/,
);
});
it.each([false, true])("projects wake context with the appropriate execution contract (conversation=%s)", (conversationMode) => {
const input = buildNativeExecutionInput({
companyId,
runId: currentRunId,
issue: {
id: issueId,
identifier: "DOT-146",
title: "Finish after child handoff",
description: "Use the child result.",
workMode: "standard",
},
taskPrompt: "Paperclip task context:\n- Issue: DOT-146",
wakePayload: {
reason: "issue_children_completed",
issue: {
id: issueId,
identifier: "DOT-146",
title: "Finish after child handoff",
description: "Use the child result.",
status: "in_progress",
priority: "medium",
workMode: "standard",
},
childIssueSummaries: [
{
id: "child-147",
identifier: "DOT-147",
title: "Build utility",
status: "done",
summary: "Created three files and passed 7/7 tests.",
},
],
childIssueSummaryTruncated: false,
checkedOutByHarness: true,
},
resumedSession: true,
conversationMode,
agentId,
workspace: {
id: currentRunId,
cwd: "/workspace",
repoUrl: null,
repoRef: null,
branchName: null,
},
normalizedSessionId,
provider: "opencode",
model: "openrouter/z-ai/glm-5.2",
completionContract: {
id: "70000000-0000-4000-8000-000000000007",
sha256: `sha256:${"a".repeat(64)}`,
schemaVersion: "paperclip.run-result.v1",
contract: {
revision: "1",
objective: "Finish after the child",
criteria: [
{ id: "objective", requirement: "Report the child result" },
],
},
},
runtimeContext: nativeRuntimeContextFixture(),
});
expect(input.task.prompt).not.toContain("Execution contract:");
expect(input.task.prompt).not.toContain("Use child issues");
// Full bootstrap stays available if provider recovery fails after admission.
expect(input.task.prompt).toContain("## Paperclip Wake Payload");
expect(input.task.prompt).toContain("reason: issue_children_completed");
expect(input.task.prompt).toContain("DOT-147 Build utility (done)");
expect(input.task.prompt).toContain(
"Created three files and passed 7/7 tests.",
);
expect(input.task.prompt).toContain(
"Paperclip task context:\n- Issue: DOT-146",
);
expect(input.task.prompt).not.toContain("Use the child result.");
});
});