In udev rules, the %k, %b, %n variables are nice and all, but you can also use the variables you’re comparing and setting such as ID_FS_TYPE, KERNEL, SUBSYSTEM, PHYSDEVPATH, etc. When you run a command in a udev rule, there’s nothing stopping you from calling a shell and executing a few commands without actually calling a standalone script to do the dirty work. If you write out the array of environment variables from inside an external program, you can get a better understanding of just which part of the device discovery is matching your rule and getting processed.
Udev creates and removes device nodes in /dev, based on events the kernel sends out on device discovery or removal. In other words, Udev is the system that maps hardware devices to files you can interact with in the /dev directory. Udev runs in user space and creates points in /dev when the kernel detects and recognizes new hardware as it’s attached. It’s only been around since 2003/2004. All modern distributions use udev instead of the now depreciated hotplug.
I have a funky PCI card with multiple serial ports on it that loaded fine with the standard serial driver from my standard kernel, until… the revision changed and now instead of using the tried and true 16550 UART, it’s got some sort of super specialized proprietary version of that chip. The manufacturer says it’s 100% backwards compatible with the 16550 / 16550A chips, and theirs just adds some more functionality for industrial processes or something… blah.