@@ -359,8 +359,10 @@ describe("findExtraGatewayServices (win32)", () => {
359359 execSchtasksMock . mockResolvedValueOnce ( {
360360 code : 0 ,
361361 stdout : [
362- "TaskName: OpenClaw Gateway" ,
363- "Task To Run: C:\\Program Files\\OpenClaw\\openclaw.exe gateway run" ,
362+ // schtasks /Query /FO LIST /V prefixes task paths with \.
363+ // The canonical launcher task must be skipped despite the leading \.
364+ "TaskName: \\OpenClaw Gateway" ,
365+ "Task To Run: C:\\Users\\test\\.openclaw\\gateway.cmd" ,
364366 "" ,
365367 "TaskName: Clawdbot Legacy" ,
366368 "Task To Run: C:\\clawdbot\\clawdbot.exe run" ,
@@ -384,4 +386,44 @@ describe("findExtraGatewayServices (win32)", () => {
384386 } ,
385387 ] ) ;
386388 } ) ;
389+
390+ it ( "skips the active launcher scheduled task with \\-prefixed name" , async ( ) => {
391+ execSchtasksMock . mockResolvedValueOnce ( {
392+ code : 0 ,
393+ stdout : [
394+ // Real-world output from schtasks: task name is \OpenClaw Gateway
395+ "TaskName: \\OpenClaw Gateway" ,
396+ "Task To Run: C:\\Users\\test\\.openclaw\\gateway.cmd" ,
397+ "" ,
398+ ] . join ( "\n" ) ,
399+ stderr : "" ,
400+ } ) ;
401+
402+ const result = await findExtraGatewayServices ( { } , { deep : true } ) ;
403+ expect ( result ) . toStrictEqual ( [ ] ) ;
404+ } ) ;
405+
406+ it ( "does not skip genuinely orphaned tasks named after the old clawdbot" , async ( ) => {
407+ execSchtasksMock . mockResolvedValueOnce ( {
408+ code : 0 ,
409+ stdout : [
410+ "TaskName: \\Clawdbot Legacy Runner" ,
411+ "Task To Run: C:\\clawdbot\\clawdbot.exe run" ,
412+ "" ,
413+ ] . join ( "\n" ) ,
414+ stderr : "" ,
415+ } ) ;
416+
417+ const result = await findExtraGatewayServices ( { } , { deep : true } ) ;
418+ expect ( result ) . toEqual ( [
419+ {
420+ platform : "win32" ,
421+ label : "\\Clawdbot Legacy Runner" ,
422+ detail : "task: \\Clawdbot Legacy Runner, run: C:\\clawdbot\\clawdbot.exe run" ,
423+ scope : "system" ,
424+ marker : "clawdbot" ,
425+ legacy : true ,
426+ } ,
427+ ] ) ;
428+ } ) ;
387429} ) ;
0 commit comments