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.
 
 
 
 
 
 

38 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.12.0] - 2026-07-11

  • punk::args 0.6.0: command synopses (s <cmd>, i <cmd>, usage headers) now display small restricted choice sets as literal alternates — an argument whose choice pool (-choices plus -choicegroups members) has 1–3 members and -choicerestricted true renders those words unitalicised joined by | (e.g. after cancel shows literal cancel; a 3-choice option shows (left|centre|right)), matching the existing display style of literal()/literalprefix() type-alternates. Larger or unrestricted choice sets keep the italicised argname/type display and an explicit -typesynopsis always wins, so e.g. textblock::frame -type (choice|<dict>) is unchanged. Synopsis rendering of type-alternates, -typesynopsis passthrough (including documenter ANSI styling), and multi-element clause display gained characterization test coverage (synopsis.test).

[0.11.0] - 2026-07-11

  • G-001 achieved: an interactive REPL can be launched against a non-detectable terminal-like device via an ::opunk::Console subclass — repl::init -console <spec> selects the console (channel pair, anchored instance name, or object value), repl::start's input channel defaults to it, and the repl's output (prompts, results, and the code interp's stdout/stderr — diverted via shellfilter junction stacks and emitted per run) routes through the selected console's channels, with eof/size/capability answered by the subclass overrides (punk::repl 0.4.0; base ::opunk::Console and punk::console untouched). Verified end-to-end by child-process driver tests: an ::opunk::SshConsole socket session whose scripted remote terminal answers CSI 6n (size resolved over the socket) and a ::opunk::TkConsole text widget wired as a live console by new opunk::console::tk::console (reflected output channel rendering into the widget + Return-binding input pipe, opunk::console::tk 0.2.0). Process-console behaviours (tcl_interactive prompt gating, stdin reopen on eof, raw-mode re-enable, the windows line re-decode experiment) now apply only when no foreign console is selected; default stdin/stdout repl behaviour is unchanged.

[0.10.3] - 2026-07-11

  • make.tcl build/promotion commands (project, packages, modules, libs, vfs, vfslibs, bin, bootsupport, vfscommonupdate) now warn when src/ has uncommitted fossil/git changes — artifacts built from dirty src have no committed provenance (G-026 direction). Warn-only by default; a new -dirty-abort flag makes the check aborting. Dirt outside src/ is ignored (punkboot::utils::vcs_dirty_warnings gained an optional scope argument, utils 0.2.0). With <builtexe> src / <builtexe> src shell available for evaluating uncommitted source directly, building is the promotion step the warning treats it as.
  • Provenance warnings (dirty-src gate and vendorupdate's dirty source-project check) are presented with a plain column-0 PROVENANCE-WARNING: token for automated discovery in redirected output plus ANSI colour for humans, and are recapped at the very end of the run (via a wrapped ::exit) so they survive scrolling chatty build output. Interactive terminal runs (Tcl 8.7+/9 stdin -inputmode probe) additionally get a 3-second ctrl-c grace countdown before a dirty build proceeds; piped/agent/CI runs pay no delay. make.tcl check now reports src provenance status and what the build/promotion commands would do.

[0.10.2] - 2026-07-11

  • punk::libunknown bumped 0.1 → 0.2.0 (file renamed libunknown-0.2.0.tm), retroactively versioning the register_all_tm and source_pkgindex additions and adopting full major.minor.patch form. Verified nothing requires it by exact version or filename: punk_main.tcl and punk::repl glob libunknown-*.tm picking the highest by vcompare (the dev copy now also outversions the stale bootsupport/project.vfs 0.1 copies deterministically), bootsupport's include_modules.config lists it by name only. The module header now carries a version-history block in lieu of a buildversion.txt, and src/modules/AGENTS.md documents the manual-versioning bump mechanics for agents (same Patch/Minor/Major rules as buildversion-tracked modules).

[0.10.1] - 2026-07-11

  • punk::libunknown: pkgIndex.tcl scripts are now executed in an isolated source_pkgindex frame providing the documented $dir variable plus auto_path/env global links (matching stock tclPkgUnknown's contract), instead of at :: scope with a global dir. Fixes any user global named dir being silently overwritten whenever a package require fell through to the pkg unknown handler, and stops index scripts' helper variables (ver, pkg, script, _CawtSubDirs, ...) leaking into the global namespace. Verified against tcllib 2.0's index behaviours (auto_path extension, apply-scoped subindex sweep, critcl-style loaders); regression tests pin the $dir/auto_path/no-leak contract.

[0.10.0] - 2026-07-11

  • dev lib.search now performs deep module discovery by default: new punk::libunknown::register_all_tm registers .tm modules at every namespace depth across all tm paths (reusing/populating the per-epoch directory index cache, at most one scan per package epoch per interp), so namespaced modules in never-requested subfolders (e.g. test::*) appear in search results without -refresh (punk::mix::commandset::loadedlib 0.2.0).
  • dev lib.search -refresh repurposed to mean a genuine filesystem re-scan: it increments the package epoch (invalidating punk::libunknown's scan caches) and re-runs discovery, picking up .tm files added/removed on disk and re-sourcing pkgIndex.tcl files. Without punk::libunknown active, -refresh retains the previous dummy-require deep-walk behaviour.
  • lib.search dependency fixes: works in bare interps now — highlight ANSI codes computed only when highlighting (fully-qualified punk::ansi with inline require; previously errored on the shell-global a+ alias even with -highlight 0), inline requires for punk::path (fallback walk) and textblock (table output).

[0.9.1] - 2026-07-11

  • dev lib.search -refresh help rewritten to document actual semantics (punk::mix::commandset::loadedlib 0.1.1, doc-only): the flag performs a deep tm discovery pass (registering .tm modules in never-requested namespace subfolders), it does not re-scan directories already indexed in the current package epoch (run package epoch incr first for a genuine filesystem re-scan), and tm/auto_path list changes are epoch-invalidated automatically. New characterization test suites pin the underlying punk::libunknown discovery/epoch-cache behaviour (src/tests/modules/punk/libunknown/testsuites/discovery/) and the lib.search match + -refresh contract (src/tests/modules/punk/mix/testsuites/loadedlib/), including a GAP pin of the pkg-unknown handler clobbering a user global dir variable (stock Tcl keeps it proc-local).

[0.9.0] - 2026-07-11

  • G-001 (in progress) increment 1: three pluggable ::opunk::Console backend modules, with the base class and punk::console untouched — opunk::console::test (::opunk::TestConsole: deterministic channel-pair test double with fixed size and probe-free eof — the console seam the repl/editbuf characterization work needs), opunk::console::ssh (::opunk::SshConsole: socket-carried terminal sessions — construction-time capability, chan-eof without byte-consuming probes, and size resolved by punk::console's ANSI cursor-report provider querying over the connection, proven against a scripted remote terminal answering CSI 6n over a socket pair), and opunk::console::tk (::opunk::TkConsole: a Tk text widget as terminal — widget char dimensions as size, backend eof marker via opunk::console::tk::set_eof, verified live under the tk-capable punk91 kit). Subclass values dispatch through existing base-class holders and console_spec_resolve virtually. Remaining for the goal: repl launch-time console selection and output-channel parameterization.

[0.8.2] - 2026-07-11

  • G-054 achieved: tclcore moduledoc 0.2.0 — the string is class choices shown by i string is (and the per-class docids like i string is digit) are now harvested from the running interpreter at define time instead of a hand-maintained list, so the documented/parsed class set always matches what the interpreter accepts (previously the static Tcl 9.0 list wrongly accepted dict under 8.6 and rejected 8.7's unicode). Version notes render on classes that differ across releases; unrecognized future classes get a generic label instead of vanishing. Behavioural parity pinned by tclcoreparity.test with expectations derived from the live interpreter — green on Tcl 8.6.13, 8.7a6 and 9.0.3.

[0.8.1] - 2026-07-11

  • runtime.cmd powershell payload: cached sha1sums.txt fallback backported from the bash payload - list -remote against an unreachable server now warns and compares using the previously fetched copy instead of dying on an unhandled download error, and the fetch path's pre-existing silent fall-through to a cached copy now announces itself. Also fixed a latent undefined-variable bug creating the runtime folder in the list -remote branch.

[0.8.0] - 2026-07-11

  • runtime.cmd list -remote parity for the unix (bash/zsh) payload: local-vs-server comparison table (Same version / UPDATE AVAILABLE / not-listed, plus remote-only entries), falling back to a cached sha1sums.txt with a warning when the server is unreachable. Both payloads gain a PUNKBIN_URL env override of the artifact server base url (mirrors/testing).
  • The polyglot's 512-byte label guard caught its first real regression during this change: the payload growth pushed the template's :exit_multishell label across a boundary; fixed with a documented byte-alignment spacer comment in runtime.bash (workflow recorded in bin/AGENTS.md).
  • G-059 achieved: WSL capability probing + native-filesystem staging for driving unix-side tests from Windows (src/tests/testsupport/wslprobe.tcl, wsllinux constraint). The MULTISHELL sh payload and the runtime.cmd unix payload (runtime.bash — never previously executed on real unix) now run green under WSL: active/use/run resolution, env override, stale-active guidance, single-candidate fallback and offline list -remote — all staged to the distro's native filesystem, with a guard test asserting the Windows checkout's git state is untouched.

[0.7.0] - 2026-07-11

  • bin/runtime.cmd gains a use subcommand and an active-runtime selection: which runtime run launches is now the per-machine bin/runtime/<platform>/active.toml (active = "<name>", shown with a * in list), resolved as PUNK_ACTIVE_RUNTIME env override → active.toml → sole installed candidate — with multiple runtimes and no selection, run errors listing candidates instead of silently launching the last name alphabetically. The first fetch sets the active runtime only when none is recorded; later fetches never steal it.
  • runtime.cmd fetch checksum parity for the unix (bash/zsh) payload: it now fetches sha1sums.txt, skips when the local file already matches, downloads to .tmp and installs only on sha1 match (tool detection across sha1sum/shasum/sha1/openssl; refuses unverified downloads when no tool is present), and accepts an optional runtime name like the powershell payload. Bug fixes: the powershell "stored hash" message printed an empty variable; the bash MSYS branch had an invalid interp = assignment; .tmp leftovers and non-runtime files no longer appear as run/list/use candidates.
  • The runtime scriptset sources moved to src/scriptapps/bin/ (alongside getzig.*), the proper home for bin-deployed scriptsets; bin/runtime.cmd regenerated via the scriptwrap workflow (round-trip pinned byte-identical by the multishell test suite).

[0.6.0] - 2026-07-10

  • G-058: punkshell boot honours statically-linked runtime packages. Kits built on runtimes with static extensions (e.g tclsfe-x64.exe: Thread/twapi/sqlite3/tdbc — the punk91 kit) previously lost package require access to them in every interp/thread punkshell fabricates: the appended vfs replaces the runtime's own //zipfs:/app mount (taking its pkgIndex files with it) and punkshell's boot path replacement discards what remains — the repl code interp failed with can't find package Thread and punk::console couldn't load. Now punk_main.tcl captures the static baseline at boot (probe-loading each empty-filename info loaded prefix in a throwaway interp and recording only packages the load actually provides; configurable denylist for side-effecting/composite inits), and the baseline seeds package ifneeded <name> <ver> {load {} <prefix>} mappings in the boot interp, the repl codethread and code interp (punk::lib 0.4.0 interp_sync_package_paths/snapshot_package_paths, punk::repl 0.3.0), and shellthread 1.7.0 workers — introspectable at the repl via ::punkboot::static_packages.
  • punk::packagepreference 0.2.0: static-vs-bundled resolution is version-aware — requiring a baseline package triggers the package-index scan before resolution so all candidates register and the highest version wins (a static copy is no longer masked by an older bundled dll, and a genuinely newer bundled copy remains reachable); static registrations (empty-filename info loaded entries) no longer trip the loaded-shared-object same-version pinning. Composite statics whose script layer lived in the runtime's replaced zipfs (e.g. static twapi) provide nothing under the probe and correctly defer to bundled complete copies.
  • Tests: staticseed.test + staticpolicy.test (un-gated, simulated baselines) and staticruntime.test (kit integration behind the capability-probed statickitavailable constraint). The verification runtime tclsfe-x64.exe is pinned in the punkbin artifact repository (win32-x86_64 + sha1sums) so the constraint is satisfiable on other machines.

[0.5.0] - 2026-07-10

  • punk::args 0.5.0 (G-049): new punk::args::parse_status - runs a parse attempt and returns a documented parse-status structure instead of raising on validation failure: overall ok/status (valid|invalid|incomplete)/scheme/message/errorcode/failureclass/badarg/form/receivednames plus per-argument argstatus entries (class, status ok|bad|unparsed, received count/positions, value-in-effect including -default fill). arg_error accepts the structure via -parsestatus and both its renderers derive goodarg/badarg row marking and choice value-in-effect highlighting from it. Scheme colours now resolve per-render: the documented -scheme value nocolour takes effect (previously it fell through to whatever colours the last scheme render left behind) and scheme renders no longer mutate the shared colour array (the strike-only goodarg style no longer leaks into later renders). missingrequiredvalue/missingrequiredleader failures now carry -badarg, and punk::args::parse gained -caller to control the %caller% attribution in failure messages.
  • punk::ns 0.2.0 (G-049): i <cmd> <args...> (cmdhelp) gains -return dict - a machine-parsable dict of resolution info (origin/docid/cmdtype/args_remaining) plus the parse-status structure of the supplied argument words. Display fixes: a value failing its -type check now badarg-marks the unfillable argument's row (previously only choice violations marked anything), an explicit -scheme is honoured on the parse-failure path, and parse-failure messages name the queried command instead of leaking cmdhelp's internal parse source line at top call depth.

[0.4.15] - 2026-07-10

  • punk::args 0.4.2 (G-046): argument resolution no longer expands display-only ${...} content (-help on @cmd/@examples/argument records, @formdisplay bodies) - expansion is deferred to help-display time with its own cache. First use of heavily documented commands is dramatically faster (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. Also fixed: @dynamic multiline -help substitutions now align at their insertion column; prefix/alias-normalized choice values keep the same plain-string shape as exact input (\Deleted-style values); the -return string renderer aligns cmd-help continuation lines under the Description: label and its Example: line shows the example reference instead of the doc url.
  • punk::ns 0.1.4 (G-046): i <cmd> for a command whose definition requires arguments (e.g i string is, i punk::args::define) shows plain usage instead of an internal-looking "Bad number of leading values for punk::args::parse ..." error prefix - and builds the usage table once, not twice (the discarded advisory-parse error no longer renders its own table; display timing for large argdocs stays at pre-change levels).

[0.4.14] - 2026-07-10

  • punk::args 0.4.1: first i <ensemble> in a fresh shell now shows subcommand-help markers and synopsis choicelabels for documented subcommands whose argdocs are lazily registered (e.g i ansistring); previously the autogenerated ensemble help omitted them until another path loaded the ensemble's registered namespace (punk::args::update_definitions).

[0.4.13] - 2026-07-09

  • punk::args 0.4.0 tidy-up (pre G-046): dead developer-test procs removed (define2, parseXXX, the unused ::punk::args::TEST definition); the interactive Get_caller diagnostics and lib::tstr_test_one renamed with leading __ and unexported; internal parser/renderer helpers moved from the exported punk::args namespace into a new internal punk::args::private namespace (underscore prefixes dropped); every remaining exported command now carries a PUNKARGS definition, so i/punk::args::usage render documentation for the whole punk::args API (including punk::args::lib utilities and the helpers/argdocbase ANSI shorthands).

[0.4.12] - 2026-07-09

  • Tcl 9.1b0 runtime compatibility (first punk91.exe build on tclsfe-x64; the developed baseline remains Tcl 9.0.2):
    • punk::lib 0.3.1: TIP 746 removed lseq's expr-operand behaviour in Tcl 9.1 — punk::lib::range (lseq branch) now normalizes int[+-]int offset operands itself, so callers like range 0 [llength $list]-1 keep working (this broke punk::ansi::grepstr and with it example-block highlighting and the punk::args examples.test under 9.1). Also aligned the lseq branch with the tcl8 fallback contract: default by now infers direction (descending range 5 1 previously returned empty under tcl9 — silently breaking documented reverse-range callers) and by 0 returns an empty list (9.1's lseq ... by 0 changed to return one element). Direct lseq expression operands wrapped in expr (lzipn_tcl9b/lzipn_tcl9c/cols/cols2). check::has_tclbug_safeinterp_compile falls back to interp invokehidden tcl:unsupported:disassemble — Tcl 9.1 safe interps hide tcl::unsupported::* instead of exposing it.
    • punk::args 0.3.2: zero_based_posns expr-wraps its count-1 lseq operand (TIP 746).
    • New modules/punk/lib range.test pins the range contract (offset expressions, direction inference, by 0) under both 9.0 and 9.1.

[0.4.11] - 2026-07-09

  • punk::args 0.3.1: fixed helpers::example -title path calling bare [a] (resolvable only where a global a alias exists, e.g. punk shells — errored under plain tclsh); found by the new test coverage.
  • punk::args test suite grown to 128 tests across 15 files with four new characterization areas, added before any changes to the definition-parsing/indentation machinery (user-directed tests-first):
    • rendering.test (15): nesting independence (plain + tstr defs), relative-indent preservation (the 2-space help and 1-space choicelabel conventions, single and multiline), -unindentedfields (arg ✓; @cmd accepts-but-ignores — GAP pinned), constructed (string-built) definition absolute-indent characterization, multiline ${[cmd]}/${$var}/resolved_def insertions (aligned, nesting-independent), and @dynamic ${$DYN_X} double substitution (stable across resolutions, provider refresh honoured in help/choices/parse, textblock::frame-style art choicelabels byte-aligned — but multiline -help insertions lose insertion-column alignment for lines 2+, GAP pinned: the second-round subst lacks paramindent re-alignment).
    • choicegroups.test (5): group/-choices union parsing, cross-group prefixes, duplicate-entry dedup, per-group titled choice tables, and punk::imap4-style {\Deleted}/{$MDNSent} values with labels — plus a GAP pin: prefix-normalization list-quotes special-character choices (\De stores {\Deleted} where exact input stores plain \Deleted).
    • defquoting.test (3): container quoting rules pinned — braced values fully literal ($, [], two-char \n, bare backslashes), quoted values get Tcl backslash semantics (\n → newline, \\\) with $/[] still literal, and \$\{...\} renders a literal ${...} in tstr-processed blocks.
    • examples.test (6): helpers::example box structure/title/-tstr toggle (no-dedent direct-call contract pinned), ${[example ...]} insertion into @cmd help aligned with the auto Example: row, @examplespunk::args::eg with #<nodisplay>/@#<nodisplay> stripping (ANSI-tolerant), strip_nodisplay_lines unit, and a live tclcore ::lseq smoke (the heaviest example consumer).
  • Investigated punk::ansi::mark_columns first-call slowness (reproduced: 3.94s first call, 60µs thereafter): the argdoc -help contains ${[...num_columns_example]} which itself calls mark_columns, whose parse resolves the same still-resolving definition — the in-source TODO already documents the recursion hazard and candidate fixes (reentrancy guard, or deferring -help processing out of argument resolution, which would also help general first-parse performance). Recorded for goal consideration rather than patched.

[0.4.10] - 2026-07-08

  • G-040 completed (activated and flipped to achieved same day, user-directed): punk::args 0.3.0 adds -choicealiases {alias canonical ...} — aliases accepted exact under any -choiceprefix/-nocase setting, participating in prefix calculation when prefixing is on, always normalizing to the canonical choice in parse results; deny semantics apply to the matched name (a denied alias needs the full alias; a canonical reached via its alias is exempt from the canonical's own deny entry); usage display folds aliases into the canonical entry as an (alias: …) label note. The choice-word matching chain was extracted from get_dict into the shared resolver punk::args::choiceword_match, now also consumed by punk::ns 0.1.2's cmd_traverse — closing the doc-lookup parity gap (deny/reserve lists were honoured by parse but ignored by the walk; the pinned GAP tests flipped to agreement) and normalizing aliases before choiceinfo lookup.
  • punk 0.2.3: punk::help adopts the feature — i help lists one entry per registered topic (topics +alias help, tcl, env +alias environment, console +aliases term|terminal), and topic words accept aliases and unique prefixes with the user-decided minimum-prefix policy: h/he/hel, e/en, te/ter, and the reserved c/to/tc all fall through to command lookup. Argless help output remains byte-identical to the strict-80 baseline.
  • Suites: punk/args 98 pass + 1 skip (5 new alias tests incl. the punk::help policy matrix), punk/ns 28 pass (parity tests flipped, alias traverse + display-fold assertions), punk/lib 21 pass.

[0.4.9] - 2026-07-08

  • punk 0.2.2 (doc-only, from interactive review of the help restructure): i help / i help <topic> usage tables narrowed to reasonable widths (61-68 columns, previously ~160) by manually folding the helptopic argdoc help texts at ~70 columns and rendering the generated topic-choice grid with -choicecolumns 2. Only the argless help overview is strictly 80-column (unchanged, byte-identical); usage tables do not yet wrap to terminal width, so punk::args source line lengths directly set table width — automated (potentially language-dependent) wrapping, e.g. via tcllib's text-adjust facilities, is a possible future improvement.

[0.4.8] - 2026-07-08

  • G-037 completed (flipped to achieved): new make.tcl vfslibs step (also run inside make.tcl project) propagates declared vendored platform-library packages into kit vfs lib_tcl trees — declarations in src/runtime/vendorlib_vfs.toml (tomlish-parsed, per-package per-kit with explicit supersedes removal so no silent mixed-version provision; punkcheck provenance at src/vfs/.punkcheck, outside kit payloads; malformed entries fail the build naming the entry). G-024's mapvfs toml conversion was not required; the file is recorded as a candidate for absorption into it. Authority is the declaration — undeclared drift (e.g. the vendorlib/kit twapi divergence) is deliberately untouched.
  • 8.6 kits upgraded to tcludp 1.0.13 via the new step (the G-036 loose-end decision): the 1.0.13 folder is dual-generation (pkgIndex selects tcl9udp1013.dll or udp1013t.dll), so the single vendorlib_tcl9 source serves punk8win.vfs/lib_tcl8, replacing udp 1.0.12. Verified on rebuilt kits: punksys/punkbi (8.6.13) and punk902z (9.0.2) all load udp 1.0.13 from their vfs; no udp1.0.12 remains under src/vfs.

[0.4.7] - 2026-07-08

  • G-036 completed (flipped to achieved): punk::lib 0.3.0 adds punk::lib::check::has_libbug_udp_threadexit — version-based detection of the tcludp < 1.0.13 thread-exit bug on Tcl 9 Windows (the per-thread exit handler closes process-global event handles, silently freezing every other udp-using thread's event loop after any udp-loaded thread exits; root-caused and fixed-by-upgrade earlier in 0.4.3). has_libbug_* is the new check family for bundled/vendored library bugs; help tcl (punk 0.2.1) now scans it alongside has_tclbug_*, supports a full url reference key for non tcl-core trackers, and no longer errors on a triggered check carrying a reference without a description. Detection is loaded-version based, falling back to the best available registered version without loading the binary. New checkbugs.test covers the classifier matrix, the live check's dict shape/consistency, and a contract test over all existing check procs. Open decisions recorded in the G-036 detail: punk8win (8.6) kit's udp 1.0.12 swap; optional upstream tickets for residual tcludp trunk weaknesses.

[0.4.6] - 2026-07-08

  • punk::ns 0.1.1: five development trace puts removed from the command doc-lookup machinery — "PROC auto def"/"ENSEMBLE auto def" from generate_autodef were emitted on STDOUT and polluted i/s output in script/exec contexts (visible to agents piping i <cmd> per the G-015 pattern); "skipping to documented subcommand", "cmd_traverse ensembleparam" and the "cmd_traverse 10 ... review" fallthrough note were stderr noise on the space-form-id, ensemble-parameter and undocumented-tail traverse paths. No functional change.
  • punk/ns cmdflow.test: 8 new tests characterizing ensemble -parameters handling in the doc-lookup flow (the punk::netbox::man pattern — a leading apicontextid before the subcommand): generate_autodef models each parameter as a -ensembleparameter 1 leader with @leaders min/max = nparams+1 (single- and two-parameter fixtures), cmd_traverse consumes parameter words and resolves the subcommand's explicit or autodef docid (re-presenting the parameter in args_remaining for the subcommand's own leader parse, matching punk::netbox::man's explicit defs), nested sub-ensembles with their own -parameters re-consume the curried parameter at each level, parse treats -ensembleparameter leaders as ordinary named leaders, and cmdhelp renders a documented subcommand's usage through the parameter.

[0.4.5] - 2026-07-08

  • punk::args 0.2.3: fixed @opts -any 1 (arbitrary/adhoc option passthrough) — an option not present in the definition crashed parsing with "can't read argname" instead of passing through with its value (real consumers: vendored tomlish definitions declare -any 1); silenced a debug puts stderr that fired on every failed clause type assignment (visible on any multiform parse miss). Found while building the punk::args comprehensiveness pass.
  • punk::args test suite expanded (94 tests, was 71 at start of day): new forms.test characterizes multi-form (@form) parsing and pins the G-041 gaps — parse without -form is effectively form-0-only, -form rejects the documented list-of-forms usage, and the @form -synopsis override is stored but ignored by synopsis rendering; new validation.test covers the -type validation matrix, -range/-minsize/-maxsize, -nocase choice normalization, option -multiple accumulation, required-option enforcement, unknown-vs-adhoc option handling, the -- end-of-options marker, @values -max enforcement, received-key clause ordinals, solos, and default-vs-received distinction.

[0.4.4] - 2026-07-08

  • punk::args 0.2.2 (doc-only): the punk::args::define documentation for the -choice* fields now spells out the verified interplay semantics — -choicerestricted 0 passthrough of non-matching/ambiguous/denied/reserved words, -choiceprefix normalization of accepted prefixes to the canonical choice in parse results (with minimal-prefix highlighting in usage display), and the -choiceprefixreservelist phantom-entry idiom for per-choice minimum-prefix control. Characterization tests added (choices.test unrestricted-mode tests; new punk/ns cmdflow.test for the cmdwhich/cmdinfo/cmd_traverse docid flow, pinning the parse-vs-doc-walk deny/reserve divergence as GAP pending G-040).
  • help system restructured onto a topic registry (punk module 0.2.0, ::punk::helptopic): each topic (topics|help, tcl, env|environment, console|term|terminal) is a handler proc with its own punk::args definition, and the ::punk::help/::punk::help_chunks definitions are (re)generated from the registry — i help now renders a documented usage table with topic choices and summaries, and i help <topic> shows per-topic documented usage (previously an autogenerated stub). help topics is derived from the registry (lists all aliases, fits 80 columns). No-arg overview and command-fallthrough (help <cmdname>) output byte-identical to before; 80-column layout preserved; verified on both generations, script and shell subcommands. help env without an initialised punk::config (e.g. script contexts) degrades to a one-line notice instead of an error stack. The registry is the intended seam for future subshell-declared topics (punk::config-gated — not yet a goal).

[0.4.3] - 2026-07-08

  • vendored tcludp upgraded 1.0.12 -> 1.0.13 in the tcl9 kit vfs folders (punk9win.vfs, punk9win_for_tkruntime.vfs) and src/vendorlib_tcl9 — 1.0.12's Windows per-thread exit handler closed the process-global tcludp synchronization events, so the first udp-loaded worker thread to die froze every other udp-loaded thread's event loop (root cause of the G-036 wedge; fixed upstream in 1.0.13). Verified with the G-036 regression harness: run-2 syslog workers alive (baseline on 1.0.12: wedged 4/4). Note: punk8win.vfs still bundles udp 1.0.12 (8.6 appeared immune; pending decision). The manual vfs copy was required because libs/vfscommonupdate/project do not propagate vendorlib_tcl platform libraries into kit vfs lib_tcl trees — gap recorded as goal G-037.

[0.4.2] - 2026-07-08

  • piped-stdin exit/quit hang fixed (shellthread 1.6.3, shellfilter 0.2.4): repl/app teardown no longer blocks forever when a shellthread worker's event loop has wedged — unsubscribe's settings-reset send is now async, shutdown_free_threads keeps its timeout armed across all waits, and shellfilter::run honors its -syslog option (default empty -> no runtag log worker thread) instead of a hardcoded 127.0.0.1:514 debug leftover. Syslog remains supported when explicitly configured. Diagnosis and residual root-cause work tracked as goal G-036.

[0.4.1] - 2026-07-07

  • script subcommand now matches tclsh for GUI scripts: if the script leaves a registered Tk main loop (Tk loaded with a live main window), the event loop is serviced until the last window closes, instead of sourcing-then-exiting immediately. So a Tk script with no explicit exit (or one that exits from an after callback, like scriptlib/tktimer.tcl) stays alive and runs — previously it flashed and died, and shell was needed as a workaround (relevant to G-020 GUI automation). Console scripts are unaffected; a script that errors exits at once (no hanging window). Verified on both generations.

[0.4.0] - 2026-07-07

  • script subcommand supports lib:<name> scriptlib scripts (with or without .tcl extension), matching the shell subcommand's scheme: punkexe script lib:hello, or bare punkexe lib:hello via reclassification. The prefix always wins — a literal path beginning lib: (pathological; illegal on Windows filesystems) is reachable via ./lib:.... Not-found errors list the searched locations. Only .tcl runs via the script subcommand.
  • punk::path 0.2.2: new scriptlib_resolve — the shared lib: resolution policy (kit-internal app/scriptlib first and not externally overridable, then scriptlib dirs relative to the executable), PUNKARGS-documented. app-punkshell still carries its inline copy of the policy (refactor onto the shared proc noted as todo).

[0.3.1] - 2026-07-07

  • script subcommand: core-command documentation parity with the interactive shell — app-punkscript now loads punk::args::moduledoc::tclcore (catch-guarded, ~40ms) so e.g. 'i list' | punkexe script renders the doc table instead of "Undocumented command". Verified on both generations; kit startup ~0.33s.
  • punk::packagepreference 0.1.1: the moduledoc auto-load success notice moved from stdout to stderr — stdout must stay clean for script/exec contexts (the failure branch already used stderr).

[0.3.0] - 2026-07-07

  • <punkexe> script completed (goal G-015 achieved): runs a script file (script <file> ?args?, conventional ::argv0/::argv) or the whole of piped stdin (<commands> | <punkexe> script — no trailing exit needed) in the default punk shell module/alias environment, so one-liners like dev projects.work *name* work with no boilerplate. Honest exit codes (0 success, 1 error with errorInfo on stderr, script's own exit honoured); no shellfilter transforms or logging side effects; never falls into an interactive shell. Implemented as the lean app-punkscript package; the stdin form echoes the script's final result when non-empty. Verified on both Tcl generations (punk902z, punksys).

[0.2.7] - 2026-07-07

  • vendored tomlish 1.1.10: the library API now carries punk::args (PUNKARGS) documentation (from_toml, to_dict, from_dict, to_toml, update_tomlish_from_dict) — the G-014 tomlish precondition is met (documented upstream, re-vendored from a clean checkout); plus the explicit tomlish::cmdline_main entry point.
  • _vfscommon.vfs kit payload refreshed to the current built modules: shellfilter 0.2.3, shellrun 0.1.4, punkboot::utils 0.1.1, punk::console 0.7.1 content catch-up, tomlish 1.1.10.

[0.2.6] - 2026-07-06

  • shellfilter 0.2.3: shellfilter::run now guarantees tee-stack removal (stdout/stderr restoration) via try/finally even when its body errors, and the decorative stack-status table rendering in log::critical blocks is catch-guarded. Previously an error there (observed: a stale same-version textblock snapshot calling the new punk::ansi sgr_merge_singles with old option syntax) aborted the run between channel diversion and restoration, leaving the process's stdout/stderr broken and all subsequent output silently lost.
  • runtests.tcl: testinterp tm path order fixed so the bootsupport snapshot wins same-version module ties over vendormodules (verified rule on Tcl 9.0.3, standard and punk::libunknown scanners: tcl::tm::add prepends, head of tcl::tm::list wins ties, so the last test_tmlist element wins); testinterp auto_path gains the parent of [info library] so binary packages such as Thread resolve in projects without a root lib_tcl<N>/<arch> payload.

[0.2.5] - 2026-07-06

  • make.tcl vendorupdate now checks each vendor source project's fossil/git checkout state and warns (non-fatal, once per VCS root) when pulling from a dirty tree — vendored artifacts built from uncommitted source have no committed provenance. Enforcement policy (abort/override, bootsupport coverage) tracked by goal G-026.
  • punkboot::utils 0.1.1: the dirty-checkout check lives in the module as vcs_dirty_warnings (make.tcl calls it via a guarded lazy require and degrades to skipped if the bootsupport snapshot lacks it); bootsupport snapshots refreshed (punkboot::utils 0.1.1, shellrun 0.1.4, punk::console 0.7.1 content catch-up).

[0.2.4] - 2026-07-06

  • shellrun 0.1.4: added missing package require punk::args (the 0.1.3 migration left runx/run/runout/runerr calling punk::args::parse without requiring it, breaking shellrun in bare interps — including the src/tests/runtests.tcl testinterp, which made every source-tree test run fail).

[0.2.3] - 2026-07-06

  • shellrun: removed -tcl from sh_run, sh_runout, sh_runerr, sh_runx (was silently swallowed with no useful effect because sh -c is always an external shell; now rejected with a usage message).
  • shellrun: migrated runx from the legacy get_run_opts parser to punk::args::parse with a full PUNKARGS spec; runx now honours -debug and --timeout= (previously accepted but silently ignored).
  • shellrun: expanded PUNKARGS documentation for run, runconsole, runout, runerr, and runx with @cmd metadata and -help text on all opts/values.
  • shellrun: migrated sh_run, sh_runout, sh_runerr, sh_runx from get_run_opts to punk::args::parse with dedicated PUNKARGS specs.
  • shellrun: removed the internal get_run_opts proc; all callers now use punk::args.

[0.2.2] - 2026-07-06

  • punk::console: terminal queries fired while an 8.6-based shell waits at an idle line-mode prompt now fail fast with a discriminable errorcode (PUNK CONSOLE QUERY HOSTAGE_COOKED_READ) and emit nothing, instead of timing out (~500ms) and later corrupting input with the swallowed response (idle-reader hostage guard; raw mode and mid-command queries unaffected). Owner-routed queries preserve the owner-side errorcode.

[0.2.1] - 2026-07-06

  • make.tcl projectversion: new advisory subcommand verifying CHANGELOG.md matches punkproject.toml and warning if src/ has commits since the last project-version bump.
  • Clarified project versioning policy: the make.tcl command interface is part of the product surface.

[0.2.0] - 2026-07-05

  • Initial tracking of the punkshell project version in punkproject.toml.