And the answer was... tell the FFmpeg libx264 video codec to -tune zerolatency.
At the FFmpeg C API this is done with av_dict_set(&codecOptions, "tune", "zerolatency", 0), where codecOptions is the AVDictionary you will then pass as the last parameter to avcodec_open2().
Why? I couldn't tell you. It has taken me nearly a week of trying everything I could try before I found this. With this single option added the hls.js client synchronizes, and re-synchronizes, with the HLS stream every time, under all circumstances. Without it, hls.js will not gain initial sync to a HLS stream if it is started just a few seconds after the stream has begun and, won't regain synchronization if it should lose it.
Note that I did try running hls.js with lowLatency: false but that did not fix the problem.
We live and learn.