@@ -569,6 +569,8 @@ describe("TaskCreationSaga", () => {
569569 runtimeAdapter : null ,
570570 model : null ,
571571 reasoningEffort : null ,
572+ sandboxEnvironmentId : null ,
573+ customImageId : null ,
572574 } ) ;
573575 // The bundle must land on the warm run before createTask triggers activation.
574576 expect ( mockHost . uploadRunAttachments ) . toHaveBeenCalledWith (
@@ -687,6 +689,83 @@ describe("TaskCreationSaga", () => {
687689 } ) ;
688690 } ) ;
689691
692+ it . each ( [
693+ {
694+ selection : "sandbox environment" ,
695+ input : { sandboxEnvironmentId : "environment-123" } ,
696+ expectedRunOptions : { sandboxEnvironmentId : "environment-123" } ,
697+ } ,
698+ {
699+ selection : "custom image" ,
700+ input : { customImageId : "image-123" } ,
701+ expectedRunOptions : { customImageId : "image-123" } ,
702+ } ,
703+ ] ) (
704+ "falls back to a cold run without a matching warm $selection lease" ,
705+ async ( { input, expectedRunOptions } ) => {
706+ mockHost . takeWarmTaskLease . mockReturnValue ( null ) ;
707+ const createdTask = createTask ( ) ;
708+ const startedTask = createTask ( { latest_run : createRun ( ) } ) ;
709+ const createTaskMock = vi . fn ( ) . mockResolvedValue ( createdTask ) ;
710+ const createTaskRunMock = vi . fn ( ) . mockResolvedValue ( createRun ( ) ) ;
711+ const startTaskRunMock = vi . fn ( ) . mockResolvedValue ( startedTask ) ;
712+ const saga = makeSaga ( {
713+ createTask : createTaskMock ,
714+ createTaskRun : createTaskRunMock ,
715+ startTaskRun : startTaskRunMock ,
716+ } ) ;
717+
718+ const result = await saga . run ( {
719+ content : "Ship the fix" ,
720+ repository : "posthog/posthog" ,
721+ workspaceMode : "cloud" ,
722+ branch : "main" ,
723+ ...input ,
724+ } ) ;
725+
726+ expect ( result . success ) . toBe ( true ) ;
727+ expect ( createTaskMock . mock . calls [ 0 ] [ 0 ] . branch ) . toBeUndefined ( ) ;
728+ expect ( createTaskRunMock ) . toHaveBeenCalledWith (
729+ "task-123" ,
730+ expect . objectContaining ( expectedRunOptions ) ,
731+ ) ;
732+ } ,
733+ ) ;
734+
735+ it ( "reuses a warm run built from the selected custom image" , async ( ) => {
736+ mockHost . takeWarmTaskLease . mockReturnValue ( {
737+ taskId : "warm-task" ,
738+ runId : "warm-run" ,
739+ } ) ;
740+ const warmActivatedTask = createTask ( {
741+ id : "warm-task" ,
742+ latest_run : createRun ( { id : "warm-run" , task : "warm-task" } ) ,
743+ } ) ;
744+ const createTaskMock = vi . fn ( ) . mockResolvedValue ( warmActivatedTask ) ;
745+ const createTaskRunMock = vi . fn ( ) ;
746+ const saga = makeSaga ( {
747+ createTask : createTaskMock ,
748+ createTaskRun : createTaskRunMock ,
749+ } ) ;
750+
751+ const result = await saga . run ( {
752+ content : "Ship the fix" ,
753+ repository : "posthog/posthog" ,
754+ workspaceMode : "cloud" ,
755+ branch : "main" ,
756+ customImageId : "image-123" ,
757+ } ) ;
758+
759+ expect ( result . success ) . toBe ( true ) ;
760+ expect ( createTaskMock ) . toHaveBeenCalledWith (
761+ expect . objectContaining ( {
762+ branch : "main" ,
763+ custom_image_id : "image-123" ,
764+ } ) ,
765+ ) ;
766+ expect ( createTaskRunMock ) . not . toHaveBeenCalled ( ) ;
767+ } ) ;
768+
690769 it ( "uses the selected user GitHub integration for cloud task creation" , async ( ) => {
691770 const createdTask = createTask ( {
692771 github_user_integration : "user-integration-123" ,
0 commit comments