The script below exercises two different inexplicable issues:

1. (Cases A1+B1 below)
   The variable x is unset, the trace callback redefines x, but x does not
   become visible. Only if the callback command is called another time
   (directly), the namespace variable becomes visible again.

2. (Case A2)
   The namespace variable (with the same initial visibility as case A1) is
   unset but this does not trigger the callback command.

--

namespace eval ::child {
    variable x
    proc callback {args} {
	if {[llength $args] > 0} {
	    puts "Callback triggered by unset trace"
	} else {
	    puts "Callback invoked directly (not as a trace callback)"
	}
	variable x; # restore namespace variable
    }
    trace add variable x unset [list ::child::callback]
}

# Experiment with different invocations of the callback proc

# Case 0: Initial visibility of the namespace variable
puts "O. Initial situation\n|[namespace inscope ::child [list info vars x]]|"

# Case A1. let "unset" trigger the callback
puts -nonewline "\nA1. "
namespace inscope ::child {unset -nocomplain x}
puts "|[namespace inscope ::child [list info vars x]]|"

# Case B1. invoke "callback" directly, i.e. not as a callback command
puts -nonewline "\nB1. "
::child::callback
puts "|[namespace inscope ::child [list info vars x]]|"

# Repeat A. and B. and see the different results

# Case A2: should trigger the callback as in A1, but it doesn't
puts -nonewline "\nA2. "
namespace inscope ::child {unset -nocomplain x}
puts "|[namespace inscope ::child [list info vars x]]|"

# Case B2: as B1
puts -nonewline "\nB2. "
::child::callback
puts "|[namespace inscope ::child [list info vars x]]|"

--

Results:
-------

O. Initial situation
|x|

A1. Callback triggered by unset trace
||

B1. Callback invoked directly (not as a trace callback)
|x|

A2. ||

B2. Callback invoked directly (not as a trace callback)
|x|

-- end of message --