I like to read code and decide what the problems with it are, then run the code to see if I was right.
The code in #12 is harder to use than necessary. While the shifting bits deglitcher / debouncer is clever, it may be more suited to other tasks than watching a button.
Normally open pushbuttons do not show themselves as closed unless they are on to the way to being closed, or or are already closed and stable.
Nor do normally open pushbuttons show themselves as open unless they are on the way to being open, or are already open and stable.
If you have pushbuttons that do either, throw them out. 
Usually, what is of first interest for watching a button is "did it get pressed". While the shift register technique provides it, it does so only for a very brief period.
Many button libraries offer an indication of a button event. If the library worked, that is the purpose of the wasPressed() method:
if (buttons[i].wasPressed() )
Again, if it worked, this would be true once for each button going down event. As there is no service call equivalent to
buttonTask();
we infer that the event will sit around and wait until we ask about it.
In libraries that do use a loop service call, the choice of the designer is to implement a persistent flag that sits and waits for the user to check, no matter the service call is made any number of times, or to implement a "use it or lose it" philosophy that means one must check for the event after one service call and before the next. In most libraries, it does not matter how frequently one calls the service method, just that it be called before any new information can be expected.
"use it or lose it" fits perfectly with the IPO model for programming. Once per loop we service the button(s), and in that loop see and dispose of any events that turned up.
The code in #12 does not allow event detection if you are not right there in the small window of time it exists in the "picture". It's beyond "use it or lose it" in the sense that the event will not wait to be used.
Anything that doesn't come around in waitButtonTime time (500; // micros) will miss it.
The technique as presented needs way too much inside knowledge of its operation and limits. Practically speaking, it would usually need state change detection to be implemented in the higher level code.
If what you want is to do something when a button becomes pressed, you need to debounce and detect the state change. Most libraries allow this to be placed in higher level code with next to no idea of how they work (or don't, too often).
The shift register can't be shifted too fast, and can't be looked at too slowly.
Running hand-made state detection alongside the "picture" recognition of press and release at 250 Hz yields
switch is one way
switch is the other way
switch is one way
switch is the other way
release detected 20044
switch is one way
switch is the other way
switch is one way
switch is the other way
switch is one way
switch is the other way
release detected 21192
switch is one way
switch is the other way
press detected 21444
switch is one way
State of the button is fine, detecting presses and releases a matter of probability.
a7