So it looks like I went down a rabbit hole with the previous post that didn't help me much. Looks like that has to do with spring loaded and it is not the only trigger for the onchange stuff to occur.
It looks like the culprit for onChange not firing has to do with GrailsApp.enableDevelopmentModeWatch. I'm not sure why, but the logic in the loop will only fire off the onchange event if the changed file is also a new file. From the Grails 3.1.4 source, see line 222. I'd have guessed this logic was reversed, but if the changed file is also a new file, there's a line that removes that file from the new files list, and then it submits the file change event.
Whatever the reason for this, the end result is that my plugin's onChange method is not being trigger for a file that is being watched. I've confirmed through debugging that the watched files list is being loaded correctly, and I'm not sure where to go from here. If my understanding of the above is wrong, my apologies. If this sounds like a bug, I'd be happy to submit a JIRA.
Also, I'd really like to understand how a changed file can also be a new file, and why onChange will only fire if both are true.
Thanks for any help.