[Sony Xperia XZ1 Compact Questions & Answers] apexofservice:
[MENTION=4782500]pbarrette[/MENTION], thanks! I tried the naive approach:

d if=twrp-3.2.1-0-lilac-10-patchlevel-2018-05-05.img of=/dev/block/bootdevice/by-name/FOTAKernel <
60128+0 records in
60128+0 records out
30785536 bytes transferred in 2.100 secs (14659779 bytes/sec)
G8441:/data/local/tmp # sync
G8441:/data/local/tmp # sync
G8441:/data/local/tmp # reboot recovery

Alas, it just rebooted back to system. It did seem to take a bit longer, so it's possible that it tried to boot from FOTAKernel and failed then fell back to system. I've just got a new root shell so I can look in startup logs from dmesg to see if there's anything of interest.

Also, I'm probably missing something really obvious. Thanks for any insight!

Reading dmesg now, this seems quite relevant (I recall booting to recovery on my z3 compact by touching a file in /cache/recovery). I'll post it here but I'm still reading the dmesg.

[ 7.406109] bs_roots: recovery filesystem table
[ 7.406120] bs_roots: =========================
[ 7.406125] bs_roots: 0 /data ext4 /dev/block/bootdevice/by-name/userdata
[ 7.406130] bs_roots: 1 /oem ext4 /dev/block/bootdevice/by-name/oem
[ 7.406134] bs_roots: 2 /cache ext4 /dev/block/bootdevice/by-name/cache
[ 7.406139] bs_roots: 3 /rca ext4 /dev/block/bootdevice/by-name/appslog
[ 7.406143] bs_roots: 4 /idd ext4 /dev/block/bootdevice/by-name/diag
[ 7.406148] bs_roots: 5 /storage/sdcard1 vfat /devices/soc/c0a4900.sdhci/mmc_host*
[ 7.406153] bs_roots: 6 none swap /dev/block/zram0
[ 7.406157] bs_roots: 7 /persistent emmc /dev/block/bootdevice/by-name/frp
[ 7.406162] bs_roots: 8 /misc emmc /dev/block/bootdevice/by-name/misc
[ 7.406167] bs_roots: 9 /firmware vfat /dev/block/bootdevice/by-name/modem
[ 7.406172] bs_roots: 10 /bt_firmware vfat /dev/block/bootdevice/by-name/bluetooth
[ 7.406177] bs_roots: 11 /dsp ext4 /dev/block/bootdevice/by-name/dsp
[ 7.406182] bs_roots: 12 /persist ext4 /dev/block/bootdevice/by-name/persist
[ 7.406187] bs_roots: 13 /boot/modem_fs1 emmc /dev/block/bootdevice/by-name/modemst1
[ 7.406191] bs_roots: 14 /boot/modem_fs2 emmc /dev/block/bootdevice/by-name/modemst2
[ 7.406195] bs_roots: 15 auto auto /devices/soc/a800000.ssusb/a800000.dwc3/xhci-hcd.0.auto/usb*
[ 7.406199] bs_roots: 16 /qns ext4 /dev/block/bootdevice/by-name/Qnovo
[ 7.406203] bs_roots: 17 /tmp ramdisk ramdisk
[ 7.406206] bs_roots:
[ 7.408585] MR: Mounting /cache ourselves
[ 7.412318] EXT4-fs (sda53): recovery complete
[ 7.412666] EXT4-fs (sda53): mounted filesystem with ordered data mode. Opts:
[ 7.413213] MR: fopen() failed -/cache/recovery/command (No such file or directory)
[ 7.413219] MR: Unmounting /cache
[ 7.413959] MR: Fail to get command from /cache/recovery/command, trying /misc
[ 7.414272] MR: Unknown wipe command
[ 7.414280] MR: Buffer is empty from /dev/block/bootdevice/by-name/misc with command 0
[ 7.417568] MR: TA_MASTER_RESET value = 0
[ 7.418475] init: Service 'exec 3 (/sbin/mr)' (pid 605) exited with status 0 waiting took 0.022997 se
conds
[ 7.418513] init: starting service 'exec 4 (/sbin/ffu)'...
[ 7.418846] init: SVC_EXEC pid 609 (uid 0 gid 0+0 context u:r:recovery:s0) started; waiting...
[ 7.419833] init: Service 'exec 4 (/sbin/ffu)' (pid 609) exited with status 255 waiting took 0.001316
seconds

------

One more update, I did a sanity check that that dd command is actually overwriting FOTAkernel. It doesn't look like it's working:

G8441:/data/local/tmp # dd if=/dev/block/bootdevice/by-name/FOTAKernel of=FOTAKernel-extracted.img
131072+0 records in
131072+0 records out
67108864 bytes transferred in 0.812 secs (82646384 bytes/sec)
G8441:/data/local/tmp # chown shell:shell FOTAKernel-extracted.img
G8441:/data/local/tmp # dd if=twrp-3.2.1-0-lilac-10-patchlevel-2018-05-05.img of=/dev/block/bootdevice/by-name/FOTAKernel
60128+0 records in
60128+0 records out
30785536 bytes transferred in 2.037 secs (15113174 bytes/sec)
G8441:/data/local/tmp # sync
G8441:/data/local/tmp # sync
=/dev/block/bootdevice/by-name/FOTAKernel of=FOTAKernel-extracted-2.img <
131072+0 records in
131072+0 records out
67108864 bytes transferred in 0.846 secs (79324898 bytes/sec)

And there's no `diff` on the device, so I pulled the files back to a laptop then:

$ diff FOTAKernel-extracted-2.img FOTAKernel-extracted.img
$ diff FOTAKernel-extracted.img twrp-3.2.1-0-lilac-10-patchlevel-2018-05-05.img
Binary files FOTAKernel-extracted.img and twrp-3.2.1-0-lilac-10-patchlevel-2018-05-05.img differ