Preserve runner process start time across controller recovery

Use the verified remote process marker and adopted process identity when reporting runner process metadata, rather than the creation time of a replacement controller transport.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Dotta 2026-09-10 14:25:05 -05:00
parent 802dfe5e9e
commit 6ae2dc5de7
4 changed files with 10 additions and 3 deletions

View File

@ -3212,7 +3212,7 @@ async function verifyLiveRunnerAdoption(mismatchedCheckpoint: boolean) {
adoptExistingRunner: {
pid: runnerPid!,
processGroupId: runnerPid,
startedAt: new Date().toISOString(),
startedAt: "2026-09-01T10:00:00.000Z",
isAlive: () => {
try {
process.kill(runnerPid!, 0);
@ -3237,6 +3237,7 @@ async function verifyLiveRunnerAdoption(mismatchedCheckpoint: boolean) {
}),
);
expect(adopted.evidence().runnerPid).toBe(runnerPid);
expect(adopted.transport.processInfo?.().startedAt).toBe("2026-09-01T10:00:00.000Z");
expect(duplicateLauncher).not.toHaveBeenCalled();
expect(adopted.evidence().diagnostics).toContain(
`adopted runner ${runnerPid} authenticated to its durable PRP authority`,

View File

@ -2515,7 +2515,8 @@ class DurablePrpCodexTransport implements CodexAppServerTransport {
return {
pid: this.#evidence.runnerPid,
processGroupId: this.#evidence.runnerProcessGroupId,
startedAt: this.#startedAt,
// Reconnecting creates a new transport, not a new runner process.
startedAt: this.options.adoptExistingRunner?.startedAt ?? this.#handle?.startedAt ?? this.#startedAt,
exited: this.#evidence.runnerExited,
exitCode: this.#evidence.runnerExitCode,
signal: this.#evidence.runnerSignal,

View File

@ -341,6 +341,7 @@ describe("remote runner process supervision", () => {
startedAt: "2026-09-06T00:00:00.000Z",
});
expect(handle.child.pid).toBe(4321);
expect(handle.startedAt).toBe("2026-09-06T00:00:00.000Z");
expect(handle.child.kill("SIGKILL")).toBe(true);
await vi.waitFor(() =>

View File

@ -6362,7 +6362,11 @@ export function createRemoteRunnerProcessLauncher(input: {
};
}
})();
return { child, completion };
return {
child,
completion,
get startedAt() { return launchedIdentity?.startedAt; },
};
};
}