diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs
index 7e3b03a06018f7e30c77d496b80a52a05cb6db35..7efc7279497e99890c6adf0c16ca1eb2d7789170 100644
--- a/hercules_ir/src/ir.rs
+++ b/hercules_ir/src/ir.rs
@@ -526,7 +526,7 @@ impl Function {
      * Many transformations will delete nodes. There isn't strictly a gravestone
      * node value, so use the start node as a gravestone value (for IDs other
      * than 0). This function cleans up gravestoned nodes. This function returns
-     * a map from old IDs to the new IDs, so that other datastructures can be
+     * a map from old IDs to the new IDs, so that other data structures can be
      * updated.
      */
     pub fn delete_gravestones(&mut self) -> Vec<NodeID> {
@@ -584,11 +584,11 @@ impl Function {
  * Some analysis results can be updated after gravestone deletions.
  */
 pub trait GraveUpdatable {
-    fn map_gravestones(&self, grave_mapping: &Vec<NodeID>) -> Self;
+    fn map_gravestones(self, function: &Function, grave_mapping: &Vec<NodeID>) -> Self;
 }
 
 impl<T: Clone> GraveUpdatable for Vec<T> {
-    fn map_gravestones(&self, grave_mapping: &Vec<NodeID>) -> Self {
+    fn map_gravestones(self, _function: &Function, grave_mapping: &Vec<NodeID>) -> Self {
         let mut new_self = vec![];
         for (data, (idx, mapping)) in
             std::iter::zip(self.into_iter(), grave_mapping.iter().enumerate())
diff --git a/hercules_ir/src/schedule.rs b/hercules_ir/src/schedule.rs
index 08f8103dac29219850558f16cae91d37cd98f970..4221bd8d7fb194e7ecc6142dc623bd6a1416b68d 100644
--- a/hercules_ir/src/schedule.rs
+++ b/hercules_ir/src/schedule.rs
@@ -55,6 +55,32 @@ impl Plan {
     }
 }
 
+impl GraveUpdatable for Plan {
+    /*
+     * Plans must be "repairable", in the sense that the IR that's referred to
+     * may change after many passes. Since a plan is an explicit side data
+     * structure, it must be updated after every change in the IR.
+     */
+    fn map_gravestones(self, function: &Function, grave_mapping: &Vec<NodeID>) -> Self {
+        let Plan {
+            mut schedules,
+            partitions,
+            partition_devices,
+            num_partitions,
+        } = self;
+
+        // Schedules of old nodes just get dropped. Since schedules don't hold
+        // necessary semantic information, we are free to drop them arbitrarily.
+        schedules = schedules.map_gravestones(function, grave_mapping);
+        schedules.resize(function.nodes.len(), vec![]);
+
+        // Once we've repaired the plan, now we are free to try and infer new
+        // schedules about the nodes added by previous passes.
+
+        todo!()
+    }
+}
+
 /*
  * A "default" plan should be available, where few schedules are used and
  * conservative partitioning is enacted. Only schedules that can be proven safe