punk/ns tests: 8.6/8.7 leg conditioning (feature probes + divergence pins)
The six 8.6/8.7 failures in nslist.test/nsprimitives.test were
never-green pins (authored 2026-07-14/19, before native-8.6 runner
support existed), not regressions. Three causes, conditioned without
module changes since both module behaviours are documented intent:
- 'info vars' in a namespace context includes globals on pre-TIP-278
cores: nseval_ifexists_weird pattern-narrowed to 'info vars m*'.
- nstree_raw weird-children recursion: the composed :🅰️::odd string
form is unresolvable as a fresh string on ALL cores (probed
8.6.18/8.7a6/9.0.5); the 9 leg passes only because 'namespace
children' values carry a resolved internal rep that survives the
recursion. New capability probe weirdns_children_recursable gates the
literal-listing pin, with a portable plain-tree test and an
inverse-gated recursion-failure pin.
- get_ns_dicts classification needs ::tcl::info::cmdtype (8.7+): the
8.6 fallback deliberately returns na for renamed aliases, coroutines
and native builtins. have_infocmdtype gates the four dependent tests
(cor tag split out so the other five tag pins keep the 8.6 render
path covered) and nslist_classification_no_cmdtype_fallback pins the
divergence.
Verified green: 8.6/8.7/9.0 x -jobs/singleproc, ns subtree 131 total
0 fail (8.6: 5 skip, 8.7/9.0: 2 skip, all by constraint design);
testbody_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
#Tier A ------------------------------------------------------------------
#Tier A ------------------------------------------------------------------
test nslist_classification_buckets {get_ns_dicts classifies each element into its bucket (machine contract for display reworks)}\
test nslist_classification_buckets {get_ns_dicts classifies each element into its bucket (machine contract for display reworks)}\
-constraints have_infocmdtype\
-setup $fsetup -body {
-setup $fsetup -body {
set d [lindex [punk::ns::get_ns_dicts ::navfix::*] 0]
set d [lindex [punk::ns::get_ns_dicts ::navfix::*] 0]
lappend result [dict get $d location]
lappend result [dict get $d location]
@ -161,6 +170,7 @@ namespace eval ::testspace {
]
]
test nslist_classification_alias_edge_cases {alias overwritten by same-name proc classifies as proc only; alias renamed in-namespace stays a plain als entry}\
test nslist_classification_alias_edge_cases {alias overwritten by same-name proc classifies as proc only; alias renamed in-namespace stays a plain als entry}\
-constraints have_infocmdtype\
-setup $fsetup -body {
-setup $fsetup -body {
set d [lindex [punk::ns::get_ns_dicts ::navfix::*] 0]
set d [lindex [punk::ns::get_ns_dicts ::navfix::*] 0]
#maskme: alias registration invisible once a proc took the name
#maskme: alias registration invisible once a proc took the name
@ -214,6 +224,7 @@ namespace eval ::testspace {
]
]
test nslist_classification_native_builtin_ns {native bucket populates for a builtin namespace (fixture cannot contain native commands)}\
test nslist_classification_native_builtin_ns {native bucket populates for a builtin namespace (fixture cannot contain native commands)}\
-constraints have_infocmdtype\
-setup {
-setup {
set result ""
set result ""
}\
}\
@ -226,6 +237,30 @@ namespace eval ::testspace {
1
1
]
]
#added 2026-08-09 (agent) - the pre-8.7 no-cmdtype fallback's documented divergence
#(see the have_infocmdtype constraint note): what cmdtype cannot prove classifies na -
#present in commands, absent from the specific buckets. Also retains 8.6-leg coverage
#of the maskme pin from the gated alias_edge_cases test (that part is not cmdtype
#dependent). Flip these pins if an 8.6-capable detection ever lands.
test nslist_classification_no_cmdtype_fallback {without info cmdtype (pre-8.7): renamed alias, coroutine and native commands stay unbucketed but remain in commands; proc-masked alias still classifies as proc only}\
-constraints !have_infocmdtype\
-setup $fsetup -body {
set d [lindex [punk::ns::get_ns_dicts ::navfix::*] 0]
lappend result [expr {"nowalias" in [dict get $d commands]}]
lappend result [expr {"nowalias" in [dict get $d aliases]}]
lappend result [expr {"coro" in [dict get $d commands]}]
lappend result [expr {"coro" in [dict get $d coroutines]}]
lappend result [expr {"maskme" in [dict get $d procs]}]
lappend result [expr {"maskme" in [dict get $d aliases]}]
set d2 [lindex [punk::ns::get_ns_dicts ::tcl::mathop::*] 0]
lappend result [expr {"+" in [dict get $d2 commands]}]
lappend result [expr {"+" in [dict get $d2 native]}]
}\
-cleanup $fcleanup\
-result [list\
1 0 1 0 1 0 1 0
]
#Tier B ------------------------------------------------------------------
#Tier B ------------------------------------------------------------------
#Marking semantics located per element - layout agnostic. SGR fragments are
#Marking semantics located per element - layout agnostic. SGR fragments are
@ -252,6 +287,8 @@ namespace eval ::testspace {
1 1 1 1 0
1 1 1 1 0
]
]
#2026-08-09 Agent-Updated: cor moved to nslist_marking_coroutine_tag - coroutine
#classification needs info cmdtype (8.7+), the remaining tags render on all cores
test nslist_marking_command_type_tags {each command type renders its tag with its designated colour}\
test nslist_marking_command_type_tags {each command type renders its tag with its designated colour}\
-setup $fsetup -body {
-setup $fsetup -body {
set raw [punk::ns::nslist -types all ::navfix::*]
set raw [punk::ns::nslist -types all ::navfix::*]
@ -260,11 +297,24 @@ namespace eval ::testspace {
lappend result [rawhas $raw "[punk::ansi::a+ bold purple]als"]
lappend result [rawhas $raw "[punk::ansi::a+ bold purple]als"]
lappend result [rawhas $raw "[punk::ansi::a+ term-aqua]ooc"]
lappend result [rawhas $raw "[punk::ansi::a+ term-aqua]ooc"]
lappend result [rawhas $raw "[punk::ansi::a+ bold cyan]ooo"]
lappend result [rawhas $raw "[punk::ansi::a+ bold cyan]ooo"]
}\
-cleanup $fcleanup\
-result [list\
1 1 1 1 1
]
#added 2026-08-09 (agent) - split from nslist_marking_command_type_tags: the cor tag
#requires coroutine classification, which needs info cmdtype (see the have_infocmdtype
#constraint note)
test nslist_marking_coroutine_tag {coroutine commands render the cor tag with its designated colour (cmdtype-dependent)}\
-constraints have_infocmdtype\
-setup $fsetup -body {
set raw [punk::ns::nslist -types all ::navfix::*]
lappend result [rawhas $raw "[punk::ansi::a+ term-hotpink]cor"]
lappend result [rawhas $raw "[punk::ansi::a+ term-hotpink]cor"]
}\
}\
-cleanup $fcleanup\
-cleanup $fcleanup\
-result [list\
-result [list\
1 1 1 1 1 1
1
]
]
test nslist_marking_exported_imported {exported commands colour green-bold; imported commands carry the -I marker}\
test nslist_marking_exported_imported {exported commands colour green-bold; imported commands carry the -I marker}\
#added 2026-07-14 (agent) - characterization pins for the punk::ns name/path string primitives and eval variants, coverage precondition for the punk::ns hygiene pass
#added 2026-07-14 (agent) - characterization pins for the punk::ns name/path string primitives and eval variants, coverage precondition for the punk::ns hygiene pass
#The primitive region of punk::ns contained variant/deprecated twins (nsparts1, nsprefix1, nsprefix_orig, nstail1, nstail_orig).
#The primitive region of punk::ns contained variant/deprecated twins (nsparts1, nsprefix1, nsprefix_orig, nstail1, nstail_orig).
#This file originally also pinned their divergence from the live primitives (they collapsed long colon runs differently);
#This file originally also pinned their divergence from the live primitives (they collapsed long colon runs differently);
@ -225,7 +240,10 @@ namespace eval ::testspace {
lappend result [namespace children ::punknstest_w]
lappend result [namespace children ::punknstest_w]
lappend result [punk::ns::nschildren ::punknstest_w]
lappend result [punk::ns::nschildren ::punknstest_w]
lappend result [punk::ns::nseval_ifexists ::punknstest_w:::odd {set marker}]
lappend result [punk::ns::nseval_ifexists ::punknstest_w:::odd {set marker}]
lappend result [punk::ns::nseval_ifexists ::punknstest_w:::odd {info vars}]
#2026-08-09 Agent-Updated: pattern-narrowed from bare 'info vars' - pre-TIP-278
#cores (8.6/8.7) include global variables in a namespace context's 'info vars',
#so the bare form is not portable; m* still pins that the script ran in the weird ns
lappend result [punk::ns::nseval_ifexists ::punknstest_w:::odd {info vars m*}]
lappend result [catch {punk::ns::nseval_ifexists ::punknstest_w:::odd {error boom}} emsg] $emsg
lappend result [catch {punk::ns::nseval_ifexists ::punknstest_w:::odd {error boom}} emsg] $emsg
lappend result [punk::ns::nseval_ifexists ::punknstest_w:::nope {set marker}]
lappend result [punk::ns::nseval_ifexists ::punknstest_w:::nope {set marker}]
lappend result [namespace eval ::punknstest_w {namespace exists {:nope}}] ;# 0 - not created
lappend result [namespace eval ::punknstest_w {namespace exists {:nope}}] ;# 0 - not created
@ -286,7 +304,14 @@ namespace eval ::testspace {
::punknstest_c::a::g
::punknstest_c::a::g
]
]
#2026-08-09 Agent-Updated: gated to cores where nstree_rawlist's recursion survives
#weird children (see the weirdns_children_recursable probe above - Tcl 9 today, via
#internal-rep survival; 8.6/8.7 die re-parsing the composed name). nstree_raw is
test nstree_raw_weird_children_norecurse {nstree_raw recursion dies on a weird child where the core re-parses the composed name form (documented raw/no-weird-consideration contract; 8.6/8.7 today)}\
-constraints !weirdns_children_recursable\
-setup {
set result ""
namespace eval ::punknstest_t {
namespace eval sub {}
namespace eval {:odd} {}
}
}\
-body {
lappend result [catch {punk::ns::nstree_raw ::punknstest_t} emsg]
lappend result $emsg
}\
-cleanup {
catch {namespace delete ::punknstest_t}
}\
-result [list\
1 {namespace "::punknstest_t:::odd" not found}
]
test globmatchns_pins {globmatchns - * matches within a level (including a single inner colon) but not across ::, ** crosses levels, ? matches one non-colon char}\
test globmatchns_pins {globmatchns - * matches within a level (including a single inner colon) but not across ::, ** crosses levels, ? matches one non-colon char}\
-setup $common -body {
-setup $common -body {
lappend result [punk::ns::globmatchns ::a::* ::a::b]
lappend result [punk::ns::globmatchns ::a::* ::a::b]