When I filter the list used in virtual-repeat.for so that the new list is shorter than the count of visible items the old items appear as "ghosts". I think the culprit is in _inPlaceProcessItems of array-virtual-repeat-strategy.js where there is no check in the first for loop whether we are working beyond the itemsLength
if (view.bindingContext[local] === items[i + first] && view.overrideContext.$middle === middle && view.overrideContext.$last === last) {
Here items[i+first] can actually point to a non-existing item since the itemsLength is less than viewsLength. In such a case the code should probably remove the old views instead.