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
- new punk::args::parse_status: documented status structure from a parse attempt (overall ok / status valid|invalid|incomplete / scheme / message / errorcode minus -argspecs / failureclass / badarg / form / receivednames + per-argument argstatus with class, status ok|bad|unparsed, received count/positions, value-in-effect incl -default fill); validation failures reported in the structure, not raised
- arg_error -parsestatus: both renderers derive goodarg/badarg row marking and choice value-in-effect highlighting from the structure (transient goodargs/badarg locals replaced; built internally from -badarg/-parsedargs when not supplied)
- per-render scheme colour resolution: documented -scheme choice value 'nocolour' now takes effect and scheme renders no longer mutate the shared arg_error_CLR array (strike-only goodarg leak fixed)
- parse: new -caller option overriding the %caller% frame-walk substitution (included in parse cache key); get_dict missingrequiredvalue/missingrequiredleader now carry -badarg (type/allocation failures get badarg marking, not just choice violations)
- punk::ns::cmdhelp: -return dict {origin docid cmdtype args_remaining parsestatus}; advisory parse via parse_status on both alias and main paths; explicit -scheme honoured on the parse-failure render; failure messages name the queried command instead of leaking the internal parse source line at top call depth
- tests: parsestatus.test new (12); usagemarking.test G-049 GAP pins flipped + -parsestatus parity/badarg render tests (17); cmdhelp.test G-049 GAP pins flipped + cmdhelp_return_dict_* (25); punk/args + punk/ns trees green on Tcl 9.0.3 and 8.7; full source-tree suite baseline unchanged (exec-14.3 only)
- punkshell 0.5.0: CHANGELOG entry; src/tests/modules/AGENTS.md test-index blurbs updated
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Argument resolution no longer tstr-expands display-only content (-help on
@cmd/@examples/argument records, @formdisplay bodies): ${...} there is masked with
inert tokens (spec key DISPLAY_DEFERRED) and expanded at display time via
private::expand_display_fields (hooks in arg_error/eg/resolved_def/@default copyfrom;
separate display cache for non-dynamic defs; @dynamic re-expands per render preserving
provider refresh; reentrancy guard substitutes raw sources when expansion of the same
id re-enters). First parse of heavily documented commands drops accordingly
(punk::ansi::mark_columns first call ~4.3s -> ~12ms; tclcore ::lseq resolve
~184ms -> ~2ms) and -help content that calls punk::args-parsing commands - including
against its own definition id - resolves cleanly instead of stalling or looping.
-choicelabels stays eager (punk::ns reads it from parse specs in the subcommand walk).
Record splitter factored to private::split_definition_records.
Also per G-046 acceptance:
- @dynamic multiline -help substitutions align at the insertion column
(rendering_atdynamic_multiline_help_insertion GAP flipped)
- prefix/alias choice normalization keeps single-element-clause values plain-string
({\Deleted} list-wrap shape bug; choicegroups_imap_prefix_shape GAP flipped)
- -return string renderer aligns cmd-help continuations under the Description: label
(characterization updated) and its Example: line shows the example, not the doc url
- punk::ns cmdhelp shows plain info-scheme usage when no argument words are supplied
for a leader/value-requiring definition ('i string is', 'i punk::args::define') -
advisory parse runs -errorstyle minimal so the discarded error no longer renders a
second usage table (timing parity with pre-change: ~5.3s/4.1s on punk91 src)
Tests: deferredhelp.test (new); suites green on tcl903 + tcl87; full source-tree run
baseline-clean (exec-14.3 only). GOALS.md: G-046 -> achieved 2026-07-10 (activated
this session at user direction); design + verification evidence in the detail file.
Project 0.4.15.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- punk::args level (usagemarking.test, 14 tests): pins -parsedargs/-badarg/-scheme
marking primitives, goodchoice highlighting of selected and default-in-effect
choice words, and scheme border selection - asserted by SGR-parameter subset
against the live colour arrays. GAP pins for the documented -scheme choice
'nocolour' falling through to 'na' (renders with the previous scheme's leftover
colours) and the dash-spelling '-nocolour' leaking strike-only goodarg into the
shared colour array (G-049 candidates).
- punk::ns level (cmdhelp.test, 19 tests): pins scheme selection (error scheme on
failed parse of supplied args, info scheme + goodarg marking on success), badarg
marking via choiceviolation, the early alias-resolution branch, -return string
parity, goodchoice highlighting through cmdhelp, and the cmdinfo result shape.
GAP pins: pseudo-command cmdtype 'notfound' despite resolved docid + space-form
docid exact-word-only jump (G-051; real 'string is true'/'is tr' pins behind the
have_tclcoredocs constraint), TclOO undocumented-method class-summary fallback
with info-scheme parse of bogus args (G-052), synopsis marking absence and
curried-alias braced-target substitution (G-050), explicit -scheme ignored on
the parse-failure path and caller-attribution leaking cmdhelp's internal parse
source line at top-level call depth (G-049).
- punk::ns 0.1.3 (doc-only): cmdhelp 'subcommand' argument help rewritten - was
described as ensemble-subcommands-only; now covers tcl::oo methods and argument
words, and documents the info/error scheme display driven by argument validity.
- Verified: full punk::args + punk::ns suites green on Tcl 9.0.3 and 8.7.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Activated and completed under user direction (2026-07-08). Aliases for choice
values are now first-class: accepted at parse, normalized to their canonical
choice in results, folded into the canonical entry in usage display, and
resolved identically by the punk::ns doc-lookup walk.
- punk::args 0.3.0:
* -choicealiases {alias canonical ...} on argument lines; dict shape
validated in the option switch, alias->existing-choice and no-collision
cross-validated after spec merge (surfaces at resolve time - define is
lazy)
* the choice-word matching chain extracted from get_dict into the shared
resolver punk::args::choiceword_match {word nocase allchoices
choicealiases choiceprefix denylist reservelist} -> {matched exact
canonical}; get_dict delegates to it (writeback/lset logic stays at the
call site) - one implementation for parser and doc walk
* exact aliases match under any -choiceprefix/-nocase setting; alias names
join the prefix-calculation pool when -choiceprefix is true; deny applies
to the matched NAME (denied alias requires the full alias; a canonical
reached via its alias is exempt from the canonical's own deny entry)
* display: aliases fold into the canonical entry as an '(alias: x)' /
'(aliases: x|y)' label note (single convergence point covers all render
paths); alias names join the display prefix calculation so highlighted
minimal prefixes stay truthful
* define doc gains the -choicealiases section
- punk::ns 0.1.2: cmd_traverse resolves subcommand words via choiceword_match
- -choiceprefixdenylist/-choiceprefixreservelist now honoured in doc lookup
(the two pinned parity GAP tests flipped to agreement), aliases normalize
before choiceinfo lookup, -nocase honoured in the walk
- punk 0.2.3: punk::help adopts the feature - 'i help' lists one entry per
registered topic (topics+help, tcl, env+environment, console+term|terminal);
topic words accept aliases and unique prefixes with the user-decided
minimum-prefix policy recorded in ::punk::helptopic: denylist {help}
(h/he/hel stay command words), reservelist {c to tc} (fall through to
command lookup; e/en and te/ter fall through naturally as ambiguous).
Argless 'help' output byte-identical to the strict-80 baseline.
- tests: choices.test +5 (alias exact/prefix normalization, noprefix exact-
only, nocase, the punk::help policy matrix, resolve-time validation);
cmdflow.test parity tests flipped from GAP to agreement + alias-traverse and
display-fold assertions (+flowaliased fixture)
- suites: punk/args 98 pass + 1 skip, punk/ns 28 pass, punk/lib 21 pass
- G-040 flipped active -> achieved 2026-07-08; detail file records
implementation and verification
- project 0.4.10 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- commented out five development trace puts in the doc-lookup machinery:
"PROC auto def"/"ENSEMBLE auto def" (generate_autodef) were emitted on STDOUT
and polluted 'i'/'s' output in script/exec contexts (agent-facing per the
G-015 piped-call pattern); "cmd_traverse - skipping to documented subcommand"
(space-form id path), "---> cmd_traverse ensembleparam" (ensemble -parameters
traversal) and "cmd_traverse 10 ... - review" (fallthrough return) were
stderr noise. No functional change.
- cmdflow.test: 8 new tests characterizing ensemble -parameters handling in the
doc-lookup flow (the punk::netbox::man pattern - leading apicontextid before
the subcommand at every ensemble level):
* generate_autodef models each -parameters entry as a -ensembleparameter 1
leader with @leaders min/max = nparams+1 (single- and two-param fixtures)
* cmd_traverse consumes parameter words and resolves the subcommand's
explicit or autodef docid, re-presenting the parameter in args_remaining
so the subcommand's own leader-based definition (as punk::netbox::man's
explicit defs model the curried parameter) can parse it
* nested sub-ensembles with their own -parameters re-consume the curried
parameter at each level
* punk::args::parse treats -ensembleparameter leaders as ordinary named
leaders; cmdhelp renders a documented subcommand's usage through the
parameter (end-to-end smoke)
- suites: punk/ns 26 pass (was 18), punk/args 93 pass + 1 skip (unchanged)
- project 0.4.6 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com