fix(runner): verify ACPX model from durable state

This commit is contained in:
Dotta 2026-09-02 21:14:27 -05:00
parent d60306420d
commit d49c011403
2 changed files with 69 additions and 12 deletions

View File

@ -199,26 +199,39 @@ describe("Codex ACPX runtime adapter", () => {
expect(assertWorkspaceHeld).toHaveBeenCalledOnce();
expect(command.spawn).not.toHaveBeenCalled();
});
it("maps status, model selection, and state-preserving close", async () => {
it("reads verified status from durable state without draining live updates", async () => {
const runtime = fakeRuntime();
vi.mocked(runtime.getStatus!).mockResolvedValue({
models: {
currentModelId: "gpt-5.6-sol",
availableModelIds: ["gpt-5.6-sol"],
vi.mocked(runtime.getStatus!).mockReturnValue(new Promise(() => {}));
const durableRecord = {
acpxRecordId: "record-1",
acpSessionId: "backend-1",
agentSessionId: "agent-1",
acpx: {
current_model_id: "gpt-5.6-sol",
available_models: ["gpt-5.6-sol"],
},
});
} as never;
const durableStore: AcpSessionStore = {
load: vi.fn(async () => structuredClone(durableRecord)),
save: vi.fn(),
};
const port = await openCodexAcpxRuntime(openOptions(fakeCommand()), {
createRegistry: () => registry(),
createStore: () => store(),
createStore: () => durableStore,
createRuntime: () => runtime,
});
expect(await port.getStatus()).toEqual({
expect(await port.getStatus()).toMatchObject({
acpxRecordId: "record-1",
backendSessionId: "backend-1",
agentSessionId: "agent-1",
models: {
currentModelId: "gpt-5.6-sol",
availableModelIds: ["gpt-5.6-sol"],
},
});
expect(durableStore.load).toHaveBeenCalledWith("record-1");
expect(runtime.getStatus).not.toHaveBeenCalled();
await port.setModel?.("gpt-5.6-sol");
expect(runtime.setConfigOption).toHaveBeenCalledWith({
handle: HANDLE,

View File

@ -23,6 +23,7 @@ import {
awaitVerifiedAcpxProviderExit,
awaitVerifiedAcpxProviderOwnership,
} from "./installation-integrity.js";
import type { AcpxModelStatus } from "./model-verification.js";
import { decideAcpxPermission } from "./permission-policy.js";
const VERIFIED_COMMAND_SENTINEL = "paperclip-verified-acpx-command";
@ -366,6 +367,7 @@ export async function openQualifiedAcpxRuntime(
runtime,
handle,
requireIdentity(handle),
baseStore,
children,
runtimeCloseTimeoutMs,
);
@ -774,6 +776,7 @@ function runtimePort(
runtime: AcpRuntime,
handle: AcpRuntimeHandle,
identity: AcpxRuntimePortIdentity,
sessionStore: AcpSessionStore,
children: SpawnedChildSet,
runtimeCloseTimeoutMs: number,
): AcpxRuntimePort {
@ -1004,10 +1007,7 @@ function runtimePort(
return structuredClone(identity);
},
async getStatus() {
if (!runtime.getStatus) {
throw new Error("The pinned ACPX runtime cannot report session status");
}
return structuredClone(await runtime.getStatus({ handle }));
return await persistedRuntimeStatus(sessionStore, handle, identity);
},
...(runtime.setConfigOption
? {
@ -1035,6 +1035,50 @@ function runtimePort(
return port;
}
async function persistedRuntimeStatus(
sessionStore: AcpSessionStore,
handle: AcpRuntimeHandle,
identity: AcpxRuntimePortIdentity,
): Promise<AcpxModelStatus> {
const recordId = handle.acpxRecordId ?? handle.sessionKey;
const record = await sessionStore.load(recordId);
if (!record) {
throw new Error(
"The pinned ACPX runtime omitted its persisted session record",
);
}
if (
record.acpxRecordId !== identity.acpxRecordId ||
record.acpSessionId !== identity.backendSessionId ||
record.agentSessionId !== identity.agentSessionId
) {
throw new Error(
"The persisted ACPX session identity changed after admission",
);
}
const currentModelId = record.acpx?.current_model_id;
const availableModelIds = record.acpx?.available_models;
return {
summary: [
`session=${record.acpxRecordId}`,
`backendSessionId=${record.acpSessionId}`,
`agentSessionId=${record.agentSessionId}`,
record.closed === true ? "closed" : "open",
].join(" "),
acpxRecordId: record.acpxRecordId,
backendSessionId: record.acpSessionId,
agentSessionId: record.agentSessionId,
...(currentModelId === undefined && !availableModelIds?.length
? {}
: {
models: {
...(currentModelId === undefined ? {} : { currentModelId }),
availableModelIds: availableModelIds ? [...availableModelIds] : [],
},
}),
};
}
function runtimeCloseOutcome(
runtime: AcpRuntime,
input: Parameters<AcpRuntime["close"]>[0],