diff --git a/application/modules/courses/models/ApprovalActionForkAceModel.php b/application/modules/courses/models/ApprovalActionForkAceModel.php
new file mode 100644
index 0000000000000000000000000000000000000000..0106ff4a1dd46c4052150ec3f2d1be15f9688ad6
--- /dev/null
+++ b/application/modules/courses/models/ApprovalActionForkAceModel.php
@@ -0,0 +1,203 @@
+<?php
+
+class Courses_ApprovalActionForkAceModel 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' => 'creqApprovalActionsForkAce'), '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'] = 'ApprovalActionForkAce';
+        
+        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 creqApprovalActionsForkAce (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('ACE' => 'ACE');
+    }
+    
+    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');
+        
+        foreach ($requests as $request) {
+            
+            // check to see what each of the new request types will be
+            switch ($request->getType()) {
+                case 'NewCourseWithACE':
+                    $request->setType('NewCourse');
+                    $addAce = true;
+                    break;
+                case 'AddACEAndChangeCourse':
+                    $request->setType('ChangeCourse');
+                    $addAce = true;
+                    break;
+                case 'RemoveACEAndChangeCourse':
+                    $request->setType('ChangeCourse');
+                    $addAce = false;
+                    break;
+                default:
+                    continue 2;
+                    break;
+            }
+            
+            $course = $courses[$request->getId()];
+            $parentCourse = $parentCourses[$request->getId()];
+            
+            // create a new generation of the course from the input request to base the new request on.
+            $aceCourse = clone $course;
+            
+            // either remove or add the ACE data to the non-ACE request's course.
+            if ($addAce) {
+                $course->removeAce();
+            } else {
+                $course = new Courses_CourseModel();
+                foreach ($parentCourse->getAceOutcomes() as $aceOutcome) {
+                    $course->setAceOutcome($aceOutcome['name'],
+                                           $aceOutcome['justification'],
+                                           $aceOutcome['studentWork'],
+                                           $aceOutcome['assesmentPlan']
+                                           );
+                }
+                foreach ($parentCourse->getAceReinforcements() as $aceReinforcement) {
+                    $course->setAceReinforcement($aceReinforcement['name'],
+                                                 $aceReinforcement['description']);
+                }
+            }
+            
+            // create the new request to contain only the ACE data.
+            $newRequest = clone $request;
+            if ($addAce) {
+                $newRequest->setType('AddACEToCourse');
+            } else {
+                $newRequest->setType('RemoveACEFromCourse');
+            }
+            $newRequest->setState('ACE');
+            
+            $newRequests[] = $newRequest;
+            $newCourses[] = $aceCourse;
+            $newCourseRequests[] = array(
+                'request' => $newRequest,
+                'course' => $aceCourse
+            );
+        }
+        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);
+        
+        //  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/views/scripts/approval-chain-manager/edit-action/forkAce.phtml b/application/modules/courses/views/scripts/approval-chain-manager/edit-action/forkAce.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..b3d9bbc7f3711e882119cd6b3af051245d859d04
--- /dev/null
+++ b/application/modules/courses/views/scripts/approval-chain-manager/edit-action/forkAce.phtml
@@ -0,0 +1 @@
+<?php
diff --git a/application/modules/requests/models/CommentsModel.php b/application/modules/requests/models/CommentsModel.php
index 37362e764f43e67ff8baca90e37b41aa10bf6212..b219131cadb8683f87bb73fd921289fe2c78b0e3 100644
--- a/application/modules/requests/models/CommentsModel.php
+++ b/application/modules/requests/models/CommentsModel.php
@@ -192,6 +192,11 @@ class Requests_CommentsModel extends Unl_Model
         $db->query($sql);
     }
 
+    public function __clone()
+    {
+        unset($this->_data['requestCommentId']);
+    }
+    
     public function getId()
     {
     	return $this->_data['requestCommentId'];
diff --git a/application/modules/requests/models/RequestModel.php b/application/modules/requests/models/RequestModel.php
index 72c7888e16982faa5a0bbb17d0819764ca3c2329..e26d93aaebd50a8d4b496ed6c54686f7321044d3 100644
--- a/application/modules/requests/models/RequestModel.php
+++ b/application/modules/requests/models/RequestModel.php
@@ -9,6 +9,7 @@ class Requests_RequestModel extends Unl_Model
 
     static protected $_typeMap;
     static protected $_typeDescriptions;
+    protected $_clonedFrom;
 
     static public function find($id)
     {
@@ -397,6 +398,8 @@ class Requests_RequestModel extends Unl_Model
         	self::_insertRequestRows($modelsToInsert);
         	self::_updateRequestRows($modelsToUpdate);
 
+            self::_cloneCleanup($models);
+            
             $filesToInsert = array();
             $filesToUpdate = array();
         	foreach ($models as $model) {
@@ -443,7 +446,7 @@ class Requests_RequestModel extends Unl_Model
         	foreach ($models as $model) {
         		$model->_setClean();
         	}
-
+        	
             $db->commit();
 
     	} catch (Exception $e) {
@@ -704,6 +707,56 @@ class Requests_RequestModel extends Unl_Model
         return $data;
     }
     
+    static protected function _cloneCleanup($models)
+    {
+        $cloneMap = array();
+        foreach ($models as $model) {
+            if (!$model->_clonedFrom) {
+                continue;
+            }
+            $cloneMap[$model->_clonedFrom] = $model;
+            $model->_clonedFrom = NULL;
+        }
+        
+        $parentRequests = self::find(array_keys($cloneMap));
+        $parentRequestComments = Requests_CommentsModel::findByRequest($parentRequests);
+        $newComments = new Unl_Model_Collection('Requests_CommentsModel');
+        
+        foreach ($cloneMap as $parentRequestId => $newRequest) {
+            foreach ($parentRequestComments[$parentRequestId] as $parentComment) {
+                $newComment = clone $parentComment;
+                $newComment->setRequest($newRequest);
+                $newComments[] = $newComment;
+            }
+        }
+        
+        Requests_CommentsModel::save($newComments);
+        
+        $db = Zend_Registry::get('db');
+        $sql = 'INSERT INTO creqRequestFiles (file, request, type) VALUES ';
+        $sqlParts = array();
+        foreach ($cloneMap as $parentRequestId => $newRequest) {
+            foreach ($newRequest->_data['files'] as $file) {
+                $sqlParts[] = $db->quoteInto('(?, ', $file['fileId'])
+                            . $db->quoteInto('?, ' , $newRequest->getId())
+                            . $db->quoteInto('?)'  , $file['type']);
+            }
+        }
+        
+        if (count($sqlParts) > 0) {
+            $sql .= implode(', ', $sqlParts);
+            
+            $db->query($sql);
+            $lastId = $db->lastInsertId();
+            foreach ($cloneMap as $parentRequestId => $newRequest) {
+                foreach ($newRequest->_data['files'] as &$file) {
+                    $file['requestFileId'] = $lastId;
+                    $lastId++;
+                }
+            }
+        }
+    }
+    
     public function __sleep()
     {
     	foreach ($this->_data['files'] as &$file) {
@@ -726,6 +779,21 @@ class Requests_RequestModel extends Unl_Model
         }
     }
 
+    public function __clone()
+    {
+        $this->_clonedFrom = $this->_data['requestId'];
+        unset($this->_data['requestId']);
+        
+        foreach ($this->_data['files'] as $key => &$file) {
+            unset($file['requestFileId']);
+        }
+        
+        if ($this->_data['stackPointer']) {
+            $newStack = clone Requests_StackModel::find($this->_data['stackPointer']);
+            $this->_data['stackPointer'] = $newStack->getId();
+        }
+    }
+    
     public function getId()
     {
         return $this->_data['requestId'];
@@ -799,7 +867,7 @@ class Requests_RequestModel extends Unl_Model
 	}
 	
 	public function getOwnerModel()
-	{	
+	{
 		if (!$this->_owner) {
 	        if (!$this->getOwner()) {
 	            return null;
@@ -813,6 +881,11 @@ class Requests_RequestModel extends Unl_Model
 	{
 		$this->_data['owner'] = $owner->getId();
 	}
+	
+	public function setOwnerId($ownerId)
+	{
+	    $this->_data['owner'] = $ownerId;
+	}
 
 	public function getState()
 	{
@@ -873,7 +946,7 @@ class Requests_RequestModel extends Unl_Model
 	}
 	
 	public function addFile($type, $title, $mimeType, $data)
-	{	
+	{
         $lowestId = min(array_keys($this->_data['files']));
         if (!($lowestId < 0)) {
             $lowestId = 0;
diff --git a/application/modules/requests/models/StackModel.php b/application/modules/requests/models/StackModel.php
index 687976d5f996495aa52042c6c4bd4161d664c4e7..3cd46af9f0ce75872dbddec643af74955e107848 100644
--- a/application/modules/requests/models/StackModel.php
+++ b/application/modules/requests/models/StackModel.php
@@ -231,4 +231,14 @@ class Requests_StackModel extends Unl_Model
     {
         $this->_data['previous'] = $previousId;
     }
+
+    public function __clone()
+    {
+        unset($this->_data['requestStackId']);
+        if ($this->_data['previous']) {
+            $newPrevious = clone self::find($this->_data['previous']);
+            $this->_data['previous'] = $newPrevious->getId();
+        }
+        self::save($this);
+    }
 }
\ No newline at end of file