@@ -906,7 +906,10 @@ export class SSHRuntime implements Runtime {
906906 }
907907 initLogger . logStep ( "Branch checked out successfully" ) ;
908908
909- // 3. Run .mux/init hook if it exists
909+ // 3. Pull latest from origin (best-effort, non-blocking on failure)
910+ await this . pullLatestFromOrigin ( workspacePath , trunkBranch , initLogger , abortSignal ) ;
911+
912+ // 4. Run .mux/init hook if it exists
910913 // Note: runInitHook calls logComplete() internally if hook exists
911914 const hookExists = await checkInitHookExists ( projectPath ) ;
912915 if ( hookExists ) {
@@ -928,6 +931,68 @@ export class SSHRuntime implements Runtime {
928931 }
929932 }
930933
934+ /**
935+ * Fetch and rebase on latest origin/<trunkBranch> on remote
936+ * Best-effort operation - logs status but doesn't fail workspace initialization
937+ */
938+ private async pullLatestFromOrigin (
939+ workspacePath : string ,
940+ trunkBranch : string ,
941+ initLogger : InitLogger ,
942+ abortSignal ?: AbortSignal
943+ ) : Promise < void > {
944+ try {
945+ initLogger . logStep ( `Fetching latest from origin/${ trunkBranch } ...` ) ;
946+
947+ // Fetch the trunk branch from origin
948+ const fetchCmd = `git fetch origin ${ shescape . quote ( trunkBranch ) } ` ;
949+ const fetchStream = await this . exec ( fetchCmd , {
950+ cwd : workspacePath ,
951+ timeout : 120 , // 2 minutes for network operation
952+ abortSignal,
953+ } ) ;
954+
955+ const fetchExitCode = await fetchStream . exitCode ;
956+ if ( fetchExitCode !== 0 ) {
957+ const fetchStderr = await streamToString ( fetchStream . stderr ) ;
958+ initLogger . logStderr (
959+ `Note: Could not fetch from origin (${ fetchStderr } ), using local branch state`
960+ ) ;
961+ return ;
962+ }
963+
964+ initLogger . logStep ( "Fast-forward merging..." ) ;
965+
966+ // Attempt fast-forward merge from origin/<trunkBranch>
967+ const mergeCmd = `git merge --ff-only origin/${ shescape . quote ( trunkBranch ) } ` ;
968+ const mergeStream = await this . exec ( mergeCmd , {
969+ cwd : workspacePath ,
970+ timeout : 60 , // 1 minute for fast-forward merge
971+ abortSignal,
972+ } ) ;
973+
974+ const [ mergeStderr , mergeExitCode ] = await Promise . all ( [
975+ streamToString ( mergeStream . stderr ) ,
976+ mergeStream . exitCode ,
977+ ] ) ;
978+
979+ if ( mergeExitCode !== 0 ) {
980+ // Fast-forward not possible (diverged branches) - just warn
981+ initLogger . logStderr (
982+ `Note: Fast-forward skipped (${ mergeStderr || "branches diverged" } ), using local branch state`
983+ ) ;
984+ } else {
985+ initLogger . logStep ( "Fast-forwarded to latest origin successfully" ) ;
986+ }
987+ } catch ( error ) {
988+ // Non-fatal: log and continue
989+ const errorMsg = getErrorMessage ( error ) ;
990+ initLogger . logStderr (
991+ `Note: Could not fetch from origin (${ errorMsg } ), using local branch state`
992+ ) ;
993+ }
994+ }
995+
931996 async renameWorkspace (
932997 projectPath : string ,
933998 oldName : string ,
0 commit comments