Just for the purposes of comparison - my own "bright line between [good and bad]" is "does the commit message just contain 'WIP', or is it actually fully written-out?" - but I can see that "is the work committed or not?" also works. Thanks for explaining!
On some _very_ rare occasions, I might find that, by the time I've gotten the change to a reviewable state, it's actually too large to be meaningfully reviewed in one go, in which case I'll go back and retroactively (re-)implement it reviewable-chunk-by-reviewable-chunk (on a different branch), and get each of them reviewed and merged in turn. But, 99% of the time, I simply:
* use WIP commits as "checkpoints" along the way while implementing
* get to a minimal mergable change
* use `rebase -i` to squash everything into a single, well-written, reviewable commit
* rinse and repeat