Fix SerializerSupport.reconstruct, and introduce RangeFactory
diff --git a/accord-core/src/main/java/accord/api/RoutingKey.java b/accord-core/src/main/java/accord/api/RoutingKey.java
index 4ae6506..b219036 100644
--- a/accord-core/src/main/java/accord/api/RoutingKey.java
+++ b/accord-core/src/main/java/accord/api/RoutingKey.java
@@ -19,6 +19,7 @@
 package accord.api;
 
 import accord.primitives.Range;
+import accord.primitives.RangeFactory;
 import accord.primitives.RoutableKey;
 import accord.primitives.Unseekable;
 
@@ -26,4 +27,5 @@
 {
     @Override default RoutingKey toUnseekable() { return this; }
     Range asRange();
+    RangeFactory rangeFactory();
 }
diff --git a/accord-core/src/main/java/accord/local/SerializerSupport.java b/accord-core/src/main/java/accord/local/SerializerSupport.java
index fb8f121..cefe63c 100644
--- a/accord-core/src/main/java/accord/local/SerializerSupport.java
+++ b/accord-core/src/main/java/accord/local/SerializerSupport.java
@@ -73,6 +73,7 @@
             case PreCommitted:
                 return accepted(attrs, status, executeAt, promised, accepted, messageProvider);
             case Committed:
+            case Stable:
             case ReadyToExecute:
                 return committed(attrs, status, executeAt, promised, accepted, waitingOnProvider, messageProvider);
             case PreApplied:
diff --git a/accord-core/src/main/java/accord/messages/CheckStatus.java b/accord-core/src/main/java/accord/messages/CheckStatus.java
index a98e5ff..f888f48 100644
--- a/accord-core/src/main/java/accord/messages/CheckStatus.java
+++ b/accord-core/src/main/java/accord/messages/CheckStatus.java
@@ -437,7 +437,7 @@
 
         public Ranges matchingRanges(Predicate<FoundKnown> match)
         {
-            return foldlWithBounds((known, ranges, start, end) -> match.test(known) ? ranges.with(Ranges.of(start.asRange().newRange(start, end))) : ranges, Ranges.EMPTY, i -> false);
+            return foldlWithBounds((known, ranges, start, end) -> match.test(known) ? ranges.with(Ranges.of(start.rangeFactory().newRange(start, end))) : ranges, Ranges.EMPTY, i -> false);
         }
 
         private static FoundKnown reduceInferredOrKnownForWithQuorum(FoundKnown foundKnown, @Nullable FoundKnown prev)
@@ -474,7 +474,7 @@
                 if (!required.isSatisfiedBy(known))
                     return prev;
 
-                return prev.with(Ranges.of(start.asRange().newRange(start, end)));
+                return prev.with(Ranges.of(start.rangeFactory().newRange(start, end)));
             }, Ranges.EMPTY, i -> false);
         }
 
diff --git a/accord-core/src/main/java/accord/primitives/LatestDeps.java b/accord-core/src/main/java/accord/primitives/LatestDeps.java
index 98020ad..c2a03e3 100644
--- a/accord-core/src/main/java/accord/primitives/LatestDeps.java
+++ b/accord-core/src/main/java/accord/primitives/LatestDeps.java
@@ -134,7 +134,7 @@
             if (!slice) slice = rangeDeps.indexOfStart(start) != -1 || rangeDeps.indexOfStart(end) != -1 - rangeDeps.rangeCount();
             if (!slice) return deps;
 
-            Ranges ranges = Ranges.of(start.asRange().newRange(start, end));
+            Ranges ranges = Ranges.of(start.rangeFactory().newRange(start, end));
             return new Deps(keyDeps.slice(ranges), rangeDeps.slice(ranges));
         }
 
@@ -327,7 +327,7 @@
 
         private <V> Stream<V> stream(TriFunction<Ranges, MergeEntry, BiFunction<Deps, Ranges, V>, Stream<V>> selector, BiFunction<Deps, Ranges, V> getter)
         {
-            Range rangeFactory = starts[0].asRange();
+            RangeFactory rangeFactory = starts[0].rangeFactory();
             return IntStream.range(0, size())
                             .filter(i -> values[i] != null)
                             .mapToObj(i -> selector.apply(Ranges.of(rangeFactory.newRange(starts[i], starts[i+1])), values[i], getter))
diff --git a/accord-core/src/main/java/accord/primitives/Range.java b/accord-core/src/main/java/accord/primitives/Range.java
index a656c9b..f652186 100644
--- a/accord-core/src/main/java/accord/primitives/Range.java
+++ b/accord-core/src/main/java/accord/primitives/Range.java
@@ -35,7 +35,7 @@
 /**
  * A range of keys
  */
-public abstract class Range implements Comparable<RoutableKey>, Unseekable, Seekable
+public abstract class Range implements Comparable<RoutableKey>, Unseekable, Seekable, RangeFactory
 {
     public static class EndInclusive extends Range
     {
diff --git a/accord-core/src/main/java/accord/primitives/RangeFactory.java b/accord-core/src/main/java/accord/primitives/RangeFactory.java
new file mode 100644
index 0000000..6eb4dbb
--- /dev/null
+++ b/accord-core/src/main/java/accord/primitives/RangeFactory.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package accord.primitives;
+
+import accord.api.RoutingKey;
+
+public interface RangeFactory
+{
+    Range newRange(RoutingKey start, RoutingKey end);
+}
diff --git a/accord-core/src/test/java/accord/impl/IntHashKey.java b/accord-core/src/test/java/accord/impl/IntHashKey.java
index df90d2b..1d0ffd3 100644
--- a/accord-core/src/test/java/accord/impl/IntHashKey.java
+++ b/accord-core/src/test/java/accord/impl/IntHashKey.java
@@ -25,6 +25,7 @@
 
 import accord.api.RoutingKey;
 import accord.local.ShardDistributor;
+import accord.primitives.RangeFactory;
 import accord.primitives.RoutableKey;
 import accord.primitives.Ranges;
 import accord.primitives.Keys;
@@ -128,6 +129,12 @@
         {
             return new Range(new Hash(hash - 1), new Hash(hash));
         }
+
+        @Override
+        public RangeFactory rangeFactory()
+        {
+            return (s, e) -> new Range((Hash) s, (Hash) e);
+        }
     }
 
     public static class Range extends accord.primitives.Range.EndInclusive
diff --git a/accord-core/src/test/java/accord/impl/IntKey.java b/accord-core/src/test/java/accord/impl/IntKey.java
index 2fa8df6..ae57550 100644
--- a/accord-core/src/test/java/accord/impl/IntKey.java
+++ b/accord-core/src/test/java/accord/impl/IntKey.java
@@ -24,6 +24,7 @@
 
 import accord.api.RoutingKey;
 import accord.local.ShardDistributor;
+import accord.primitives.RangeFactory;
 import accord.primitives.RoutableKey;
 import accord.primitives.Keys;
 import accord.primitives.RoutingKeys;
@@ -128,6 +129,12 @@
         {
             return new Range(new Routing(key - 1), new Routing(key));
         }
+
+        @Override
+        public RangeFactory rangeFactory()
+        {
+            return (s, e) -> new Range((Routing)s, (Routing)e);
+        }
     }
 
     public static class Range extends accord.primitives.Range.EndInclusive
diff --git a/accord-core/src/test/java/accord/impl/PrefixedIntHashKey.java b/accord-core/src/test/java/accord/impl/PrefixedIntHashKey.java
index a8dab2b..2ee13d4 100644
--- a/accord-core/src/test/java/accord/impl/PrefixedIntHashKey.java
+++ b/accord-core/src/test/java/accord/impl/PrefixedIntHashKey.java
@@ -25,6 +25,7 @@
 
 import accord.api.RoutingKey;
 import accord.local.ShardDistributor;
+import accord.primitives.RangeFactory;
 import accord.primitives.Ranges;
 import accord.primitives.RoutableKey;
 import accord.utils.CRCUtils;
@@ -127,6 +128,12 @@
         {
             super(prefix, key, isHash);
         }
+
+        @Override
+        public RangeFactory rangeFactory()
+        {
+            return (s, e) -> new Range((PrefixedIntRoutingKey) s, (PrefixedIntRoutingKey) e);
+        }
     }
 
     public static final class Sentinel extends PrefixedIntRoutingKey
diff --git a/accord-maelstrom/src/main/java/accord/maelstrom/MaelstromKey.java b/accord-maelstrom/src/main/java/accord/maelstrom/MaelstromKey.java
index 70246a3..3514afa 100644
--- a/accord-maelstrom/src/main/java/accord/maelstrom/MaelstromKey.java
+++ b/accord-maelstrom/src/main/java/accord/maelstrom/MaelstromKey.java
@@ -24,6 +24,7 @@
 import accord.api.RoutingKey;
 
 import accord.local.ShardDistributor;
+import accord.primitives.RangeFactory;
 import accord.primitives.RoutableKey;
 import accord.utils.Invariants;
 import com.google.gson.TypeAdapter;
@@ -149,6 +150,12 @@
             return new Range(new Routing(datum.hashCode() - 1),
                              new Routing(datum.hashCode()));
         }
+
+        @Override
+        public RangeFactory rangeFactory()
+        {
+            return Range::new;
+        }
     }
 
     public static class Range extends accord.primitives.Range.EndInclusive