My opinion is that toString should return a transactionally correct value, and that there should be an alternate method for the transient snapshot. This makes it so that someone reading the code can see that the string is special. Also, dbgStr and dbgValue return a value even if the enclosing transaction has already been marked for rollback (they return info about the pending rollback), because that is the most useful thing when debugging.
If you want to write your own debugging helpers take a look at TxnExecutor.unrecorded, which does something like running a nested transaction and then rolling it back at the last moment. This way you can get a self-consistent dbgStr or dbgValue even for a data structure built from multiple Ref-s (like TMap).