A criticism on this implementation: The "state" directory is never cleaned; new states are always added. Therefore if you go back to a state (hash) that you had already built in the past, you will not be able to build it again.
And there is no need to create separate shell scripts, when you can have all the relevant code inside your Makefile. Presumably those are not going to be called independently anyway.
As I've written on previous discussions:
Make by default uses the file change timestamp to trigger actions. But this is definitely not the only way, and you can code your Makefile so that rebuilds happen when a file's checksum changes. IIRC, the GNU Make Book has the code ready for you to study... Or, you might get more clever and say "when only a comment is changed, I don't want to rebuild"; file checksums are not the correct solution for this, so you can code another trigger.