diff --git a/packages/shared/src/projectSettings.test.ts b/packages/shared/src/projectSettings.test.ts index 950867d36dc7c682375126592a1647e4a4bc220f..8760433182d68200f607e89e96eb505344ee8182 100644 --- a/packages/shared/src/projectSettings.test.ts +++ b/packages/shared/src/projectSettings.test.ts @@ -29,6 +29,14 @@ describe("resolveProjectSettings", () => { ); }); + it("treats a null project like an absent one before the shell snapshot arrives", () => { + // The mobile new-task flow resolves settings while its selected project is + // still null; reading the aggregate's legacy fields off null crashed launch. + expect(resolveProjectSettings(DEFAULT_SERVER_SETTINGS, null, null).settings).toBe( + DEFAULT_SERVER_SETTINGS, + ); + }); + it("applies overrides per key and reports their source", () => { const settings = applyServerSettingsPatch(DEFAULT_SERVER_SETTINGS, { defaultAutoPull: true, diff --git a/packages/shared/src/projectSettings.ts b/packages/shared/src/projectSettings.ts index 742e1cb8d140c82d0a202ca1602407ca8fb432db..edb56654f5d03f8313a78aea65d6c7c94ec66c2e 100644 --- a/packages/shared/src/projectSettings.ts +++ b/packages/shared/src/projectSettings.ts @@ -59,11 +59,13 @@ export interface LegacyProjectSettingsFields { export function resolveProjectSettings( settings: ServerSettings, projectId: ProjectId | null, - project?: LegacyProjectSettingsFields, + // Nullable, not just optional: the mobile new-task flow passes its selected + // project straight through, and that is null until the shell snapshot lands. + project?: LegacyProjectSettingsFields | null, ): ResolvedProjectSettings { const stored = projectId === null ? undefined : settings.projectSettingsOverrides[projectId]; const overrides: ProjectSettingsOverrides = - project === undefined || settings.projectSettingsFolded + project == null || settings.projectSettingsFolded ? (stored ?? EMPTY_OVERRIDES) : { ...(project.defaultModelSelection != null