Browse Source

punk::ns 0.3.0: restore bare-query failure banner in cmdhelp (project 0.12.12)

Regression report (user, vs older punk executables): "i if" / "i while" /
"i foreach" used to render the error-scheme box with a "Bad number of
trailing values..." message signalling the command cannot be called with
no arguments; recent builds rendered plain info-scheme usage with no
indication, while direct punk::args::parse {} withid ::foreach still
errored.

Root cause: deliberate suppression, not breakage - G-046 item 5 (ns
0.1.4) suppressed the failing advisory parse for the whole
no-supplied-words path because the message then carried internal-looking
attribution ("Bad number of leading values for punk::args::parse
$args_remaining ...", the "i string is" complaint). G-049 (ns 0.2.0,
same day) independently added -caller attribution making bare-query
messages accurate - but the suppression stayed, hiding now-useful
signal.

Fix: reversal rather than rewording (user decision) - both cmdhelp
render sites (alias path and main path) drop the no-supplied-words
special case; a failing advisory parse renders its message and error
scheme uniformly, and dict returns no longer rewrite the scheme to
info. "i if" now leads with "Bad number of trailing values for if. Got
0 values. Expected at least 2"; the original "i string is" case renders
an accurate "Bad number of leading values for string is. Got 0 leaders.
Expected exactly 1" instead of being hidden.

Tests: cmdhelp_leader_required_no_args_plain_usage flipped to
cmdhelp_leader_required_no_args_error_render (message present,
attribution never the internal parse); cmdhelp_return_dict_scheme
expects scheme error for the bare-query failure. punk::ns suite 53/53;
verified live in punk902z src.

Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
Julian Noble 2 days ago
parent
commit
72d50f91df
  1. 4
      CHANGELOG.md
  2. 2
      punkproject.toml
  3. 35
      src/modules/punk/ns-999999.0a1.0.tm
  4. 3
      src/modules/punk/ns-buildversion.txt
  5. 25
      src/tests/modules/punk/ns/testsuites/ns/cmdhelp.test

4
CHANGELOG.md

@ -5,6 +5,10 @@ The latest `## [X.Y.Z]` header must match the `version` field in `punkproject.to
Entries are newest-first; one bullet per notable change. See the root `AGENTS.md`
"Project Versioning" section for the bump policy.
## [0.12.12] - 2026-07-12
- punk::ns 0.3.0: 'i <cmd>' with no argument words again signals when the command cannot be called bare - e.g 'i if' shows "Bad number of trailing values for if. Got 0 values. Expected at least 2" in the error scheme above the usage table (regression vs older builds, reported by the user). The G-046-era suppression of that render existed because the old message carried internal-looking attribution ("for punk::args::parse ..."); the G-049 -caller attribution fixed the message wording, so the suppression was reversed rather than reworded - the original 'i string is' complaint case now renders an accurate "Bad number of leading values for string is ..." instead of being hidden.
## [0.12.11] - 2026-07-12
- G-071 achieved: punk::args 0.9.0 allocation choice screen - optional arguments with restricted choice sets no longer greedily consume non-choice words at allocation time, so noise-word grammars parse correctly with the noise word omitted. 'i lseq 0 10 2' (and the '0 10 by 2' / '1 5 by 0' shapes) now parse and render correctly against the tclcore moduledoc; genuinely invalid arglists report a plain excess-values error instead of blaming an unrelated optional argument. Correction recorded: parse_status already accepted -form before the withid/withdef tail per its documented synopsis - the earlier 'missing -form' finding was an argument-order mistake, now pinned by test.

2
punkproject.toml

@ -1,4 +1,4 @@
[project]
name = "punkshell"
version = "0.12.11"
version = "0.12.12"
license = "BSD-2-Clause"

35
src/modules/punk/ns-999999.0a1.0.tm

@ -5605,15 +5605,14 @@ y" {return quirkykeyscript}
#-caller attributes any failure message to the queried command rather than
#an internal parse call site.
set pstatus [punk::args::parse_status $queryargs -form $opt_form -caller $querycommand withid $rootdoc]
#With NO supplied args a failure only reflects missing required
#leaders/values - nothing to mark and nothing wrong with the user's (absent)
#input, so we show plain usage in the info scheme instead of the
#internal-looking parse error (G-046 item 5).
#A failing advisory parse renders with the error scheme and its
#message even when NO args were supplied - see the matching site in
#the main cmdhelp body for the history (G-046 item 5 suppression
#reversed 2026-07-12 after the G-049 -caller attribution made the
#messages accurate).
if {$opt_return eq "dict"} {
if {$scheme_received} {
dict set pstatus scheme [dict get $opts -scheme]
} elseif {![dict get $pstatus ok] && ![llength $queryargs]} {
dict set pstatus scheme info
}
return [dict create origin $rootorigin docid $rootdoc cmdtype $rootorigintype args_remaining $queryargs parsestatus $pstatus]
}
@ -5623,11 +5622,6 @@ y" {return quirkykeyscript}
dict set nextopts -scheme info
}
set result [punk::args::arg_error "" [punk::args::get_spec $rootdoc] {*}$nextopts -aserror 0 -parsestatus $pstatus]
} elseif {![llength $queryargs]} {
if {!$scheme_received} {
dict set nextopts -scheme info
}
set result [punk::args::arg_error "" [punk::args::get_spec $rootdoc] {*}$nextopts -aserror 0]
} else {
set result [punk::args::arg_error [dict get $pstatus message] [punk::args::get_spec $rootdoc] {*}$nextopts -aserror 0 -parsestatus $pstatus]
}
@ -5712,15 +5706,17 @@ y" {return quirkykeyscript}
#-errorstyle minimal so no usage table is built inside a discarded error and
#dynamically updated ensembles are reflected).
set pstatus [punk::args::parse_status $args_remaining -form $opt_form -caller $caller_display withid $origindoc]
#With NO supplied trailing args a failure only reflects missing required
#leaders/values (e.g 'i string is') - nothing to mark and nothing wrong with the
#user's (absent) input, so we show plain usage in the info scheme instead of the
#internal-looking parse error (G-046 item 5).
#A failing advisory parse renders with the error scheme and its message even
#when NO trailing args were supplied: 'i if' indicating "Bad number of
#trailing values for if. Got 0 values. Expected at least 2" is useful signal
#that the command cannot be called bare. (History: G-046 item 5 suppressed
#this path because the pre-G-049 message was internal-looking - "for
#punk::args::parse $args_remaining" - but the G-049 -caller attribution made
#the messages accurate, so the suppression was reversed 2026-07-12 by user
#direction, restoring the pre-G-046 indication with the improved messages.)
if {$opt_return eq "dict"} {
if {$scheme_received} {
dict set pstatus scheme [dict get $opts -scheme]
} elseif {![dict get $pstatus ok] && ![llength $args_remaining]} {
dict set pstatus scheme info
}
return [dict create origin $origin docid $origindoc cmdtype $origintype args_remaining $args_remaining parsestatus $pstatus]
}
@ -5730,11 +5726,6 @@ y" {return quirkykeyscript}
dict set nextopts -scheme info
}
set result [punk::args::arg_error "" [punk::args::get_spec $origindoc] {*}$nextopts -aserror 0 -parsestatus $pstatus]
} elseif {![llength $args_remaining]} {
if {!$scheme_received} {
dict set nextopts -scheme info
}
set result [punk::args::arg_error "" [punk::args::get_spec $origindoc] {*}$nextopts -aserror 0]
} else {
set result [punk::args::arg_error [dict get $pstatus message] [punk::args::get_spec $origindoc] {*}$nextopts -aserror 0 -parsestatus $pstatus]
}

3
src/modules/punk/ns-buildversion.txt

@ -1,6 +1,7 @@
0.2.0
0.3.0
#First line must be a semantic version number
#all other lines are ignored.
#0.3.0 - reversal of the G-046-item-5 no-supplied-words suppression (user direction 2026-07-12): cmdhelp's advisory parse failing with NO supplied argument words renders the failure message and error scheme again (both the alias path and the main path; dict returns no longer rewrite the scheme to info), so 'i if'/'i while'/'i foreach' once more signal that the command cannot be called bare - e.g "Bad number of trailing values for if. Got 0 values. Expected at least 2". Rationale: the suppression (ns 0.1.4) existed because the pre-G-049 message was internal-looking ("... for punk::args::parse $args_remaining ..."); the G-049 -caller attribution (ns 0.2.0) made bare-query messages accurate - including the original 'i string is' complaint case, which now reads "Bad number of leading values for string is. Got 0 leaders. Expected exactly 1". Tests: cmdhelp_leader_required_no_args_plain_usage flipped to cmdhelp_leader_required_no_args_error_render; cmdhelp_return_dict_scheme expects scheme error for the bare-query failure.
#0.2.0 - G-049: cmdhelp -return dict - machine-parsable return carrying resolution info (origin/docid/cmdtype/args_remaining) plus the parse-status structure of the supplied argument words (punk::args::parse_status shape; empty for undocumented commands); the scheme field reflects an explicit -scheme and the G-046-item-5 no-supplied-words suppression. cmdhelp's advisory parse now runs via punk::args::parse_status on both the alias path and the main path: an explicit -scheme is honoured on the parse-failure render (previously only on success/tableobject - failures returned parse's internally rendered error with the default error scheme), failure renders consume the structure via arg_error -parsestatus (badarg marking now covers type/allocation failures via the structure), and the failure message names the queried command (parse -caller: querycommand + consumed subcommand words) instead of whatever the %caller% frame walk found - at top call depth that was cmdhelp's own raw 'punk::args::parse $args_remaining ...' source text. Tests: cmdhelp.test G-049 GAP pins flipped + cmdhelp_return_dict_* added
#0.1.4 - G-046 item 5: cmdhelp's advisory goodargs parse failing with NO supplied argument words (e.g 'i string is' where the definition requires leaders) now shows plain info-scheme usage instead of the internal-looking "Bad number of leading values for punk::args::parse ..." error output (both the alias path and the main path; error display for supplied-but-invalid words unchanged). The no-supplied-words advisory parse runs with -errorstyle minimal so its failure doesn't render the full usage table inside the discarded error - large argdocs (e.g 'i punk::args::define') render the table once, not twice (verified parity with pre-G-046 timings: ~5.3s first/~4.1s repeat on punk91 src, table construction dominant). Test: cmdhelp.test cmdhelp_leader_required_no_args_plain_usage
#0.1.3 - documentation-only: cmdhelp 'subcommand' argument help rewritten to match actual behaviour (was described as ensemble-subcommands-only; also covers tcl::oo methods and argument words, whose validity drives the info/error scheme and received-argument marking of the usage display)

25
src/tests/modules/punk/ns/testsuites/ns/cmdhelp.test

@ -420,19 +420,22 @@ namespace eval ::testspace {
}\
-result [list 0 incomplete error {}]
test cmdhelp_return_dict_scheme {the dict scheme field reflects an explicit -scheme, and the no-supplied-words suppression (G-046 item 5) reports info}\
test cmdhelp_return_dict_scheme {the dict scheme field reflects an explicit -scheme, and a bare-query failure reports the error scheme}\
-setup $common -body {
set d [punk::ns::cmdhelp -return dict -scheme error ::testspace::helpfix v1 0 1]
lappend result [dict get [dict get $d parsestatus] scheme]
#leader-requiring definition with no argument words - failure reflects only the
#absent input, reported with the info scheme the display path would use
#leader-requiring definition with no argument words - the failing advisory
#parse reports the error scheme like any other failure (the G-046 item 5
#info-scheme suppression was reversed 2026-07-12: the G-049 -caller
#attribution made bare-query failure messages accurate, so 'i <cmd>' on a
#command that cannot be called bare shows that signal again)
set d [punk::ns::cmdhelp -return dict ::testspace::helpstr]
set ps [dict get $d parsestatus]
lappend result [dict get $ps ok] [dict get $ps scheme]
}\
-cleanup {
}\
-result [list error 0 info]
-result [list error 0 error]
#--- GAP pins: pseudo-command cmdtype + space-delimited docid prefixes (G-051) ------------
@ -546,7 +549,14 @@ namespace eval ::testspace {
}\
-result [list {{::testspace::helpfix v1} [-flag] firstval lastval}]
#--- leader-requiring definition, no supplied args (G-046 item 5) --------------------------
#--- leader-requiring definition, no supplied args -----------------------------------------
#History: G-046 item 5 suppressed the failing advisory parse for bare queries
#because the pre-G-049 message was internal-looking ("Bad number of leading values
#for punk::args::parse $args_remaining ..."). The G-049 -caller attribution made
#the messages accurate ("... for <queried command> ..."), so the suppression was
#reversed 2026-07-12 (user direction): a bare 'i <cmd>' on a command that cannot
#be called with no arguments shows the failure message and error scheme again -
#with the message attributed to the queried command, never the internal parse.
namespace eval ::testspace::leaderhelp {}
punk::args::define {
@ -562,16 +572,17 @@ namespace eval ::testspace {
}
proc ::testspace::leaderhelp::classy {zzclass} {return $zzclass}
test cmdhelp_leader_required_no_args_plain_usage {cmdhelp with no argument words for a leader-requiring definition shows plain usage - the advisory goodargs parse failure ('Bad number of leading values for punk::args::parse ...') is suppressed (G-046 item 5, the 'i string is' shape)}\
test cmdhelp_leader_required_no_args_error_render {cmdhelp with no argument words for a leader-requiring definition shows the failure message attributed to the queried command (suppression reversed; was cmdhelp_leader_required_no_args_plain_usage)}\
-setup $common -body {
set out [punk::ansi::ansistrip [punk::ns::cmdhelp -return string ::testspace::leaderhelp::classy]]
lappend result [string match "*Bad number of leading values*" $out]
#attribution is the queried command - never the internal parse call
lappend result [string match "*punk::args::parse*" $out]
lappend result [string match "*zzclass*" $out]
}\
-cleanup {
}\
-result [list 0 0 1]
-result [list 1 0 1]
#--- ensemble autodef with lazily-registered subcommand argdocs ----------------------------
#Integration surface of the defect pinned unit-level in

Loading…
Cancel
Save