test(runner): add real Paperclip vertical slice

This commit is contained in:
Dotta committed 2026-08-21 09:31:32 -05:00
1 parent 3fe556f2d4
commit d7dd987015
2 files changed
+138 -1

No files matched your search

@@ -8,7 +8,7 @@ This roster is the implementation ledger for binding the canonical Paperclip Run
- Actions in the Codex semantic catalog: **28**
- Actions advertised by the production Paperclip authority: **13**
- Actions with a real Paperclip service binding: **13**
- Actions audited through the shared Paperclip-server PRP route: **13 service bindings; route smoke audit pending**
- Actions audited through the shared Paperclip-server PRP route: **1 full real-service vertical slice; 12 additional bound operations unit-audited**
- Existing semantic conformance bridge: five route-backed test operations (`report_progress`, `write_document`, confirmation-only `request_human_input`, `set_dependencies`, and `finish_task`). It is test-only and is not a production binding.
The generated action metadata currently says `realServiceBinding: unbound` and `prpBindingStatus: audit_pending` for every action. `realBindingStatus: live_codex` means only that a Codex scenario exercised the mock semantic implementation; it must not be interpreted as a production Paperclip binding.
@@ -54,3 +54,10 @@ authority still authenticates the one-time bootstrap ticket and durable lease
inside PRP. Unknown runs and malformed run IDs fail closed before the protocol
handshake. The run ID is a path segment because runnerd deliberately rejects
query-bearing WebSocket URLs to avoid URL ambiguity.
`paperclip-runner-real-server.integration.test.ts` is the first complete proof:
an embedded real Paperclip database and active native heartbeat run are routed
through the shared server endpoint to Rust runnerd and the fake Codex
app-server; Codex calls `get_task_context`, and the result is read from the real
run-bound Paperclip authority. The remaining advertised operations still need
their own route-level cases before the roster can call all 13 fully audited.
@@ -0,0 +1,130 @@
import { createServer } from "node:http";
import { tmpdir } from "node:os";
import { resolve } from "node:path";
import { eq } from "drizzle-orm";
import { agents, companies, createDb, heartbeatRuns, issues } from "@paperclipai/db";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import {
createRunnerdCodexTransport,
defaultCapabilityRunnerdBinary,
} from "../../vendor/paperclip-runner/index.js";
import { startEmbeddedPostgresTestDatabase } from "../../__tests__/helpers/embedded-postgres.js";
import {
registerRunnerPrpAuthority,
runnerPrpWebSocketInternals,
setupRunnerPrpWebSocketServer,
} from "../../realtime/runner-prp-ws.js";
import { PaperclipRunnerToolAuthority } from "./paperclip-runner-tool-authority.js";
describe("paperclip-runner real server vertical slice", () => {
let temporary: Awaited<ReturnType<typeof startEmbeddedPostgresTestDatabase>>;
const companyId = "00000000-0000-4000-8000-000000000701";
const agentId = "00000000-0000-4000-8000-000000000702";
const issueId = "00000000-0000-4000-8000-000000000703";
const runId = "00000000-0000-4000-8000-000000000704";
beforeAll(async () => {
temporary = await startEmbeddedPostgresTestDatabase("paperclip-runner-real-server-");
});
afterAll(async () => {
runnerPrpWebSocketInternals.resetForTests();
await temporary.cleanup();
});
it("runs Rust runnerd through Paperclip PRP and reads the real bound task", async () => {
const db = createDb(temporary.connectionString);
await db.insert(companies).values({ id: companyId, name: "Real runner slice", issuePrefix: "RRS" });
await db.insert(agents).values({
id: agentId,
companyId,
name: "Real runner agent",
adapterType: "paperclip_runner",
adapterConfig: { provider: "codex" },
runtimeConfig: {},
status: "active",
});
await db.insert(issues).values({
id: issueId,
companyId,
identifier: "RRS-1",
title: "Read me through the real control plane",
status: "in_progress",
workMode: "standard",
assigneeAgentId: agentId,
});
await db.insert(heartbeatRuns).values({
id: runId,
companyId,
agentId,
status: "running",
runtimeMode: "native",
invocationSource: "assignment",
triggerDetail: "system",
contextSnapshot: { issueId },
});
await db.update(issues).set({ executionRunId: runId }).where(eq(issues.id, issueId));
const authority = new PaperclipRunnerToolAuthority(db, { companyId, agentId, issueId, runId });
const server = createServer();
await new Promise<void>((resolveListen) => server.listen(0, "127.0.0.1", resolveListen));
const address = server.address();
if (address === null || typeof address === "string") throw new Error("Expected a TCP listener.");
setupRunnerPrpWebSocketServer(server, { port: address.port });
const bundle = createRunnerdCodexTransport({
runnerBinary: defaultCapabilityRunnerdBinary(),
codexCommand: resolve(import.meta.dirname, "../../../../packages/paperclip-runner/runner/target/debug/fake-codex-app-server"),
codexArgs: [],
prpIdentity: {
runnerInstanceId: "runner-real-server",
environmentLeaseId: "lease-real-server",
runId,
normalizedSessionId: "session-real-server",
turnId: "turn-real-server",
itemId: "item-real-server",
},
controlPlaneRegistration: (prp) => registerRunnerPrpAuthority({ runId, authority: prp }),
});
const observedResults: unknown[] = [];
bundle.transport.setServerRequestHandler(async (request) => {
const params = request.params as Record<string, unknown>;
const result = await authority.execute({
tool: String(params.tool),
callId: String(params.callId),
arguments: params.arguments,
});
observedResults.push(result);
return {
success: true,
contentItems: [{ type: "inputText", text: JSON.stringify({ ok: true, result }) }],
};
});
try {
await bundle.transport.request("initialize", {});
await bundle.transport.request("thread/start", {
cwd: tmpdir(),
dynamicTools: authority.definitions(),
});
await bundle.transport.request("turn/start", {
input: [{ type: "text", text: "Read your assigned task context." }],
});
for await (const notification of bundle.transport.notifications()) {
if (notification.method === "turn/completed") break;
}
expect(observedResults).toHaveLength(1);
expect(observedResults[0]).toMatchObject({
activeTask: { id: issueId, identifier: "RRS-1", title: "Read me through the real control plane" },
actor: { id: agentId },
run: { id: runId },
});
expect(bundle.evidence().diagnostics).toContain("runnerd authenticated to the durable PRP control plane");
} finally {
await bundle.transport.close();
server.closeAllConnections();
server.close();
}
}, 30_000);
});