Indeed, I can reproduce this on any filesystem with:
mkdir /tmp/test
cd /tmp/test
# create 2 directories
mkdir dir1 dir2
# create a dummy file
touch dir1/file
# create hard link to file in second directory
ln dir1/file dir2/file
# watch first directory
inotifywait -m dir1 &
# modify file from second directory
echo test >> dir2/file
# no event is generated...
More or less: You did not do the distinction between actual syncthing code and notify code. The latter is a separate library, that we maintain a fork for which is identical with the original https://github.com/rjeczalik/notify except for a few modifications we need. The notify library does send events without blocking, i.e. drops them - that’s a design choice. That’s why we use a buffered channel, so this never happens, unless this channel is full, which we detect (as you found out correctly). So that part is fine.
Inotify overflow events: Looks they are dropped, maybe that could be fixed. It’s in the notify library too, so you’d have to ask there, but I guess it’s not an issue because they send events without blocking, i.e. fast, so overflow shouldn’t be an issue. Just thinking out load here, I don’t know how inotify actually works.
At least in theory it should be possible that the kernel pushes lots of events in the inotify queue, but the user space Syncthing process does not get scheduled often enough to consume the events (because the CPU is overloaded or because the process priority is very low) until the queue is full.