Note: This is for a desktop app (yet another bot) so I’m not passing state because there’s no CSRF to worry about and the redirect_uri goes nowhere (404) because I intercept as soon as a redirect to that URL occurs in my app’s dialog.
Fault was at my end in my choice of development tools; namely Electron.
By default Electron spawns new browser windows with some Node.js libraries already loaded in them. When Twitch’s page tries to load jQuery, jQuery helpfully tries to play along by exporting itself as a Node module rather than a global object. Unfortunately a global object is exactly what Twitch’s JS wanted and it fails to load with jQuery is not defined.
This means that the ‘not you?’ link which uses jQuery to act like a form submit rather than a hyperlink behaves like a link and doesn’t submit the right information to Twitch. Twitch in turn handles this with a Hail Mary redirect to the homepage.