diff --git a/application/modules/courses/models/ApprovalActionForkGradModel.php b/application/modules/courses/models/ApprovalActionForkGradModel.php
new file mode 100644
index 0000000000000000000000000000000000000000..16db9a73f2664dec7cf1af82d818f92ab7b7a6da
--- /dev/null
+++ b/application/modules/courses/models/ApprovalActionForkGradModel.php
@@ -0,0 +1,255 @@
+<?php
+
+class Courses_ApprovalActionForkGradModel extends Requests_ApprovalActionModel
+{
+    static public function find($id)
+    {
+        $db = Zend_Registry::get('db');
+
+        $select = new Zend_Db_Select($db);
+        $select->from(array('a' => 'creqApprovalActions'));
+        $select->join(array('d' => 'creqApprovalActionsForkGrad'), 'a.approvalActionId = d.approvalActionId');
+        if (Unl_Util::isArray($id)) {
+            $select->where('a.approvalActionId IN(?)', $id);
+        } else {
+            $select->where('a.approvalActionId = ?', $id);
+        }
+
+        $records = $db->query($select)->fetchAll();
+        $objects = new Unl_Model_Collection(__CLASS__);
+        foreach ($records as $record) {
+            $object = Unl_Model_Registry::getInstance()->getOrAdd(new self($record));
+            $objectId = $object->getId();
+            $objects[$objectId] = $object;
+        }
+
+        if (Unl_Util::isArray($objects)) {
+            return $objects;
+        } else {
+            return array_pop($objects);
+        }
+    }
+    
+    static public function fetchNew()
+    {
+        $data = array(
+            'approvalActionId'    => NULL,
+            'name'                => '',
+            'approvalChain'       => NULL,
+            'className'           => '',
+            'participatingRoles'  => array(),
+            'editingRoles'        => array()
+        );
+        
+        $new = new self($data);
+        $new->_setClean();
+        
+        $new->_data['className'] = 'ApprovalActionForkGrad';
+        
+        return $new;
+    }
+
+    static public function save($models)
+    {
+        $modelsToInsert = new Unl_Model_Collection(__CLASS__);
+        $modelsToUpdate = new Unl_Model_Collection(__CLASS__);
+
+        if (!Unl_Util::isArray($models)) {
+            $model = $models;
+            $models = new Unl_Model_Collection(__CLASS__);
+            $models[$model->getId()] = $model;
+        }
+
+        foreach ($models as $model) {
+            if ($model->_cleanData['approvalActionId'] && $model->getId()) {
+                if ($model->_cleanData != $model->_data) {
+                    $modelsToUpdate[] = $model;
+                }
+            } else {
+                $modelsToInsert[] = $model;
+            }
+        }
+
+        if (count($modelsToInsert) > 0) {
+            self::_insert($modelsToInsert);
+        }
+
+        if (count($modelsToUpdate) > 0) {
+            self::_update($modelsToUpdate);
+        }
+    }
+
+    static protected function _update(Unl_Model_Collection $models)
+    {
+        // Nothing to update
+    }
+
+    static protected function _insert(Unl_Model_Collection $models)
+    {
+        $db = Zend_Registry::get('db');
+
+        $sql = 'INSERT INTO creqApprovalActionsForkGrad (approvalActionId) VALUES ';
+        $sqlParts = array();
+        foreach ($models as $model) {
+            $sqlParts[] = $db->quoteInto('(?) ', $model->_data['approvalActionId']);
+        }
+        $sql .= implode(', ', $sqlParts);
+        $db->query($sql);
+    }
+
+    public function getResultStatusStrings()
+    {
+        return array('Grad' => 'Grad');
+    }
+    
+    public function consider($requests)
+    {
+        $courses = Courses_CourseModel::findLatestOfRequest($requests);
+        $parentCourses = Courses_CourseModel::findParentOfRequest($requests);
+        
+        $newCourseRequests = array();
+        $newCourses = new Unl_Model_Collection('Courses_CourseModel');
+        $newRequests = new Unl_Model_Collection('Requests_RequestModel');
+        
+        $childParentRequestMap = array();
+        
+        foreach ($requests as $request) {
+            $course = $courses[$request->getId()];
+            $parentCourse = $parentCourses[$request->getId()];
+            
+            // If this isn't a Separate Grad request, we don't want to touch it.
+            if ($request->getType() != 'SeparateGrad') {
+                continue;
+            }
+            
+            // If the course isn't both grad and undergrad, there's nothing to fork!
+            if (!$course->isGraduateLevel() || !$course->isUndergraduateLevel()) {
+                continue;
+            }
+            
+            // create a new generation of the course that will have the grad crosslistings removed
+            $newGeneration = clone $course;
+            // create a new generation of the course from the input request to base the new request on.
+            $gradCourse = clone $course;
+            
+            // Grab the home suffix now in case we need to use it later (ie: xx in 4xx/8xx)
+            $homeSuffix = substr($course->getCourseNumber(), -2);
+            
+            // Remove either the grad or the undergrad crosslistings for each course.
+            foreach ($newGeneration->getCrosslistings() as $crosslistingId => $crosslisting) {
+                if ($crosslisting['courseNumber'] >= 500) {
+                    $newGeneration->removeCrosslisting($crosslistingId);
+                }
+            }
+            
+            // Remove all under grad listings, and promote the grad tie-in to the home listing.
+            $foundGradTieIn = FALSE;
+            foreach ($gradCourse->getCrosslistings() as $crosslistingId => $crosslisting) {
+                if ($crosslisting['courseNumber'] < 500) {
+                    $gradCourse->removeCrosslisting($crosslistingId);
+                }
+                if ($crosslisting['type'] == 'grad tie-in') {
+                    $gradCourse->editCrosslisting(
+                        $crosslistingId,
+                        'home listing',
+                        $crosslisting['subject'],
+                        $crosslisting['courseNumber'],
+                        $crosslisting['courseLetter']
+                    );
+                    $foundGradTieIn = TRUE;
+                }
+            }
+            
+            // If no grad tie-in was found, see if a matching suffix can be found instead.
+            if (!$foundGradTieIn) {
+                foreach ($gradCourse->getCrosslistings() as $crosslisting) {
+                    if (substr($crosslisting['courseNumber'], -2) != $homeSuffix) {
+                        continue;
+                    }
+                    $gradCourse->editCrosslisting(
+                        $crosslistingId,
+                        'home listing',
+                        $crosslisting['subject'],
+                        $crosslisting['courseNumber'],
+                        $crosslisting['courseLetter']
+                    );
+                    $foundGradTieIn = TRUE;
+                    break;
+                }
+            }
+            
+            // If we still haven't found the primary grad tie-in, just use the first one.
+            if (!$foundGradTieIn) {
+                foreach ($gradCourse->getCrosslistings() as $crosslisting) {
+                    $gradCourse->editCrosslisting(
+                        $crosslistingId,
+                        'home listing',
+                        $crosslisting['subject'],
+                        $crosslisting['courseNumber'],
+                        $crosslisting['courseLetter']
+                    );
+                    $foundGradTieIn = TRUE;
+                    break;
+                }
+            } 
+            
+            // set the existing request to change course.
+            $request->setType('ChangeCourse');
+            
+            // create the new request to contain only the grad data.
+            $newRequest = clone $request;
+            $childParentRequestMap[] = array('child' => $newRequest, 'parent' => $request);
+            $newRequest->setType('NewCourse');
+            $newRequest->setState('Grad');
+            
+            $newRequests[] = $newRequest;
+            $newCourses[] = $newGeneration;
+            $newCourses[] = $gradCourse;
+            $newCourseRequests[] = array(
+                'request' => $newRequest,
+                'course' => $gradCourse
+            );
+        }
+        Courses_CourseModel::save($courses);
+        Requests_RequestModel::save($requests);
+        Requests_RequestModel::save($newRequests);
+        
+        foreach ($newCourseRequests as $newCourseRequest) {
+            $request = $newCourseRequest['request'];
+            $course = $newCourseRequest['course'];
+            
+            $course->setRequest($request);
+        }
+        
+        Courses_CourseModel::save($newCourses);
+        
+        // Copy the watchers from the parent requests to the child requests
+        $db = Zend_Registry::get('db');
+        foreach ($childParentRequestMap as $childParentRequests) {
+        	$parent = $childParentRequests['parent'];
+        	$child = $childParentRequests['child'];
+        	$sql = 'INSERT INTO creqRequestWatchers (request, watchingApprovalRole) '
+        	     . $db->quoteInto('SELECT ?, watchingApprovalRole ', $child->getId())
+        	     . 'FROM creqRequestWatchers AS w '
+        	     . $db->quoteInto('WHERE w.request=? ', $parent->getId());
+        	     ;
+            $db->query($sql);
+        }
+        
+        //  all done... advance all requests and return them for consideration
+        $allRequests = $requests->merge($newRequests);
+        Requests_ApprovalChainModel::advance($requests);
+        return $requests;
+    }
+
+    public function setExtendedData($in)
+    {
+        // No extended data
+    }
+
+    public function userMadeDecisions($requests, $requestDecisions)
+    {
+        // Don't do anything here, this is an automated action.
+    }
+
+}
diff --git a/application/modules/courses/models/CourseModel.php b/application/modules/courses/models/CourseModel.php
index 9d7a83112b95715fa41826ee26ce9700687be9c6..8cd6e957571ffe7dca0e91a440d428664340ed91 100644
--- a/application/modules/courses/models/CourseModel.php
+++ b/application/modules/courses/models/CourseModel.php
@@ -897,8 +897,8 @@ class Courses_CourseModel extends Unl_Model
 
                 if (is_array($model->_cleanData['crosslistings'])) {
                     $keysToDelete = array_diff_key($model->_cleanData['crosslistings'], $model->_data['crosslistings']);
-                    foreach ($keysToDelete as $keyToDelete) {
-                        $activitiesToDelete[] = $model->_cleanData['crosslistings'][$keyToDelete]['courseCrosslistingId'];
+                    foreach (array_keys($keysToDelete) as $keyToDelete) {
+                        $crosslistingsToDelete[] = $model->_cleanData['crosslistings'][$keyToDelete]['courseCrosslistingId'];
                     }
                 }
             }
@@ -1689,7 +1689,7 @@ class Courses_CourseModel extends Unl_Model
 
         $db = Zend_Registry::get('db');
 
-        $sql = $db->quoteInto('DELETE FROM creqCourseCrosslistings WHERE creqCourseCrosslistingId IN (?)', $models);
+        $sql = $db->quoteInto('DELETE FROM creqCourseCrosslistings WHERE courseCrosslistingId IN (?)', $models);
         $db->query($sql);
     }
     
diff --git a/application/modules/courses/views/scripts/approval-chain-manager/edit-action/forkGrad.phtml b/application/modules/courses/views/scripts/approval-chain-manager/edit-action/forkGrad.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..b3d9bbc7f3711e882119cd6b3af051245d859d04
--- /dev/null
+++ b/application/modules/courses/views/scripts/approval-chain-manager/edit-action/forkGrad.phtml
@@ -0,0 +1 @@
+<?php