@@ -1235,3 +1235,139 @@ fi
12351235 expect ( remainingProcesses ) . toBe ( 0 ) ;
12361236 } ) ;
12371237} ) ;
1238+
1239+ describe ( "SSH runtime redundant cd detection" , ( ) => {
1240+ // Helper to create bash tool with SSH runtime configuration
1241+ // Note: These tests check redundant cd detection logic only - they don't actually execute via SSH
1242+ function createTestBashToolWithSSH ( cwd : string ) {
1243+ const tempDir = new TestTempDir ( "test-bash-ssh" ) ;
1244+ const sshRuntime = createRuntime ( {
1245+ type : "ssh" ,
1246+ host : "test-host" ,
1247+ srcBaseDir : "/remote/base" ,
1248+ } ) ;
1249+
1250+ const tool = createBashTool ( {
1251+ cwd,
1252+ runtime : sshRuntime ,
1253+ tempDir : tempDir . path ,
1254+ } ) ;
1255+
1256+ return {
1257+ tool,
1258+ [ Symbol . dispose ] ( ) {
1259+ tempDir [ Symbol . dispose ] ( ) ;
1260+ } ,
1261+ } ;
1262+ }
1263+
1264+ it ( "should reject redundant cd to absolute path on SSH runtime" , async ( ) => {
1265+ const remoteCwd = "/home/user/project" ;
1266+ using testEnv = createTestBashToolWithSSH ( remoteCwd ) ;
1267+ const tool = testEnv . tool ;
1268+
1269+ const args : BashToolArgs = {
1270+ script : `cd ${ remoteCwd } && echo test` ,
1271+ timeout_secs : 5 ,
1272+ } ;
1273+
1274+ const result = ( await tool . execute ! ( args , mockToolCallOptions ) ) as BashToolResult ;
1275+
1276+ expect ( result . success ) . toBe ( false ) ;
1277+ if ( ! result . success ) {
1278+ expect ( result . error ) . toContain ( "Redundant cd" ) ;
1279+ expect ( result . error ) . toContain ( "already runs in" ) ;
1280+ }
1281+ } ) ;
1282+
1283+ it ( "should reject redundant cd with relative path (.) on SSH runtime" , async ( ) => {
1284+ const remoteCwd = "/home/user/project" ;
1285+ using testEnv = createTestBashToolWithSSH ( remoteCwd ) ;
1286+ const tool = testEnv . tool ;
1287+
1288+ const args : BashToolArgs = {
1289+ script : "cd . && echo test" ,
1290+ timeout_secs : 5 ,
1291+ } ;
1292+
1293+ const result = ( await tool . execute ! ( args , mockToolCallOptions ) ) as BashToolResult ;
1294+
1295+ expect ( result . success ) . toBe ( false ) ;
1296+ if ( ! result . success ) {
1297+ expect ( result . error ) . toContain ( "Redundant cd" ) ;
1298+ }
1299+ } ) ;
1300+
1301+ it ( "should reject redundant cd with tilde path on SSH runtime" , async ( ) => {
1302+ const remoteCwd = "~/project" ;
1303+ using testEnv = createTestBashToolWithSSH ( remoteCwd ) ;
1304+ const tool = testEnv . tool ;
1305+
1306+ const args : BashToolArgs = {
1307+ script : "cd ~/project && echo test" ,
1308+ timeout_secs : 5 ,
1309+ } ;
1310+
1311+ const result = ( await tool . execute ! ( args , mockToolCallOptions ) ) as BashToolResult ;
1312+
1313+ expect ( result . success ) . toBe ( false ) ;
1314+ if ( ! result . success ) {
1315+ expect ( result . error ) . toContain ( "Redundant cd" ) ;
1316+ }
1317+ } ) ;
1318+
1319+ it ( "should reject redundant cd with single tilde on SSH runtime" , async ( ) => {
1320+ const remoteCwd = "~" ;
1321+ using testEnv = createTestBashToolWithSSH ( remoteCwd ) ;
1322+ const tool = testEnv . tool ;
1323+
1324+ const args : BashToolArgs = {
1325+ script : "cd ~ && echo test" ,
1326+ timeout_secs : 5 ,
1327+ } ;
1328+
1329+ const result = ( await tool . execute ! ( args , mockToolCallOptions ) ) as BashToolResult ;
1330+
1331+ expect ( result . success ) . toBe ( false ) ;
1332+ if ( ! result . success ) {
1333+ expect ( result . error ) . toContain ( "Redundant cd" ) ;
1334+ }
1335+ } ) ;
1336+
1337+ it ( "should handle trailing slashes in path comparison on SSH runtime" , async ( ) => {
1338+ const remoteCwd = "/home/user/project" ;
1339+ using testEnv = createTestBashToolWithSSH ( remoteCwd ) ;
1340+ const tool = testEnv . tool ;
1341+
1342+ const args : BashToolArgs = {
1343+ script : "cd /home/user/project/ && echo test" ,
1344+ timeout_secs : 5 ,
1345+ } ;
1346+
1347+ const result = ( await tool . execute ! ( args , mockToolCallOptions ) ) as BashToolResult ;
1348+
1349+ expect ( result . success ) . toBe ( false ) ;
1350+ if ( ! result . success ) {
1351+ expect ( result . error ) . toContain ( "Redundant cd" ) ;
1352+ }
1353+ } ) ;
1354+
1355+ it ( "should handle cwd with trailing slash on SSH runtime" , async ( ) => {
1356+ const remoteCwd = "/home/user/project/" ;
1357+ using testEnv = createTestBashToolWithSSH ( remoteCwd ) ;
1358+ const tool = testEnv . tool ;
1359+
1360+ const args : BashToolArgs = {
1361+ script : "cd /home/user/project && echo test" ,
1362+ timeout_secs : 5 ,
1363+ } ;
1364+
1365+ const result = ( await tool . execute ! ( args , mockToolCallOptions ) ) as BashToolResult ;
1366+
1367+ expect ( result . success ) . toBe ( false ) ;
1368+ if ( ! result . success ) {
1369+ expect ( result . error ) . toContain ( "Redundant cd" ) ;
1370+ }
1371+ } ) ;
1372+ } ) ;
1373+
0 commit comments