The solution is to bind the two name tests together with parens.
To illustrate this, let's consider a directory with three regular files:
$ ls -a
. .. .hidden1 .hidden2 not_hidden
Now, let's the original command:
$ find . -name ".*" -o -name "*" -exec echo Found {} \;
Found ./not_hidden
Only the non-hidden file is found.
Next, let's add parens to group the two name tests together:
$ find . \( -name ".*" -o -name "*" \) -exec echo Found {} \;
Found .
Found ./not_hidden
Found ./.hidden1
Found ./.hidden2
All files are found.
The solution is to use parens.
More details
In the original command, there is not operator between -name "*" and -exec ... \;. Consequently, find assumes the default operator which is logical-and. Because logical-and binds tighter than logical-or (-o), this means that the command is interpreted as:
find . \( -name ".*" \) -o \( -name "*" -exec echo Found {} \; \)
This means that the exec is run only if the first name condition failed to match.
For more information, see the OPERATORS section in man find.
What happens without -exec
Let's try using a simple -print:
$ find . -name ".*" -o -name "*" -print
./not_hidden
As you can see, -print bound to the -name "*" with the implicit logical-and as above.
But, consider what happens without any action specified:
$ find . -name ".*" -o -name "*"
.
./not_hidden
./.hidden1
./.hidden2
Here, all files were found. The reason is that, in this version, -o is the only operator.