fix: preserve Codex runner intent and private eval evidence

Retain native setup links and built-in settings, record explicit runner choices, and qualify native/legacy skill fixtures. Keep full grading artifacts private while projecting safe first-task summaries.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-09 10:51:10 -05:00
1 parent 38199ea8e6
commit 1be8502f27
15 files changed
+454 -32

No files matched your search

@@ -11,6 +11,9 @@ import type { BuiltInAgentState } from "@/api/builtInAgents";
const provisionMock = vi.hoisted(() => vi.fn());
const updateMock = vi.hoisted(() => vi.fn());
const adapterModelsMock = vi.hoisted(() => vi.fn());
const adapterDiscoveryMock = vi.hoisted(() => vi.fn());
vi.mock("@/api/adapters", () => ({ adaptersApi: { list: adapterDiscoveryMock } }));
vi.mock("@/api/builtInAgents", async (importOriginal) => {
const actual = await importOriginal<typeof import("@/api/builtInAgents")>();
@@ -72,6 +75,15 @@ function makeState(overrides: Partial<BuiltInAgentState> = {}): BuiltInAgentStat
};
}
function makeSavedAgent(adapterType: "codex_local" | "paperclip_runner", adapterConfig: Record<string, unknown>): NonNullable<BuiltInAgentState["agent"]> {
return {
id: "a1", companyId: "c1", name: "Briefs Agent", urlKey: "briefs-agent", role: "general", title: null, icon: null,
status: "idle", reportsTo: null, capabilities: null, adapterType, adapterConfig, runtimeConfig: {}, defaultEnvironmentId: null,
budgetMonthlyCents: 0, spentMonthlyCents: 0, pauseReason: null, pausedAt: null, permissions: { canCreateAgents: false },
lastHeartbeatAt: null, metadata: null, createdAt: new Date(0), updatedAt: new Date(0),
};
}
async function flushReact() {
for (let index = 0; index < 6; index += 1) {
await Promise.resolve();
@@ -117,6 +129,7 @@ describe("ConfigureBuiltInAgentModal (PAP-12978)", () => {
provisionMock.mockReset();
updateMock.mockReset();
adapterModelsMock.mockReset().mockResolvedValue([]);
adapterDiscoveryMock.mockReset().mockResolvedValue([{ type: "codex_local", supportedRunners: ["paperclip", "legacy"], defaultRunner: "legacy" }]);
onOpenChange.mockReset();
onConfigured.mockReset();
});
@@ -189,6 +202,40 @@ describe("ConfigureBuiltInAgentModal (PAP-12978)", () => {
});
});
it.each(["codex_local", "paperclip_runner"] as const)("lets the server translate saved %s settings for a runner-only change", async adapterType => {
const savedConfig = { model: "gpt-5", timeoutSec: 45, modelReasoningEffort: "high", env: { CODEX_HOME: { type: "secret_ref", secretId: "account-1" } }, ...(adapterType === "paperclip_runner" ? { provider: "codex", codexPermissionMode: "never", lifecycleMode: "per_turn" } : {}) };
const state = makeState({ status: "ready", agentId: "a1", agent: makeSavedAgent(adapterType, savedConfig) });
provisionMock.mockResolvedValue(state);
await renderModal(state);
const summary = document.querySelector("summary")!;
flushSync(() => summary.dispatchEvent(new MouseEvent("click", { bubbles: true })));
flushSync(() => document.querySelector('[aria-label="Runner"]')!.dispatchEvent(new MouseEvent("click", { bubbles: true })));
await flushReact();
const runner = adapterType === "paperclip_runner" ? "legacy" : "paperclip";
flushSync(() => document.querySelector(`[role="option"][data-value="${runner}"]`)!.dispatchEvent(new MouseEvent("click", { bubbles: true })));
await flushReact();
flushSync(() => findButton("Configure")!.dispatchEvent(new MouseEvent("click", { bubbles: true })));
await flushReact();
expect(provisionMock).toHaveBeenCalledWith("c1", "briefs", { runner });
expect(state.agent?.adapterConfig).toEqual(savedConfig);
});
it("merges a built-in model edit into the saved native configuration", async () => {
const savedConfig = { provider: "codex", model: "gpt-5", timeoutSec: 45, modelReasoningEffort: "high", env: { CODEX_HOME: { type: "secret_ref", secretId: "account-1" } } };
const state = makeState({ status: "ready", agentId: "a1", agent: makeSavedAgent("paperclip_runner", savedConfig) });
provisionMock.mockResolvedValue(state);
await renderModal(state);
const modelInput = document.querySelector('[data-testid="model-input"]') as HTMLInputElement;
flushSync(() => {
Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")!.set!.call(modelInput, "gpt-6-sol");
modelInput.dispatchEvent(new Event("input", { bubbles: true }));
});
await flushReact();
flushSync(() => findButton("Configure")!.dispatchEvent(new MouseEvent("click", { bubbles: true })));
await flushReact();
expect(provisionMock).toHaveBeenCalledWith("c1", "briefs", { adapterType: "paperclip_runner", adapterConfig: { ...savedConfig, model: "gpt-6-sol" } });
});
it("shows a visible error and blocks provisioning for an unknown model", async () => {
adapterModelsMock.mockResolvedValue([
{ id: "claude-haiku-4-5", label: "Claude Haiku 4.5" },