Data streams maintain a list of backing indices. The last index in the list is considered the "write" index which is afforded a number of protections to keep it from being deleted or incorrectly changed underneath the stream.

Each time CCR creates a new follower index that belongs to a replicated data stream, [the follow API performs a sort operation](https://github.com/elastic/elasticsearch/blob/248918f142b870b18fd5168a3210947e6550d3df/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportPutFollowAction.java#L339) on the replicated data stream's backing index list. This is to keep older backing indices that are being followed from incorrectly replacing the latest backing index, which should logically be the write index.

The problem with this consistency model is that it assumes the backing indices are always sortable such that the youngest index is last lexicographically. In the case that the follower cluster has an ILM policy that replaces a replicated data stream's backing indices with mounted searchable snapshots, the resulting names will be prefixed with `restored-` or `partial-` which will always sort later than the regular data stream prefix of `.ds-`.

If an index mounted as a searchable snapshot is incorrectly "sorted" to the back of the backing index list, it can make the resulting index impossible to delete until another searchable snapshot of a younger backing index is created and a new follower is created to re-sort the list and free the older index from the incorrectly assumed write index position.

Example: Assuming the following data stream `data-test`. The follower cluster is setup with an auto follow pattern that follows indices named `.ds-data-test*`. An ILM policy that converts aging indices to searchable snapshots and then deletes them after a time is present on both clusters.

Initial state, a replicated data stream with three backing indices:
Leader:  `[.ds-data-test-01, .ds-data-test-02, .ds-data-test-03]`
Follower:  `[.ds-data-test-01, .ds-data-test-02, .ds-data-test-03]`

ILM converts oldest index (01) to a mounted searchable snapshot:
Leader:  `[restored-.ds-data-test-01, .ds-data-test-02, .ds-data-test-03]`
Follower:  `[restored-.ds-data-test-01, .ds-data-test-02, .ds-data-test-03]`

ILM rolls over the data stream on the leader. A new write index (04) is created on the leader and replicated to the follower, triggering the sort bug:
Leader:  `[restored-.ds-data-test-01, .ds-data-test-02, .ds-data-test-03, .ds-data-test-04]`
Follower:  `[.ds-data-test-02, .ds-data-test-03, .ds-data-test-04, restored-.ds-data-test-01]`

Eventually, when ILM goes to delete the oldest index (01), it cannot on the follower cluster because the oldest index was sorted to the last position in the array and is considered the data stream's write index:
Leader:  `[.ds-data-test-02, .ds-data-test-03, .ds-data-test-04]`
Follower:  `[.ds-data-test-02, .ds-data-test-03, .ds-data-test-04, restored-.ds-data-test-01]` // STUCK

ILM will continue looping trying to delete the index (01) until the next oldest index (02) becomes a searchable snapshot...
Leader:  `[restored-.ds-data-test-02, .ds-data-test-03, .ds-data-test-04]`
Follower:  `[restored-.ds-data-test-02, .ds-data-test-03, .ds-data-test-04, restored-.ds-data-test-01]` // Still Stuck

... and another rollover happens so that the next oldest (02) is sorted to the end:
Leader:  `[restored-.ds-data-test-02, .ds-data-test-03, .ds-data-test-04, .ds-data-test-05]`
Follower:  `[.ds-data-test-03, .ds-data-test-04, .ds-data-test-05, restored-.ds-data-test-02]` // Old index-01 finally deleted.


x-pack/plugin/ccr/qa/multi-cluster/src/test/java/org/elasticsearch/xpack/ccr/AutoFollowIT.java
var followerDataStreamName = "logs-http-na";
        try {
            
            createAutoFollowPattern(client(), "id1", "logs-*-eu", "leader_cluster", null);
            
            try (var leaderClient = buildLeaderClient()) {
                initialNumberOfSuccessfulFollowedIndicesInLeaderCluster = getNumberOfSuccessfulFollowedIndices(leaderClient);
                
                var request = new Request("PUT", "/_cluster/settings");
                try (var bodyBuilder = JsonXContent.contentBuilder()) {
                    bodyBuilder.startObject();
                    {
                        bodyBuilder.startObject("persistent");
                        {
                            bodyBuilder.startObject("cluster");
                            {
                                bodyBuilder.startObject("remote");
                                {
                                    bodyBuilder.startObject("follower_cluster");
                                    {
                                        bodyBuilder.startArray("seeds");
                                        var nodesInfoRequest = new Request("GET", "/_nodes/_local");
                                        var nodesInfoResponse = toMap(client().performRequest(nodesInfoRequest));
                                        var node = (Map<?, ?>) ((Map<?, ?>) nodesInfoResponse.get("nodes")).values().iterator().next();
                                        var transportMetrics = (Map<?, ?>) node.get("transport");
                                        var address = (String) transportMetrics.get("publish_address");
                                        bodyBuilder.value(address);
                                        bodyBuilder.endArray();
                                    }
                                    bodyBuilder.endObject();