diff --git a/doc/plans/2026-10-06-default-agent-runner.md b/doc/plans/2026-10-06-default-agent-runner.md index bcc98ce0870..a8e1e59cde4 100644 --- a/doc/plans/2026-10-06-default-agent-runner.md +++ b/doc/plans/2026-10-06-default-agent-runner.md @@ -336,3 +336,25 @@ Next action: push these narrow corrections, run fresh full CI and review, build matching immutable preview artifacts in hosted CI, then qualify the one QA tenant after those gates pass. Retain all historical cost and cleanup holds. The draft remains neither merge-ready nor production-ready. + +At correction `f6a15200c`, fresh review passes 5/5 with all eight threads resolved, +and the previously failing retry E2E shard passes. One unchanged auth-signal +fixture exceeded its 15-second test deadline during a cold route import; its +previous exact version passed on the integrated head. Imports now run in the +existing setup hook after the same resets, keeping the 15-second assertion +deadline and all actor/response checks. All 127 affected auth/form/model cases +pass. A temporary 100ms assertion deadline also passes while setup takes about +six seconds, confirming the separation. Keyboard coverage moved intact into +the existing form suite; the PR stays 99 files. This correction changes only +tests and this record, with the production runtime byte-identical to `f6a15200c`. +Three hosted server shards were interrupted after passing progress and remain +incomplete evidence. The new test-only head requires fresh completed CI. + +The frozen `f6a15200c` preview image is building remotely; exact-source shared/DB +preview packages are published and their source metadata verified. The isolated +local preview restarted at `2026-10-09T16:46:58.859Z`, serving that version with +startup recovery ready and no pending migrations. Its existing worktree execution +preference was off; activating it allowed the queued user onboarding response +to run. The actual legacy Codex task completed and its independently read file +contained the exact two requested lines. The same-task follow-up is running. +No second task, agent hire, or automatic runner conversion was used. diff --git a/server/src/__tests__/adapter-auth-signal-routes.test.ts b/server/src/__tests__/adapter-auth-signal-routes.test.ts index 8360e3e133a..33fd90570c9 100644 --- a/server/src/__tests__/adapter-auth-signal-routes.test.ts +++ b/server/src/__tests__/adapter-auth-signal-routes.test.ts @@ -113,6 +113,8 @@ vi.mock("@paperclipai/adapter-codex-local/server", async (importOriginal) => { }); let currentActor: Record; +let agentRoutes: typeof import("../routes/agents.js").agentRoutes; +let errorHandler: typeof import("../middleware/index.js").errorHandler; function boardActor(userId: string, companyIds: string[] = [COMPANY_1, OTHER_COMPANY]): Record { return { @@ -125,10 +127,6 @@ function boardActor(userId: string, companyIds: string[] = [COMPANY_1, OTHER_COM } async function createApp() { - const [{ agentRoutes }, { errorHandler }] = await Promise.all([ - vi.importActual("../routes/agents.js"), - vi.importActual("../middleware/index.js"), - ]); const app = express(); app.use(express.json()); app.use((req, _res, next) => { @@ -144,7 +142,7 @@ const authSignalPath = (companyId: string, type: string, environmentId?: string) `/api/companies/${companyId}/adapters/${type}/auth-signal${environmentId ? `?environmentId=${environmentId}` : ""}`; describe("adapter auth-signal route", () => { - beforeEach(() => { + beforeEach(async () => { vi.resetModules(); vi.clearAllMocks(); currentActor = boardActor(OWNER_A); @@ -176,6 +174,14 @@ describe("adapter auth-signal route", () => { effectiveHome: "/tmp/codex-home", sharedSourceHome: "/tmp/codex-shared-home", }); + // Keep cold route-module transforms in fixture setup, while the unchanged + // test deadline measures the HTTP request and its authorization assertions. + const [routes, middleware] = await Promise.all([ + vi.importActual("../routes/agents.js"), + vi.importActual("../middleware/index.js"), + ]); + agentRoutes = routes.agentRoutes; + errorHandler = middleware.errorHandler; }); afterEach(() => { diff --git a/ui/src/components/AgentConfigForm.render.test.tsx b/ui/src/components/AgentConfigForm.render.test.tsx index 433fe70b102..5c038a8fd73 100644 --- a/ui/src/components/AgentConfigForm.render.test.tsx +++ b/ui/src/components/AgentConfigForm.render.test.tsx @@ -9,7 +9,7 @@ import type { Agent, Environment, UserSecretDefinition } from "@paperclipai/shar import { getEnvironmentCapabilities } from "@paperclipai/shared"; import { TooltipProvider } from "@/components/ui/tooltip"; import { ToastProvider } from "../context/ToastContext"; -import { AgentConfigForm, AdapterLoginPanel, subtractPersistedOverlay, type AdapterLoginDescriptor } from "./AgentConfigForm"; +import { AgentConfigForm, AdapterLoginPanel, ModelDropdown, subtractPersistedOverlay, type AdapterLoginDescriptor } from "./AgentConfigForm"; import { defaultCreateValues } from "./agent-config-defaults"; import { buildNewAgentHirePayload } from "../lib/new-agent-hire-payload"; import { ApiError } from "../api/client"; @@ -1301,6 +1301,33 @@ describe("AgentConfigForm environment selector", () => { expect(result.container.textContent).toContain("Network unavailable"); }); + it("moves through model options with the same keyboard controls as the harness picker", async () => { + const curated = [ + { id: "claude-fable-5-1", label: "Claude Fable 5.1" }, + { id: "claude-opus-5-5", label: "Claude Opus 5.5" }, + { id: "claude-haiku-4-5", label: "Claude Haiku 4.5" }, + { id: "claude-opus-4-8", label: "Claude Opus 4.8" }, + ]; + const container = document.createElement("div"); + document.body.appendChild(container); + const root = createRoot(container); + try { + await act(() => root.render( + {}} open onOpenChange={() => {}} allowDefault={false} required groupByProvider={false} preserveOrder /> + )); + const search = document.body.querySelector("input")!; + await act(() => { search.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true })); }); + expect(document.activeElement?.textContent).toBe(curated[0].label); + await act(() => { document.activeElement?.dispatchEvent(new KeyboardEvent("keydown", { key: "End", bubbles: true })); }); + expect(document.activeElement?.textContent).toBe(curated.at(-1)?.label); + await act(() => { document.activeElement?.dispatchEvent(new KeyboardEvent("keydown", { key: "Home", bubbles: true })); }); + expect(document.activeElement?.textContent).toBe(curated[0].label); + } finally { + await act(() => root.unmount()); + container.remove(); + } + }); + it("hides the Login button before Test and shows it after the adapter_auth_missing check for a Codex sandbox", async () => { mockAgentsApi.testEnvironment.mockResolvedValue(AUTH_MISSING_RESULT); const result = await renderCodexSandbox(); diff --git a/ui/src/components/ModelDropdown.test.tsx b/ui/src/components/ModelDropdown.test.tsx index dce410cac4a..6a17a623cc4 100644 --- a/ui/src/components/ModelDropdown.test.tsx +++ b/ui/src/components/ModelDropdown.test.tsx @@ -78,15 +78,4 @@ describe("ModelDropdown", () => { expect(shownModelIds()).toEqual(["openai/gpt-6-astra", "openai/gpt-6-sol"]); }); - - it("moves through model options with the same keyboard controls as the harness picker", () => { - renderOpenDropdown(curated, { preserveOrder: true }); - const search = document.body.querySelector("input")!; - act(() => search.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }))); - expect(document.activeElement?.textContent).toBe(curated[0].label); - act(() => document.activeElement?.dispatchEvent(new KeyboardEvent("keydown", { key: "End", bubbles: true }))); - expect(document.activeElement?.textContent).toBe(curated.at(-1)?.label); - act(() => document.activeElement?.dispatchEvent(new KeyboardEvent("keydown", { key: "Home", bubbles: true }))); - expect(document.activeElement?.textContent).toBe(curated[0].label); - }); });