You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

204 KiB

Changelog

All notable changes to the punkshell project version are documented here. The latest ## [X.Y.Z] header must match the version field in punkproject.toml. Entries are newest-first; one bullet per notable change. See the root AGENTS.md "Project Versioning" section for the bump policy.

[0.65.2] - 2026-08-08

  • make.tcl launch-site steering: the bootsupport-staleness fix block now ends with a red-highlighted reminder to return to the project root for the remaining steps (vfscommonupdate/bake are canonically root-launched on the refreshed bootsupport snapshot, which also re-arms the staleness check), and the src/-launch banner gains the same red canonical-mode steer plus a "fine for bootsupport repair and source-tooling testing" line. Early-site colour via ::punkboot::sgr - NO_COLOR/force/tty precedence honoured, piped output stays ESC-free.
  • make.tcl dirty-src proceed countdown extended to 4 seconds (was 3).

[0.65.1] - 2026-08-08

  • make.tcl bootsupport-staleness warning rewritten to explain the launch-site mechanism instead of reading as circular advice: it names the directory the run was launched from, contrasts module precedence (from src/ the source modules drive make.tcl and the check does not apply; from anywhere else the stale bootsupport snapshots are the code executing the current command), adds a NOTE when the invoked command is itself a repair command (modules/bootsupport), and prints the recommended fix with the resolved src path as a copy-pasteable line. Shared emitter for the pre-dispatch gate and the check report tail.

[0.65.0] - 2026-08-08

  • package epoch is now documented, and help output flags live command overrides (G-176 increment 4). i package epoch renders real usage: the doc block travels WITH punk::libunknown's ::package override (attached to its commandstack record via rename_command -punkargs, removed with it if the override is unwound; punk::libunknown 0.3.1 - init now requires commandstack 0.8+). punk::ns::cmdinfo gains an overridden result key (a second axis in the G-166 style: live commandstack override state of the base command with renamers and any attached doc ids) and cmdhelp/i leads its renders with a "note: '' is currently overridden/extended via commandstack by: ..." line - -return text leads with OVERRIDDEN:, -return dict carries the structured key. (punk::ns 0.11.0)

[0.64.0] - 2026-08-08

  • commandstack 0.8.0 (G-176 increment 3): rename_command accepts a new leading option -punkargs <list-of-definitionlists> attaching punk::args doc blocks to the rename's stack record - e.g documenting a subcommand the override adds, with space-form ids such as {::package epoch}. The docs are live while the record is on the stack and are removed with it by ANY removal path (remove_rename, pop_rename, remove_renamer, restore_original). Renames performed before punk::args loads are supported: definitions are mirrored in the registered ::commandstack::stackdocs namespace and load lazily with punk::args; when punk::args is already present they are defined immediately. The record carries the deflists under a trailing punkargs key (key-order contract preserved); commandstack::help and the rename_command argdoc describe the mechanism.

[0.63.0] - 2026-08-08

  • punk::libunknown 0.3.0 (G-176 increment 2): the ::package override (the epoch subcommand and controlled forget) now installs via commandstack::rename_command instead of the former rename ::package ::package:: + namespace-import mechanism, so both live ::package overrides (libunknown's and punk::packagepreference's) share one managed stack whatever the install order - stack removals and third-party renames re-link correctly instead of operating on the wrong command. Behaviour of every subcommand arm is unchanged (pinned by the increment-1 characterisation suite; only its marked install-shape pins flipped). ::package:: no longer exists (nothing in the tree called it); libunknown's init now requires commandstack (a no-op when packagepreference installed first, as in punkshell boot).

[0.62.2] - 2026-08-08

  • i ::tcl::prefix no longer emits 12x "warning: update_definitions received unqualified ns: tcl" on stderr (nor 6x on subcommand renders): the tclcore moduledoc passed the ensemble name to punk::args::ensemble_subcommands_definition unqualified, and the generator's space-form id checks derived the non-empty unqualified namespace tcl from it once per subcommand per @dynamic re-resolve. The tclcore call site now passes ::tcl::prefix, and the generator itself normalizes its ensemble argument to fully-qualified in the caller's context - covering any future relative multi-component caller. Rendered help verified byte-identical. tcl::prefix was the only ensemble affected: single-component names (info, dict, file, ...) derive an empty qualifier that was already mapped to ::. (punk::args 0.25.2, punk::args::moduledoc::tclcore 0.4.2)

[0.62.1] - 2026-08-08

  • grepstr works with dash-led patterns again: the capture-group probe regexp -about in punk::ansi::grepstr lacked its -- end-of-options guard, so any dash-led pattern (e.g grepstr -h underline -group test-group) errored with regexp's own "bad option" message - with or without -- in the grepstr invocation - ever since this grepstr replaced the dash-safe ::punk::grepstr (2025-11-10). The punk::args parse layer was never at fault: it seats the dash-led word as the pattern value in both invocation forms (now pinned). The -type regexp validator in punk::args had the same missing --, falsely rejecting legitimate dash-led regex values. (punk::ansi 0.2.1, punk::args 0.25.1)

[0.62.0] - 2026-08-08

  • punk::args bounded -multiple occurrence ranges now participate in positional allocation (directed work, post-G-053): a leader or value argument that has taken its max occurrences yields further words to later arguments (an untyped {3 3} followed by a -multiple tail takes exactly 3 instead of overrunning and erroring), a later REQUIRED ranged argument reserves min-occurrences worth of words from earlier greedy collection (the allocator reservation, the derived valmin floor for the leader/value split and option scan - an explicit @values -min still overrides), and the greedy leader scan caps a bounded -multiple last leader. Genuine over-supply keeps a pointed report: the overflow site renders the occurrence limit with the G-053 occurrencecount errorcode via a new G-082 rejection kind. Legacy boolean -multiple allocation is unchanged. (punk::args 0.25.0)

[0.61.0] - 2026-08-07

  • punk::args -parsekey completeness (G-084): a VALUE argument's -parsekey now renames its result values slot and its received key (previously accepted at define time but aborted parse), with -multiple values collecting under the parsekey; a leader -parsekey is rejected at define time (was silently ignored). Cross-member -multiple on a shared-parsekey option group is a define-time error unless ALL members share one @opts -parsekeymode error group whose mutual exclusivity makes per-member collection well-defined - settling the cross-member accumulation question as rejection rather than accumulate; a {0 1} range member (replace-shape) stays allowed. Value parsekeys must be unique per form and must not be dash-led (previously silent positional overwrite / internal parse abort). The shared-group defaulted-members precedence rule is now documented behaviour: the last-defined member's default wins. parse_status/parse_report attribute received/value through unique storage keys (value parsekeys, renamed options, =-suffixed optset tails); shared-parsekey groups keep the recorded per-member attribution gap. undefine/undefine_deflist return an empty string instead of a whole internal cache dict. define -help now documents -parsekey. (punk::args 0.23.0/0.24.0)

[0.60.0] - 2026-08-07

  • punk::args -multiple gains occurrence-arity ranges (G-053): -multiple accepts a {min max} range (max -1 unbounded) alongside the legacy booleans, so a definition can declare at most once ({0 1}; a second occurrence is a parse error), bounded repetition ({2 4}), or one-or-more ({1 -1}) instead of choosing between silent last-wins (0) and unbounded collection (1). The spec compiler canonicalises once at resolve, keeping the stored -multiple boolean's hot-path meaning so legacy 0/1 stay byte-unchanged; range companions live in a separate per-form MULTIPLE_RANGES dict (not in ARG_INFO, so they survive resolved_def spec round-trips). A new PUNKARGS VALIDATION occurrencecount failure class fires per section (opts/leaders/values); over-max is a hard contradiction (invalid), under-min is pure exhaustion (incomplete, suppressed in the G-152 viability probe). The -optional/range-min reconciliation is enforced and documented at define time. The usage-table Multi column shows 0-1/2-4/1+ (greencheck stays for legacy 1), the string renderer emits MULTI:0-1, and the synopsis distinguishes at-most-once (?arg?) from repeating (arg...). -multipleunique/-multipleuniqueset compose unchanged.

[0.59.0] - 2026-08-07

  • punk::args gains argument-relation vocabulary and parse-time enforcement (G-083): per-argument -conflicts <list> declares that named arguments (parsekeys or flag names) must not be received together with this argument, and @opts -parsekeymode override|error (per named group) makes a shared-parsekey group's distinct-member co-occurrence a parse-time optionconflict (override, the legacy last-wins default, or error). Both are cross-validated at definition resolve; a colliding -parsekey is now a resolve error. optionconflict is a new PUNKARGS VALIDATION failure class, checked against received arguments only (defaults never conflict), over both the ordinary and mash (short-flag bundling) parse paths, and classified as invalid (not incomplete). Usage/arg_error rendering surfaces the rules: a conflicts with: <targets> hint on each conflicted argument's help row and a mutually exclusive (distinct members may not be combined) group header annotation for -parsekeymode error groups; the synopsis one-line form carries no conflict detail. The lsearch tclcore moduledoc models its documented -sorted/-glob/-regexp and -bisect/-all/-not incompatibilities via per-arg -conflicts (the group stays override so -glob/-regexp remain last-wins) and drops its punk::args fixes required caveat. Legacy behaviour is untouched by default (no -conflicts, default override, no colliding parsekey).

[0.58.0] - 2026-08-07

  • punk::path gains machine-parsable return modes and a stable conflict verdict (G-173): -return text|dict|json (default table byte-unchanged) emit ANSI-free structured data; -context <namespace> (default the caller's namespace) makes the TCL-context conflict verdict stable for a machine consumer invoked through a wrapper; -conflicts 0 skips conflict computation. The JSON form uses tcllib json::write and round-trips the dict form byte-for-byte.

[0.57.1] - 2026-08-07

  • punk-runtime surfaces a recorded CPU instruction-set floor and gates launching a runtime the local CPU cannot run (G-172). A runtime's artifact metadata toml now carries cpu_floor (the recipe's declared default floor) and cpu_model (the build's resolved CPU model); fetch reports them (ungated - a cross-platform fetch for another machine stays free), list annotates rows the host cannot run (!CPU-FLOOR:v<req>), use/run abort with a named diagnosis instead of a silent STATUS_ILLEGAL_INSTRUCTION (0xC000001D), and info shows the fields. The suite_tcl90 kit-family record writes the floor into each artifact's [provenance], and a new codegen audit tool scriptlib/developer/cpufloor_audit.tcl disassembles a binary and reports instructions above the declared floor (the acceptance instrument for the AVX-512 host-tuning regression). Floor-bearing published artifacts land at the next republication.

[0.57.0] - 2026-08-06

  • Recognised-but-unavailable documentation landings are now surfaced distinctly at the shell (G-166). On Tcl 8.6, i string is dict and i string is true were machine- and eye-indistinguishable: both reported cmdtype doconly with identical key sets, and i string is dict 5 rendered exactly like a usable command line. punk::ns::cmdinfo gains an unavailable result key (empty, or the canonical -choiceunavailable name the resolution addressed) as a second axis beside cmdtype, and punk::ns::cmdhelp marks such subjects visibly in every return form - the dict form carries the key, table/string render the marking below the usage, and -return text leads with an UNAVAILABLE: line.
  • i <cmd> <prefix> landing uniquely on an unavailable name now resolves that name's documentation (marked) instead of resolving nothing - i string is dic on 8.6 documents the dict class. Addressing documentation and word availability are separate axes; only the latter says the word is unusable.
  • The string is <class> documentation for a class this runtime lacks now leads with the unavailability statement instead of ending with it.

[0.56.2] - 2026-08-06

  • make.tcl bake/bakehouse now end with a BAKE SUMMARY block: a counts headline (deployed=N unchanged=N not-built=N failed=N, plus the number of BAKE-WARNINGs recapped after it) and one line per kit under NOT BUILT / UNCHANGED / INSTALLED KITS / FAILED KITS, each with its reason. A full bake's per-kit output scrolls far out of reach, so the run previously ended with no answer to "what actually baked?" - the old INSTALLED KITS and FAILED KITS blocks named only the kits the kit machinery touched and said nothing about the rest. The summary covers the whole configured matrix: kits skipped for an absent runtime, bake_default=false, a release-gated scheme output or a missing .vfs folder never reach the kit machinery at all, and on a part-populated runtime store those are most of the rows. Rows are keyed by the kit's path relative to bin//src/_bake/ so cross-target namesakes (kits/<platform>/<kit> - G-127) stay distinct; a selective bake summarises only the kits it was asked for. The block is stdout (contiguous under redirection) with failures echoed to stderr from the same ledger.
  • make.tcl bake/bakehouse now exit 4 when the run completed with one or more FAILED kits. make.tcl's existing non-zero codes all mean "refused to do the work" (1 usage/gate refusal, 2 structural abort, 3 config error), so a run that DID the work and had kits fail exited 0 like a clean one - and punk::mix::cli::make (dev make <subcommand>, the in-tree caller that branches on the exit code) reported OK make finished and returned true for a bake in which every kit failed. 4 keeps "could not run" distinguishable from "ran, produced failures". The not-built bucket deliberately never affects the exit code: an absent runtime, bake_default=false or a release-gated output are normal states, and a part-populated runtime store is the common case.

[0.56.1] - 2026-08-06

  • make.tcl project-version bake gate: the kit-assembling subcommands (bake, bakehouse, bin) now treat the project version as the bake input it is (stamped into every kit's punkkit-stamp.toml and used for versioned-scheme output names). A new -expect-projectversion <ver> flag asserts the version a bake is intended to ship - a mismatch with punkproject.toml aborts before any kit work. When a bump looks pending (src/ commits since punkproject.toml last changed, none staged), an interactive run is prompted (y/N) and a non-interactive run aborts fast unless the version is asserted; -confirm 0 deliberately does not waive the gate (agent runs pass it habitually - the gate interrupts habit with a checked claim). A staged-but-uncommitted bump passes (bake reads the working-tree value); degraded bootsupport reduces the gate to a NOTE, but a supplied assertion then aborts as unverifiable. Motivated by the 2026-08-06 bake-then-bump inversion, which stamped 0.55.1 into 11 kits and cost a full re-bake.
  • make.tcl projectversion overdue warning now states the consequence and prints the ready-made assertion command; make.tcl check reports the gate state and current staleness verdict; the workflow text ([K2]/[K6], release-sequence steps (2)/(8)) and the help surfaces document the ordering and the flag. Root and src AGENTS.md "Project Versioning" guidance updated to state the bake-input dependency and the bump-BEFORE-bake order.

[0.56.0] - 2026-08-06

  • Coherent-set promotion + bake (the G-169 and G-170 follow-on promotion lines, landed together): the launcher-family work of G-151, G-168, G-169 and G-170 reaches the kits. Promoted punk::args 0.18.0 and punk::ansi 0.2.0 into bootsupport and _vfscommon.vfs, plus punkboot core 0.7.0, punkexe moduledoc 0.9.0, punkboot moduledoc 0.3.1 and app-punkscript/app-punkscript-docs 1.3 into _vfscommon.vfs; 11 kits rebaked and deployed. User-visible in a deployed kit for the first time: <punkexe> help <sub> <formname|index> narrows a multi-form definition to that form's argument table, the multi-form synopsis lines carry actionable help <sub> %formname% labels instead of the suppressed column, any other tail on a parse-true subcommand is dry-run through its definition (accepted lines render the matched form plus the punk::args::parse_report landing report; rejected lines emit the parse diagnosis on stderr, exit 1), and help script renders the app-owned definition that now lives beside the code implementing it.
  • The tclsh dry-run arm goes live with this bake: it requires the G-168 fence witness in the moduledoc actually served, so kits carrying the older 0.6.1 snapshot had kept the historic ignored-tail render. That mixed-vintage state is now resolved in the deployed kits.

[0.55.1] - 2026-08-05

  • G-149 follow-on landed: make.tcl's multi-form definitions (tool, buildsuite) adopt '@cmd -formhint' - 'make.tcl help tool' / 'help buildsuite' now label each form's synopsis line with the actionable dry-run-help invocation plus a trailing ellipsis ('make.tcl help tool build ...' rendered with U+2026) instead of the repl-oriented ' i -form N ...' default, which is unreachable for make.tcl's (script) ids. The ellipsis honestly marks that help accepts the form's own command line after the action (the dry-run continuation). The labels also render on dispatch usage errors, where they are the discovery route to per-action help - the reason the column is configured rather than suppressed. Renders via the promoted bootsupport punk::args 0.17.0; degrades harmlessly (default labels) under older snapshots in generated projects. Layout make.tcl copies and the templates modpod synced via the established channels.

[0.55.0] - 2026-08-05

  • G-149 achieved: punk::args configurable multi-form synopsis hint labels (punk::args 0.17.0, source module). The per-form hint labels rendered beside a multi-form definition's synopsis lines in usage/help tables (hard-coded " i -form N ..." previously) are now a template substituted per form: %formindex% is replaced with the form's 0-based ordinal, %formname% with its name, and an empty template suppresses the labels entirely. A definition supplies its own via the new '@cmd -formhint' directive key; callers of usage/arg_error may override with the new -formhint option. Unconfigured definitions render byte-identical to before. Motivation: script-level (script) definitions such as make.tcl's are unreachable from any repl, so the repl-oriented 'i' hint was not actionable there - make.tcl adoption follows a future bootsupport promotion. Kits pick this up at the next bootsupport/vfscommon refresh and bake.

[0.54.0] - 2026-08-05

  • G-073 achieved: punk::args unavailable choices (punk::args 0.16.0, tclcore moduledoc 0.4.0, punk::ns 0.9.3, source modules). A definition can declare -choiceunavailable names - recognised but not available in the current runtime/context. They display among the choices under a dedicated "Unavailable (recognised, not selectable here)" group with their ordinary choicelabels notes, reserve prefixes (a prefix shared with an available choice is ambiguous), and are rejected with a tailored choiceunavailable error naming the entry and its note instead of the generic listed-values error; synopsis literals and value-in-effect marking never include them. The tclcore 'string is' model adopts the key via a curated forward-class list: on Tcl 8.6 the dict class now displays with its "(class not present in Tcl 8.6)" note, 'string is dict' is rejected informatively, 'string is di' is ambiguous (deliberately stricter than real 8.6, preparing users for 9.x - recorded as a sanctioned parity exemption), and 'i string is dict' documents the class via its per-class virtual id. The punk::ns doc walk honours unavailable names identically to parsing. Kits pick this up at the next bootsupport/vfscommon refresh and bake.

[0.53.1] - 2026-08-05

  • G-082 follow-on landed (punk::args 0.15.2, source module): a REQUIRED typed value or leader whose supplied word fails the basic-type allocation screen (int/double/bool/number/dict) now reports the pointed typemismatch naming the word and argument (with -badarg/-badval) instead of the generic "Not enough remaining values" missingrequiredvalue/missingrequiredleader shortfall. Genuine shortfalls (end-of-input, literal-typed members, multi-member clause partials) report unchanged. parse_status for the affected shape now classifies invalid/typemismatch (the formstatus viability verdict was already invalid). Kits pick the fix up at the next bootsupport/vfscommon refresh and bake.

[0.53.0] - 2026-08-05

  • Single help mechanism (user direction; boot core 0.5.0, moduledoc::punkexe 0.6.0, moduledoc::punkboot 0.3.0): all -help/--help flag interception is withdrawn from the kit launcher and make.tcl - the leading help word is the one help entry (the punkshell i <cmd> ... idiom). <punkexe> help <subcommand> ?arg ...? now accepts and ignores trailing words, so help can simply be prepended to an existing command line (previously help tclsh somefile somearg confusingly fell back to the top-level table). Help flags are ordinary arguments everywhere: a leading -help earns the unknown-first-argument refusal (whose stderr usage answers it, exit 1), tclsh -help regains full stock dash parity (the sole-argument carve-out is gone), buildinfo -help is refused like any argument (exit 2), the experimental shellspy processor's own -help/--help handling is reachable again, and make.tcl <subcommand> ... -help fails whatever punk::args gate it meets (e.g. bakelist -help = the same choice-gate rejection as bakelist nonexistant) with the usage error itself carrying the documentation. launcherhelp.test and maketclhelp.test re-pinned to the revised contract.

[0.52.0] - 2026-08-04

  • G-165 driver-invariant kit assembly: every make.tcl zip-kit bake now emits an ARCHIVE-relative kit regardless of the driving interpreter (legacy file-relative mkimg in 8.7/9.0.0, fixed mkimg in 9.0.1+, or no mkimg at all). Zip-kit assembly uses a single writer layer - punk::zip::mkzip (0.4.0), punkzip-accelerated when bin/punkzip resolves via the new write-path seam (mirroring the G-126 read-path accelerator), the pure-Tcl floor otherwise - with the runtime prefix concatenated outside the writer; tcl::zipfs::mkimg is retired from the pipeline. Four-driver acceptance on the reference machine (8.7a6, 9.0.3, native 8.6, msys2 8.6): identical member sets and CRCs, offsetstyle=archive, no BAKE-WARNINGs. File-relative kits remain available only as an explicit per-kit offsetstyle = "file" declaration in src/runtime/mapvfs.toml (the G-134 carve-out as configuration; the pin now warns only on undeclared file-relative output and exempts declared kits - specimen: [kit.punkfiledemo]).
  • punkzip 2.4.0 re-vendored (G-165 enabling changes, upstream commit 2599127): build gains -b root-strip (mkzip -base semantics) and repeatable -x entry-name exclusion (Tcl string match syntax).
  • make.tcl bake/bakehouse -force flag: re-assemble kits whose inputs are unchanged (bypasses the 'no change detected' skip).
  • punkkit-stamp.toml is now written with pinned LF translation - the default text translation followed the driving interpreter (crlf vs lf), making the stamp's bytes driver-dependent (caught by the four-driver parity run).

[0.51.2] - 2026-08-04

  • punk::tcltestrun 0.4.2 (G-161 follow-on, landed at user direction): the closing-banner prefix match no longer treats the test NAME as a glob pattern - string match "$line_inner*" meant a name containing glob metacharacters (* ? backslash) never matched its own opening text, so the closing banner failed to close the failure section and every later event including the summary line was swallowed (the G-161 wedge class; latent, unexercised in the corpus). The check is now an exact byte prefix compare (string equal -length) - identical semantics for ordinary names. Pinned by new parsetestrun-globname-7.0/7.1 in the parser suite (8/8 green: tclsh90 both modes, tclsh86).

[0.51.1] - 2026-08-04

  • punk::args 0.15.1 (G-164): the G-152 form-viability verdict's valmin-reservation false negative is cured. When the reservation seats a word that literally names a declared required option into a required value slot at end-of-input, and the resulting optionmissing stands in the viability probe (a value word consumed), the probe re-parses with the stolen word(s) consumed as the options they name and classes the form viable (incomplete) on pure end-of-input exhaustion. i hash -t now marks the test form "(viable - needs more arguments)" (show_or_set/rehash/delete/help stay not viable) and i hash -d marks delete viable - the 0.51.0 known issue is resolved. Runtime seating is unchanged: the trailing-flag-as-value rule is load-bearing and pinned unchanged, as is the runtime optionmissing ("missing flags") path; a stolen word naming a value-TAKING required option stays conservative (invalid). Options still missing after the re-seating are ordinary exhaustion in the re-probe. Verdict contract documentation updated in the parse/parse_status argdoc. Pins: formviability.test +7 tests (17/17), cmdhelp.test GAP pin cmdhelp_GAP_multiform_flagled_testform_false_notviable flipped to cmdhelp_multiform_flagled_testform_viable (45/45); args + ns subtrees green apart from the 2 pre-existing nsprimitives environment failures on this box.

[0.51.0] - 2026-08-04

  • i <command> ?word ...? form narrowing for flat multi-form commands (G-150): punk::auto_exec::hash's declaration is now selection-sound - its show_or_set name value carries -regexprefail {^-}, so a bare punk::args parse of a flag-led line selects the flag form uniquely instead of reporting an ambiguous match with show_or_set (which swallowed flag-like words as plain names). i hash -r now renders only the rehash form's usage and i hash -d <name> only the delete form, driven by the declaration through cmdhelp's existing G-041 advisory-parse candidacy (no hash-handler involvement); no-word, ambiguous and no-match lines keep the whole-command render. hash's runtime behaviour is unchanged - a dash-led name now needs an explicit flag form at the declaration level too (accepted cost). cmdhelp's subcommand help documents the narrowing contract. Modules: auto_exec 0.1.1, ns 0.9.2 (documentation-only). Pins: 8 new tests in ns/testsuites/ns/cmdhelp.test (narrowing on -r/-d, bare-parse selection incl -t/plain/empty lines, the dash-led-name noformmatch cost, no-word and ambiguity whole-render fallbacks, unknown-flag noformmatch fallback, runtime-unchanged hash behaviour).
  • hash declaration/handler refinements (user direction, same batch): the help form dropped -anyopts so --help must lead, and trailing words of any shape are consumed as ignored values - dash-led words included, via the new punk::args @values -flagvalues 1 capability (punk::args 0.15.0, added for this: an unmatched dash-led word in option position seats as a trailing value instead of raising invalidoption; opt-in, off by default). A flag-led line (e.g. -t) no longer marks the help form viable via adhoc-option seating (the old "help (viable)" pointer for i hash -t was wrong). Known issue in the remaining verdict: the test form also reports "(not viable)" for i hash -t - a false negative, since hash -t foo is valid; the valmin reservation seats the lone -t as the required name value, after which the G-152 position guard lets the required-flag optionmissing stand. The intended refinement is an alternative- allocation re-probe in the G-152 probe layer (re-probe with the stolen word consumed as the option it literally names), NOT a runtime seating change - the trailing-flag-as-value rule is load-bearing and pinned unchanged. GAP-pinned in cmdhelp.test. Also the handler's multi-name -t missing-name branch now prints "hash: : not found" (was an undefined-variable error "can't read hash"). Pins: args flagvalues.test (9) + cmdhelp.test (45/45 green).

[0.50.1] - 2026-08-04

  • commandstack 0.7.1 (G-160 follow-on, landed at user direction): the reload contract - known_renamers and debug are now info-exists guarded like the rest of the module state (all_stacks, renamer_command_tokens, token_implementations), so a module re-source refreshes proc definitions only and no longer resets them while stacks/tokens survive. Previously the reset stranded live stacks: the removal forms gate on known_renamers membership, so the surviving records' renamers became unknown and removal errored. Contract documented in commandstack::help; pinned by commandstack_reload_preserves_state (suite 41/41 on tclsh90 9.0.3 and punk86 8.6; packagepreference consumer suites 6/6 on both). Minted as modules/commandstack-0.7.1.tm; bootsupport/vfscommon promotion left to the next promotion cycle (as with 0.6.0/0.7.0).

[0.50.0] - 2026-08-04

  • punk executable -e one-liner support (G-077, achieved): ` -e