I probably don't understand the issue since the PairSplitter is working correctly for me...
My demo reads the splitter position from the ini file and sets it accordingly. This happens in the OnCreate event of the form where the splitter does not have a handle yet. Therefore the setter writes the ini value to FPosition only but cannot apply it to the widths of the sides, yet. Later, when handles are created, the splitter's CreateWnd is called which finally sets the widths of the sides.
Instead of using the Position property you can also write directly to the Sides[0].Width property of the TPairSplitterSide. This way the FPosition property is bypassed, and there is a discrepancy between the real width of the left splitter and the FPosition value internally. But this is irrelevant because you can detect this only by reading the Position property which calls UpdatePosition and brings them back into agreement.
Note that setting Sides[1].Width does not call UpdatePosition which might be considered a bug. At least the user should know...
If you look at the setter you will see that nothing happens if the parameter is the same as the current value of FPosition:
procedure TCustomPairSplitter.SetPosition(const AValue: integer);
begin
if FPosition = AValue then
Exit;
...
So a manual adjustment of position followed by a change of position under program control will do noting if the manual change didn't update FPosition
This is standard behaviour of most property setters: when the new property value already is identical to the old value there's nothing else to be done.