$watch watches changes on the $scope. Since your input is not bound to the same $scope property that is being watched, your watch listener is only called once, on initialization.
To give a little better idea of how $watches, binding and $scope works, here is what your scope looks like (actually, your scope is empty, because you haven't written anything into it, but this is what it WOULD look like based on your template):
{
shizzle: { // <--- This is the property you're watching
$valid: false,
whatev: {
valid: false
}
},
whatev: "" // <--- This is the object that is changing when you type into the <input>
}
As you can see, shizzle is being watched, but doesn't change, so the watch listener is only fired once.
Here is an edited version of your plunker that binds the watcher to the input's model, and logs all changes, for demonstration:
http://plnkr.co/edit/NrE5blIbyBcsOjC2vIrk?p=preview
EDIT: If your goal is to watch the $valid attribute, which angular is setting, then you can change this line:
scope.$watch(attrs.name, function(newVal, oldVal) {
console.log(newVal);
}, true);
to this:
scope.$watch("shizzle.$valid", function(newVal, oldVal) {
console.log(newVal);
}, true);