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.
 
 
 
 
 
 

64 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.35] - 2026-07-14

  • punk::ansi 0.1.3 (documentation-only): grepstr's -return summarydict help corrected - the summary dict's linemap key is always present (the old text claimed it appeared only with -n; the always-present behaviour is pinned in ansi/grepstr.test). This was the doc/behaviour reconciliation deferred from the grepstr characterization wave to the punk::ns hygiene pass.

[0.12.34] - 2026-07-14

  • punk::ns 0.7.0/0.7.1 comment/documentation hygiene pass + pinned-wart fixes: ~1200 lines of dead code removed (the fully commented-out arginfo predecessor of cmdhelp, the never-exported name-primitive twins nsparts1/nsprefix1/nsprefix_orig/nstail1/nstail_orig whose divergence was pinned before removal, obsolete nsglob_as_re1, empty stubs, misc commented remnants); stale docs corrected (nsprefix :::a comment, nsglob_as_re 'should be fixed' note, nstree_list empty PUNKARGS help, cmdhelp/corp help typos). Shell-visible fixes (0.7.1, pins flipped): bare nslist (no -types) now displays all member types instead of erroring with a malformed literal-$known_types message; nsjoinall's absolute-path error is now prefixed 'nsjoinall:' (was 'nsjoin:'); a development trace puts removed from nscommands' weird-namespace path. Flagged unchanged: get_nslist's apparently-unreachable alias display branches, superseded nscommands1/nscommands2 aliases, cmdtrace output noise (deferred to proposed G-085).

[0.12.33] - 2026-07-14

  • punk::repl 0.5.2: fixed the codethread seeding template creating a stray namespace named after the ::punk::nav::ns::ns_current variable in every code interp (a phantom 'ns_current' child visible when browsing the nav namespace with n/). Subshell namespace carry-over semantics unchanged. Plus n/ n// n/// display-and-navigation characterization groundwork for the planned punk-tables/width-responsive rework: new punk/ns nslist.test (classification buckets as machine contract, per-element marking pins, REWORK-flagged layout pins, bare -types quirk), new punk/nav/ns navns.test (navigation state machine + ns_current contract), new punk/repl nscurrent.test (real-codethread inscope evaluation, retention, navigation, auto-create, seeding-fix guard).

[0.12.32] - 2026-07-14

  • punk::lib 0.5.0: new punk::lib::check::has_tclbug_nestedswitch_tracelines (+ pure signature classifier) - live behavioural probe of the upstream nested-switch trace-line mis-attribution (tcl tktview 5d5b1052280c976ea3d4), surfaced in the 'help tcl' warning report (level medium) alongside the existing has_tclbug_* checks. No version gate: the probe matches the characterized wrong/right arm signature, so it flips automatically on a fixed Tcl runtime; a fixed-canary test in ns/cmdtrace.test then fails first, triggering the documented followup (flip GAP pins, update cmdtrace argdoc caveat, record fixed-in version).

[0.12.31] - 2026-07-14

  • punk::ns 0.6.0: cmdtrace gains -pause 0 for non-interactive use (bypasses the enter-key pause so the marked-up traced-body report can be captured by scripts/tests). The nested-switch line-mismark was characterized with a punk-free minimal repro (identical on Tcl 8.6.17/8.7a6/9.0.3) confirming the bug upstream (core.tcl-lang.org tktview 5d5b1052280c976ea3d4): arm bodies whose split-list index lands on a literal word of the switch command report container-relative lines; new ns/cmdtrace.test pins correct flat/2-word-form marking and GAP-pins the upstream mismarks; cmdtrace argdoc caveat updated with the ticket and pattern.

[0.12.30] - 2026-07-14

  • punk::args 0.12.3: fixed the stringstartswith tail-clause reservation bug flagged in the 0.12.2 comment review - the multi-member tail-clause walk in get_dict_can_assign_value compared the prefix against the type string instead of the candidate value, so an optional trailing clause like {literal(with) stringstartswith(v)} lost its matching words to a preceding -multiple argument, and certain prefix spellings caused spurious "Received more values than can be assigned" errors. Characterized pre-fix, pin flipped (allocation.test), guards added for the literal-only and no-match cases.

[0.12.29] - 2026-07-14

  • punk::args 0.12.2 comment/documentation hygiene pass (no behaviour change): ~1100 lines of superseded commented-out code removed (old check_clausecolumn, abandoned _check_clausecolumn2 experiment with its error-collection idea preserved as a note for G-072-era rework, pre-parsekey ordering loop, disabled switch arm, debug remnants); MAINTENANCE loop-parity comments upgraded to a dated refactor assessment (shared-helper extraction deferred to ride G-084 under G-046 hot-path constraints); user-visible doc fixes (get_dict return-shape and directive lists corrected, false solo-flag/last-value-only claims removed, two broken doc examples fixed); goal cross-refs (G-053, G-084) annotated at the relevant code sites; a suspected latent bug in the multi-member clause stringstartswith( arm flagged in a comment (matches the type string instead of the value) without changing behaviour.

[0.12.28] - 2026-07-14

  • G-082 (achieved): punk::args 0.12.1 single-form parse error selection - a word rejected by an optional argument's allocation screen (restricted choices, or the basic int/double/bool/number/dict type screen) that then overflows the argument list now reports the specific rejection (choiceviolation naming the word and allowed choices, or typemismatch naming the type, with -badarg/-badval) instead of the generic "Received more values than can be assigned" overflow - restoring the 0.5.0-era pointedness for optional choice-restricted dispatch shapes (shell-visible in usage errors from punk::args-parsed commands). Genuinely-surplus words still report toomanyarguments; multiform selection unchanged. New errorselection.test (pre-fix behaviour characterized first, pins flipped deliberately); the make.tcl -optional 0 authoring workaround is no longer needed on fixed versions (src/modules/AGENTS.md guideline re-documented; make.tcl keeps it while running against the bootsupport 0.12.0 snapshot).
  • Also: punk::args goals G-083 (argument relations: strict mutual exclusivity, parsekey-group integrity) and G-084 (-parsekey completeness) proposed, with parsekey characterization tests (mash/prefix/shared-default/collision pins + dev known-bug pins) landed alongside.

[0.12.27] - 2026-07-14

  • make.tcl shell under a built punk executable: fixed missing prompts and the raw-mode 'invalid command name struct::set' error. Both stemmed from the kit's script-mode boot pre-loading the punk stack: (1) app-punkscript correctly forces ::tcl_interactive 0 for script runs, and since punk::repl was already loaded its load-time interactivity probe never re-ran - the shell branch now recomputes ::tcl_interactive via punk::repl::is_interactive against the real input channel before repl::start; (2) the accelerator-reload block (package forget + command destroy of sha1/md5/struct::*) relied on later package-require chains to restore the packages, which never re-fire when consumers (punk::lib, punk::du, flagfilter etc) were pre-loaded at kit boot - the block now records what was actually loaded and re-requires it immediately (verified: repl-thread interp state now identical under tclsh and punk91). src/AGENTS.md gains a "pre-loaded interp, not a virgin one" note covering the class: interp surgery and load-time-state assumptions in make.tcl must restore deliberately and be tested under both tclsh and a punk exe (includes the kit-vs-bootsupport module provenance-mixing caveat).

[0.12.26] - 2026-07-14

  • make.tcl under a built punk executable: kit builds gain a self-build guard - the kit whose deployed executable is running the build is skipped with a clear warning (previously the pre-deploy process sweep would taskkill the build's own process mid-run with -k, since it matched processes by executable name only; without -k the polite kill's failure was the only thing saving the run). The sweep now also excludes the build's own pid unconditionally (covers a same-named copy driving the build from a non-deploy path). Informational/update subcommands were already safe (they exit before the kit machinery); building other kits from a punk exe remains supported. Also quietened the 'punk::libunknown::init already done - unnecessary call?' stderr diagnostic when a punk exe runs make.tcl: make.tcl now leaves an already-active libunknown in place instead of re-sourcing the bootsupport copy over it and tripping init's rename guard. src/AGENTS.md build guidance updated.

[0.12.25] - 2026-07-14

  • G-030 follow-up (user review): make.tcl's constructed punk::args definitions adopt the G-045 authoring mechanisms - @cmd -help bodies converted to block-form values with a bare @normalize per definition, fixing the constructed-definition indent leak (first Description line rendered less indented than continuations; the braced option fragments never leaked because literal block-shaped parts get file-style normalization). Added a define-time capability probe (get_spec on representative ids) so a stale punk::args that accepts the text but cannot resolve a mechanism degrades to the plain fallback immediately. AGENTS infrastructure for future documentation work: new "punk::args definition authoring ergonomics" subsection in src/modules/AGENTS.md (constructed-def @normalize + block form, -unindentedfields, -& record continuation, container quoting rules, explicit @form -synopsis for script-level ids, the optional-choice error-quality workaround), cross-referenced from src/AGENTS.md with ::punkboot::argdoc named as the in-tree exemplar. Layout make.tcl copies followed via the punkcheck channel.

[0.12.24] - 2026-07-14

  • G-030 (achieved): make.tcl dogfoods punk::args. All 15 subcommands are punk::args-declared ((script)::punkboot definitions with single-source summaries, shared option fragments and explicit @form -synopsis lines): bare make.tcl/-help render tabled usage with grouped subcommand summaries, make.tcl help ?subcommand? / <subcommand> -help show per-subcommand definitions, invalid flags and unknown subcommands raise punk::args usage errors (exit 1) with unambiguous-prefix resolution. New -confirm 0|1 prompt policy on every confirmation point (bootsupport minor-staleness gate, vfscommonupdate REPLACE, kit-type mismatch): default prompts only on an interactive terminal and aborts fast with guidance on non-interactive stdin (the piped-y agent workflow is retired - use -confirm 0; the old vfscommonupdate decline half-abort now exits 1). punk::args joined the bootstrap-tracked staleness set (parsing contract only - the punk::ansi/textblock rendering stack degrades instead: minimal errorstyle/plain help when unhealthy, and full scan-based fallback dispatch when punk::args itself is unavailable; PUNKBOOT_PLAIN=1 forces the degraded mode). Bootsupport snapshot refreshed (args 0.5.0->0.12.0 plus punk/lib/ns/repl/tclcore moduledoc) and layout make.tcl/bootsupport copies followed via the punkcheck channel. Docs: src/AGENTS.md, src/bootsupport/AGENTS.md, src/modules/AGENTS.md, src/tests/shell/AGENTS.md. Dogfooding finding recorded in the goal file: punk::args 0.12.0 reports a generic overflow error where 0.5.0 reported a pointed choiceviolation for optional-choice mismatches (worked around with required leaders; candidate punk::args error-selection improvement).
  • Also since 0.12.23 (landed before this version's bump, entry added retrospectively 2026-07-14): punk::args -> doctools and punk-native HTML/Markdown converter prototypes under src/scriptapps/tools (punkargs_to_doctools.tcl, punkargs_punknative.tcl); vendored punkdoc-mono web font (OFL subset of Cascadia Mono 2404.23) with reproducible fontprep builds and -assets embed|link|none in the punknative generator; punknative generator refinements (nav index, per-form arg tables, terminal-black backdrop, integer row pitch, settled ansi-art html rendering recipe). Goals G-078..G-081 drafted (punk::ansi->html api, default-colour semantics, cell-grid rendering mode, argdoc build pipeline).

[0.12.23] - 2026-07-13

  • Restored dev doc.validate: tcllib dtplite wrapped as the generated polyglot bin/dtplite.cmd (multishell scriptset: src/scriptapps/dtplite.tcl + dtplite_wrap.toml, LF-only payload; falls back to the project-vendored tcllib under src/vendorlib_tcl9/ when the invoking tclsh lacks the dtplite package). Previously the repl unknown-handler's auto_execok found no dtplite executable ("invalid command name dtplite" - only the legacy misnamed bin/dtplite_run.bat existed). New src/tests/shell/testsuites/binscripts/dtplite.test pins the artifact (LF-only, checkfile-clean, byte-identical round-trip re-wrap) and exercises usage-error/validate/html usecases. Verified: 'dev doc.validate' validates all 64 src/doc .man files clean. The doctools pipeline remains interim - punk::args is intended to become the documentation source of truth. (Entry added retrospectively 2026-07-14; the version bump landed in the original commit without one.)

[0.12.22] - 2026-07-13

  • G-074 (achieved): punk::args 0.12.0 adds punk::args::formcheck - on-demand multiform ambiguity analysis. It reports the form pairs of a definition that some argument list could cleanly match simultaneously, confirming every candidate with a real parse of a synthetic witness arglist against both forms - so fully discriminated form pairs can never false-alarm, and each reported witness is a genuine multipleformmatches input. Findings classify as type-weakness (a literal/choice discriminator aligned with a permissive non-validating type such as expr/any/string - the 'lseq 1 count 5' class) vs structural (the forms genuinely share an argument shape - the 'after cancel id|script' class). The new @form -overlapallowed key sanctions a known/documented overlap for formcheck reporting only (parse behaviour untouched; unknown form names rejected at definition resolve); tclcore moduledoc 0.3.4 adopts it for the after cancel pair, leaving ::after with zero unsanctioned findings while ::lseq's expr-typed-end findings stay visible as actionable. New testsuite args/formcheck.test.

[0.12.21] - 2026-07-13

  • G-076 (new goal, active): 'help tcl' now warns about the tcl9 dead-console defect (upstream ticket f10d91c2d3, root-caused in G-039: a dead console is never delivered to the script as a fileevent while the core's console reader thread busy-loops) via punk::lib 0.4.3's has_tclbug_console_deadspin — version-based detection through the pure classifier tclbug_console_deadspin_applies, gated by check::tclbug_console_deadspin_fixed_in (empty until a released Tcl contains the upstream fix verified by re-running the G-039 kill procedure). punk::repl 0.5.1 arms the dead-console watchdog only when that same check reports the runtime affected, so recording the fixed release once silences the warning and stops arming the watchdog together. Buginfo dicts gain a mitigated/mitigation axis orthogonal to level (punk 0.2.6 renders it): the deadspin warning keeps severity major but displays "(mitigated)" in subdued grey with the watchdog's scope described when punk::repl >= 0.5.0 is available to the runtime; non-repl console reads remain exposed and unmitigated warnings render unchanged.

[0.12.20] - 2026-07-13

  • tclcore moduledoc 0.3.3: removed the unnecessary @dynamic tags from the split, array and join definitions - no bad-@dynamic warnings remain anywhere in the module, and the three definitions now cache their display expansion like the rest instead of re-expanding per render.

[0.12.19] - 2026-07-13

  • punk::args 0.11.2: the "bad @dynamic tag" warning now emits once per definition instead of on every resolve ('i join' emitted it 4x, user-reported) - the underlying inefficiency fixed: parse-inert @dynamic definitions now cache their round-1 resolution like legitimately dynamic ones instead of redoing the full text substitution on every resolve. The warning wording now notes @dynamic still forces display-field re-expansion per render for such definitions. tclcore moduledoc 0.3.2: fixed the malformed ::tcl_startOfNextWord definition (unescaped quotes in its embedded man-page example prevented it resolving at all - 'i tcl_startOfNextWord' now works), found by sweeping all 462 registered ids; the sweep identified ::split, ::array and ::join as the parse-inert @dynamic carriers.

[0.12.18] - 2026-07-13

  • tclcore moduledoc 0.3.1 (authoring-style only): the after id-shape harvest is consumed via tstr placeholders with the variable in the argdoc namespace (the defspace), replacing the interim string-map token - the module now showcases the neater placeholder style documented in punk::args 0.11.1, with string map reserved for when build-time substitution is genuinely necessary. Behaviour unchanged.

[0.12.17] - 2026-07-13

  • punk::args 0.11.1 (documentation-only): the define help now documents the two definition-registration styles (direct define vs lazy PUNKARGS/register::NAMESPACES registration used by module templates and moduledocs) and the tstr interpolation rules - display-field deferral, parse-field expansion at first resolve, the defspace rule (argdoc child namespace wins when present), the silent-literal fallback for unresolvable placeholders, and the safe patterns for load-time-computed values.

[0.12.16] - 2026-07-13

  • tclcore moduledoc 0.3.0: 'after cancel ' and 'after info ' now discriminate by the after-id shape, harvested from the running interpreter at load time (user-directed). 'i after cancel someid' resolves cleanly to the cancel-script form exactly as real Tcl treats it (silent script-match no-op), and only genuinely id-shaped words ('after#N') report the cancelid/cancelscript ambiguity - the junction real Tcl itself resolves by id liveness at runtime. Parity pins added (tclcoreparity.test) including the accepted dead-id over-acceptance boundary.

[0.12.15] - 2026-07-13

  • G-041 doc surface: the help system presents the command form matching the supplied words - 'i after cancel ' presents the cancel form's argument table (candidates are named when no form or several forms match, e.g 'after cancel someid' reports the genuine cancelid/cancelscript ambiguity of the documented forms), and 's after cancel someid' underlines the matching synopsis line(s) (punk::ns 0.5.0). punk::args 0.11.0: the documented @form -synopsis override now renders in synopsis output, and candidate-form ranking recognises -choices discriminators (the tclcore models' subcommand words) via the shared choice resolver.

[0.12.14] - 2026-07-13

  • punk::args 0.10.0 (G-041 increment): multi-form argument definitions now parse by automated form selection - punk::args::parse without -form attempts every form and auto-selects the one that cleanly matches ('lseq'-style multiform commands no longer fail with the first form's error when the arguments fit a later form). No matching form raises an error naming each candidate form's failure (best candidate first); arguments matching several forms raise an error naming them, with -form (which now accepts the documented list of form names/indices) restricting to the intended form. Parse results and parse_status report the selected form and every candidate's status ('form'/'formstatus' keys).

[0.12.13] - 2026-07-13

  • G-051 achieved: punk::ns 0.4.0 - the help system's doc walk now accepts the same choice-word abbreviations parsing accepts: 'i string is tr' resolves to the 'string is true' documentation exactly as 'string is tr 1' executes (unique prefixes, aliases, nocase; ambiguous/denied/unknown words stay at the parent exactly when parse rejects them). cmdinfo also reports the truthful cmdtype 'doconly' (was 'notfound') for documentation-only levels such as 'string is ' and documented TclOO method docids. punk::lib 0.4.1 adapts its script analysis to the new value with identical behaviour.

[0.12.12] - 2026-07-12

  • punk::ns 0.3.0: 'i ' 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.

[0.12.10] - 2026-07-12

  • punk::args 0.8.3 (G-071 increment): silenced four more unconditional debug lines that printed to stderr during normal argument parsing whenever an optional element was skipped (visible when using 'i'/help display against commands modelled with noise-word arguments such as if and lseq). New allocation characterization testsuite pins the optional-element mis-allocation ('lseq 0 10 2'-class failures) as GAP tests ahead of the allocator fix.

[0.12.9] - 2026-07-12

  • punk::args 0.8.2: fixed stray debug output ("checking tp ... against value ...") printed to the console when parsing multi-element clause arguments (e.g. 'i try ...' style usage against the tclcore moduledoc). Found during G-041 prework probing of if/switch/try/lseq real-vs-model divergence; findings recorded in the G-041 and G-055 goal detail files.

[0.12.8] - 2026-07-12

  • G-045 achieved: punk::args 0.8.1 documents the definition container quoting rules in the punk::args::define help (braced values fully literal; double-quoted values with Tcl backslash semantics at record parse while $ and [] stay literal; the backslash-escaped tstr placeholder idiom). This completes the definition authoring ergonomics goal: @cmd -unindentedfields honoured (0.6.1), -& record continuation (0.7.0), @normalize block-form indent normalization with the help-system definitions as consumer proof (0.8.0 / punk 0.2.5), quoting documentation (0.8.1).

[0.12.7] - 2026-07-12

  • G-045 (increment): punk::args 0.8.0 adds the bare @normalize directive - opts a definition into indent normalization of block-form multi-line field values (structural leading newline dropped, content re-based to the file-style 4-space continuation convention, relative indents preserved, -unindentedfields exempt, no-op on conforming file-style definitions). Intended for constructed (string-built) definitions. punk 0.2.5: the help-system definitions (::punk::help / help_chunks) convert to indented block authoring under @normalize; 'i help' rendering unchanged.

[0.12.6] - 2026-07-12

  • G-045 (increment): punk::args 0.7.0 adds the -& record-continuation token - an unquoted trailing -& on a definition record line continues the record on the next line, assembling byte-identically to the equivalent backslash continuation. Intended for constructed (string-built) definitions, where backslash-newline is consumed by the building code's own quoting. Brace a literal trailing -& value ({-&}); -& elsewhere on a line or inside braced/quoted multi-line values is ordinary data. Backslash-continuation authoring is unchanged.

[0.12.5] - 2026-07-12

  • G-045 (increment): 'i help' usage table alignment fixed (punk 0.2.4) - the Description block's continuations no longer render indented +12 relative to the first line, and the topic argument's help first line no longer renders +4 relative to its continuations. ::punk::helptopic::define_docs authors help text at the left margin with -unindentedfields {-help} on the @cmd and topic lines. Help text content unchanged.

[0.12.4] - 2026-07-12

  • G-045 (increment): punk::args 0.6.1 - the @cmd directive now honours -unindentedfields for -help, so command help authored at the left margin renders its first line flush with continuations in help/usage displays (previously the option was accepted on @cmd but ignored). No shipped definitions used it yet, so existing help rendering is unchanged; the define documentation states where -unindentedfields is valid.

[0.12.3] - 2026-07-12

  • punk::args 0.6.0 synced into the common vfs payload (_vfscommon.vfs): help/usage synopses render small restricted choice sets as literal alternates (module change committed earlier as c309ed47; this ships it in built kits).

[0.12.2] - 2026-07-12

  • G-039 fix: an interactive shell orphaned by its hosting console dying (killed conhost/terminal) previously spun ~2 CPU cores forever — the Tcl 9 windows console driver never delivers the dead-console state to the script level as a fileevent (tclWinConsole.c ConsoleEventProc only notifies on buffered data) while its reader thread busy-loops on the persistent channel error. punk::repl 0.5.0 adds repl::console_watchdog, a 5s liveness poll (read-only GetConsoleMode via chan configure -inputmode) armed only for a tcl9 console input channel on the process-default console on windows: on a dead console it closes the input channel (stopping the driver's reader thread) and finishes the repl via the normal eof path, so the orphan exits cleanly within seconds. Piped, foreign-console and tcl 8.6 inputs are unaffected.

[0.12.1] - 2026-07-11

  • G-062 achieved: canonical project license declared as BSD-2-Clause. LICENSE.txt added at the repo root with the standard BSD-2-Clause text (copyright Julian Marcel Noble, 2023-2026); README.md names BSD-2-Clause and points at LICENSE.txt; root AGENTS.md Repo-wide Notes names the license precisely; punkproject.toml [project] carries license = "BSD-2-Clause". Repo-sweep found no top-level license claims contradicting it (vendored library licenses and module-level generated docs are not project-level claims).

[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.