Browse Source

G-082 increment 1: activate goal; characterize 0.12.x optional-rejection overflow errors

Set G-082 active (user-directed). New errorselection.test pins current
single-form error selection before the fix:

- _GAP pins: an optional choice-restricted leader (make.tcl dispatch shape),
  an optional choice-restricted value, and an optional typed (int) value each
  reject a word that then overflows - all report generic
  {toomanyarguments N index I} with no -badarg/-badval attribution,
  discarding the specific rejection (regression vs punk::args 0.5.0)
- reference pins: the -optional 0 equivalents report pointed choiceviolation
  with -badarg/-badval and Leading/Trailing argument messages
- guards: genuine surplus stays toomanyarguments; a rejected word consumed by
  a later slot parses cleanly; multiform failures still route through
  rank_form_failures (noformmatch)

Verified: 7/7 pass against the unfixed module under Tcl 9.0.3.

Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
Julian Noble 17 hours ago
parent
commit
0032478e46
  1. 2
      GOALS.md
  2. 2
      goals/G-082-punkargs-error-selection.md
  3. 178
      src/tests/modules/punk/args/testsuites/args/errorselection.test

2
GOALS.md

@ -310,7 +310,7 @@ Detail: goals/G-080-ansi2html-cellgrid-mode.md
Scope: src/modules/punk/mix/commandset/doc-999999.0a1.0.tm (doc.* commandset - new generation subcommands), src/scriptapps/tools/punkargs_to_doctools.tcl + punkargs_punknative.tcl (prototypes to productize), src/scriptapps/tools/fontprep/ (shared doc-set asset in link mode), src/doc tree conventions, src/tests coverage
Detail: goals/G-081-argdoc-build-pipeline.md
### G-082 [proposed] punk::args single-form parse error selection: specific validation failures preferred over generic overflow
### G-082 [active] punk::args single-form parse error selection: specific validation failures preferred over generic overflow
Scope: src/modules/punk/args-999999.0a1.0.tm (get_dict/parse error selection, validation-failure capture around the choice/type screens), src/tests/modules/punk/args/testsuites/args/ (characterization + regression suite)
Detail: goals/G-082-punkargs-error-selection.md

2
goals/G-082-punkargs-error-selection.md

@ -1,6 +1,6 @@
# G-082 punk::args single-form parse error selection: specific validation failures preferred over generic overflow
Status: proposed
Status: active
Scope: src/modules/punk/args-999999.0a1.0.tm (get_dict/parse error selection, validation-failure capture around the choice/type screens), src/tests/modules/punk/args/testsuites/args/ (characterization + regression suite)
Goal: when a single-form parse fails because a word was rejected by an optional argument's validation (restricted choices, type) and consequently overflowed the argument list, the reported error names the specific rejection (the choiceviolation with the offending word and choice list, or the type failure) instead of the generic "Received more values than can be assigned" overflow - restoring the pointedness punk::args 0.5.0-era parsing had for optional choice-restricted leaders/values, and removing the need for the -optional 0 authoring workaround adopted by make.tcl's dispatch definitions.
Acceptance: a definition with an optional choice-restricted leader or value that receives a non-matching word reports a choiceviolation-class error naming the word and the allowed choices (message and -errorcode), not toomanyarguments - pinned for the make.tcl-style dispatch shape (optional subcommand leader with choices) and a values-position equivalent; a word rejected by a typed optional argument (e.g int) that then overflows reports the type failure similarly; genuinely-surplus cases (all optional args satisfied, extra word remains) still report toomanyarguments; multiform error selection (rank_form_failures) is unchanged or its pins deliberately updated; current 0.12.x behaviour is characterized first and the pins flipped deliberately; full punk::args suite passes with no expectations weakened; on completion the G-030 -optional 0 workaround sites are revisited (make.tcl dispatch definitions, the src/modules/AGENTS.md "punk::args definition authoring ergonomics" bullet) and relaxed or re-documented.

178
src/tests/modules/punk/args/testsuites/args/errorselection.test

@ -0,0 +1,178 @@
package require tcltest
#added 2026-07-14 (agent, G-082) - single-form parse error selection.
#Characterizes the error reported when a word rejected by an OPTIONAL argument's
#allocation screen (restricted choices, basic type) subsequently overflows the
#argument list. Current 0.12.x behaviour: the specific rejection is discarded and a
#generic toomanyarguments overflow is reported (regression vs punk::args 0.5.0 -
#see goals/G-082-punkargs-error-selection.md). The _GAP pins here encode that
#current behaviour and are to be flipped deliberately by the G-082 fix.
namespace eval ::testspace {
namespace import ::tcltest::*
variable common {
set result ""
}
#slim an errorcode: classification triple plus -badarg/-badval extras (drop -argspecs)
proc ecinfo {opts} {
set ec [dict get $opts -errorcode]
set extras [dict create]
foreach {k v} [lrange $ec 3 end] {
if {$k eq "-argspecs"} {break}
dict set extras $k $v
}
return [list [lrange $ec 0 2] $extras]
}
test errsel_leader_optional_choice_reject_GAP {GAP: optional choice-restricted leader rejecting a word reports generic overflow (make.tcl dispatch shape)}\
-setup $common -body {
set docid ::testspace::errsel_leader_optional_choice
set docids [list $docid]
punk::args::define [list @id -id $docid] {@leaders -min 0 -max 1} {subcommand -type string -optional 1 -choices {build test help}}
set err [catch {punk::args::parse {frobnicate} withid $docid} msg opts]
lappend result $err {*}[ecinfo $opts]
}\
-cleanup {
foreach id $docids {
punk::args::undefine $id 1
}
}\
-result [list\
1 {PUNKARGS VALIDATION {toomanyarguments 1 index 0}} {}
]
test errsel_value_optional_choice_reject_GAP {GAP: optional choice-restricted value rejecting a word reports generic overflow}\
-setup $common -body {
set docid ::testspace::errsel_value_optional_choice
set docids [list $docid]
punk::args::define [list @id -id $docid] @values {subject -type string -optional 1 -choices {build test help}}
set err [catch {punk::args::parse {frobnicate} withid $docid} msg opts]
lappend result $err {*}[ecinfo $opts]
}\
-cleanup {
foreach id $docids {
punk::args::undefine $id 1
}
}\
-result [list\
1 {PUNKARGS VALIDATION {toomanyarguments 1 index 0}} {}
]
test errsel_value_optional_type_reject_GAP {GAP: optional typed (int) value rejecting a word reports generic overflow}\
-setup $common -body {
set docid ::testspace::errsel_value_optional_type
set docids [list $docid]
punk::args::define [list @id -id $docid] @values {num -type integer -optional 1}
set err [catch {punk::args::parse {notanumber} withid $docid} msg opts]
lappend result $err {*}[ecinfo $opts]
}\
-cleanup {
foreach id $docids {
punk::args::undefine $id 1
}
}\
-result [list\
1 {PUNKARGS VALIDATION {toomanyarguments 1 index 0}} {}
]
test errsel_required_choice_reference {Reference: required choice-restricted args report pointed choiceviolation (leader and value)}\
-setup $common -body {
set docid1 ::testspace::errsel_required_leader
set docid2 ::testspace::errsel_required_value
set docids [list $docid1 $docid2]
punk::args::define [list @id -id $docid1] {@leaders -min 0 -max 1} {subcommand -type string -optional 0 -choices {build test help}}
punk::args::define [list @id -id $docid2] @values {subject -type string -optional 0 -choices {build test help}}
set err [catch {punk::args::parse {frobnicate} withid $docid1} msg opts]
lappend result $err {*}[ecinfo $opts]
lappend result [string match "Leading argument 'subcommand' for*must be one of the listed values:*Received: 'frobnicate'*" $msg]
set err [catch {punk::args::parse {frobnicate} withid $docid2} msg opts]
lappend result $err {*}[ecinfo $opts]
lappend result [string match "Trailing argument 'subject' for*must be one of the listed values:*Received: 'frobnicate'*" $msg]
}\
-cleanup {
foreach id $docids {
punk::args::undefine $id 1
}
}\
-result [list\
1 {PUNKARGS VALIDATION {choiceviolation frobnicate choices {build test help}}} {-badarg subcommand -badval frobnicate} 1\
1 {PUNKARGS VALIDATION {choiceviolation frobnicate choices {build test help}}} {-badarg subject -badval frobnicate} 1
]
test errsel_genuine_surplus {Genuinely-surplus words still report toomanyarguments (all optionals satisfied or none defined)}\
-setup $common -body {
set docid1 ::testspace::errsel_surplus_after_choice
set docid2 ::testspace::errsel_surplus_no_names
set docids [list $docid1 $docid2]
punk::args::define [list @id -id $docid1] @values {subject -type string -optional 1 -choices {build test help}}
punk::args::define [list @id -id $docid2] @values
#subject satisfied by 'build' - 'extra' is genuinely surplus
set err [catch {punk::args::parse {build extra} withid $docid1} msg opts]
lappend result $err {*}[ecinfo $opts]
#no value names defined at all
set err [catch {punk::args::parse {extra} withid $docid2} msg opts]
lappend result $err {*}[ecinfo $opts]
}\
-cleanup {
foreach id $docids {
punk::args::undefine $id 1
}
}\
-result [list\
1 {PUNKARGS VALIDATION {toomanyarguments 2 index 1}} {}\
1 {PUNKARGS VALIDATION {toomanyarguments 1 index 0}} {}
]
test errsel_rejected_word_lands_later {A word rejected by an optional choice arg but consumed by a later slot parses cleanly}\
-setup $common -body {
set docid ::testspace::errsel_word_lands_later
set docids [list $docid]
punk::args::define [list @id -id $docid] @values {subject -type string -optional 1 -choices {build test help}} {other -type string -optional 1}
set argd [punk::args::parse {frobnicate} withid $docid]
lappend result [dict get $argd values]
}\
-cleanup {
foreach id $docids {
punk::args::undefine $id 1
}
}\
-result [list\
{other frobnicate}
]
test errsel_multiform_selection {Multiform failures still route through rank_form_failures (noformmatch)}\
-setup $common -body {
set docid ::testspace::errsel_multiform
set docids [list $docid]
punk::args::define [list @id -id $docid] {@form -form {A B}} {@leaders -form A -min 0 -max 1} {subcommand -form A -type string -optional 1 -choices {build test help}} {@values -form B -min 1 -max 1} {num -form B -type int}
set err [catch {punk::args::parse {frobnicate} withid $docid} msg opts]
set ec [dict get $opts -errorcode]
lappend result $err [lrange $ec 0 1] [lindex $ec 2 0]
}\
-cleanup {
foreach id $docids {
punk::args::undefine $id 1
}
}\
-result [list\
1 {PUNKARGS VALIDATION} noformmatch
]
}
tcltest::cleanupTests ;#needed to produce test summary line.
Loading…
Cancel
Save