fix: retain built-in settings when changing Codex runner

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-09 10:12:15 -05:00
1 parent 0a82004bd0
commit eaabc5c624
3 files changed
+19 -7

No files matched your search

+8 -4
View File
@@ -38,8 +38,9 @@ Docker materialization, Git installer, or extra login isolation wholesale.
Authorized 2026-10-09. Canonical branch: `codex/codex-runner-default`.
Master base: `57e977be7` (includes both prerequisite merges and Pi integration).
Canonical PR: [draft #15683](https://github.com/paperclipai/paperclip/pull/15683).
Initial CI candidate: `8ce217b71`; final source freeze follows scoped discovery
and explicit-native import preservation checks.
Initial CI candidate: `8ce217b71`. Scoped environment discovery and native import
preservation are committed at `5ba1bc986`; the final follow-up preserves saved
model, effort, and timeout through runner-only built-in configuration changes.
Preview: [isolated Codex QA](http://127.0.0.1:3124), normal dev supervisor,
separate empty database. Current-head live evidence is pending the source freeze
and verified binary provenance; older services and artifacts are not proof.
@@ -116,8 +117,8 @@ Local startup hit the macOS shared-memory ID limit. One detached 56-byte segment
was released only after zero attachments and exited owners were verified. No
running server or database file was changed. The separate QA server is healthy.
Next action: finish core integration checks, commit and push the candidate,
then run existing Linux CI/install checks and bounded actual journeys. Preserve
Next action: verify the final candidate through existing Linux CI/install checks,
fresh review, and bounded actual journeys. Preserve
failed attempts and costs. Unrelated findings and remaining harness qualification
belong to later slices.
@@ -135,3 +136,6 @@ pass 280 cases plus three final regressions. Missing discovery metadata shows
loading or the server error with Retry; explicit Legacy remains available.
Final portability checks pass 105 cases; approval, built-in asset and CLI unit
controls pass eight, three and three. The 72 skipped DB cases still need Linux.
Final candidate Storybook builds at `5ba1bc986`; fresh desktop/mobile captures
are in progress against the frozen UI tree. The runner-only built-in regression
now checks nondefault settings through switches in both directions.
+7 -2
View File
@@ -287,7 +287,8 @@ describeEmbeddedPostgres("built-in agents", () => {
it("keeps existing legacy and native built-in runners through unrelated edits and startup", async () => {
const companyId = await seedCompany({ requireApproval: false });
const svc = builtInAgentService(db);
const created = await svc.ensure(companyId, "briefs", { adapterType: "codex_local", adapterConfig: { model: "gpt-5.4" }, runner: "legacy" });
const savedSettings = { model: "gpt-5.5", modelReasoningEffort: "high", timeoutSec: 123 };
const created = await svc.ensure(companyId, "briefs", { adapterType: "codex_local", adapterConfig: savedSettings, runner: "legacy" });
expect(created.agent?.adapterType).toBe("codex_local");
await svc.ensure(companyId, "briefs", { budgetMonthlyCents: 100 });
await reconcileBuiltInAgentsOnStartup(db);
@@ -295,10 +296,14 @@ describeEmbeddedPostgres("built-in agents", () => {
expect(legacy.agent?.adapterType).toBe("codex_local");
expect(legacy.agent?.adapterConfig).toEqual(created.agent?.adapterConfig);
const switched = await svc.ensure(companyId, "briefs", { runner: "paperclip" });
expect(switched.agent).toMatchObject({ adapterType: "paperclip_runner", adapterConfig: { provider: "codex" } });
expect(switched.agent).toMatchObject({ adapterType: "paperclip_runner", adapterConfig: { provider: "codex", ...savedSettings } });
await svc.ensure(companyId, "briefs", { budgetMonthlyCents: 200 });
await reconcileBuiltInAgentsOnStartup(db);
expect((await svc.get(companyId, "briefs")).agent?.adapterConfig).toEqual(switched.agent?.adapterConfig);
const switchedBack = await svc.ensure(companyId, "briefs", { runner: "legacy" });
expect(switchedBack.agent).toMatchObject({ adapterType: "codex_local", adapterConfig: savedSettings });
const switchedAgain = await svc.ensure(companyId, "briefs", { runner: "paperclip" });
expect(switchedAgain.agent).toMatchObject({ adapterType: "paperclip_runner", adapterConfig: { provider: "codex", ...savedSettings } });
// A saved native profile remains editable on source-built macOS installs.
runnerTarget.platform = "darwin";
runnerTarget.architecture = "arm64";
+4 -1
View File
@@ -1742,7 +1742,10 @@ export function builtInAgentService(db: Db) {
);
const resolvedInput = existingPendingApproval || preserveExistingAdapter
? input
: await defaultProvisionInput(companyId, definition, input);
: existing && input.runner !== undefined && input.adapterType === undefined && input.adapterConfig === undefined
// A runner-only request translates saved settings, not provisioning defaults.
? { ...input, adapterType: existing.adapterType, adapterConfig: existing.adapterConfig }
: await defaultProvisionInput(companyId, definition, input);
if (!existingPendingApproval && !preserveExistingAdapter) {
await assertKnownBuiltInAgentModel(definition, resolvedInput);
}