Tree:
17b8a6dbbd
master
v0.1a
${ noResults }
364 Commits (17b8a6dbbdfea3d7fd2ac9cb21c3896c1e282a4a)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
17b8a6dbbd |
G-071 increment 1: allocation characterization suite + retreat-path debug silencing (punk::args 0.8.3, project 0.12.10)
G-071 flipped proposed -> active (user direction 2026-07-12).
New allocation.test (7 tests) with reduced fixtures isolating the failing
shape from the tclcore moduledoc: the lseq-range shape (start ?sep? end
?by-step clause?) reproduces the moduledoc failures exactly. Current
mis-allocation pinned as GAP tests ("1 2 3" -> invalid blaming sep,
"1 2 by 3" -> incomplete blaming end, "1 2 3 4" correctly invalid but
misblaming sep), noise-word variants and the if-shape noise-word clauses
pinned as regression guards, parse_status -form absence pinned as GAP.
Also silenced four more unconditional debug puts on get_dict allocation
retreat paths ((111)/(222)/(333)/(444)) - these printed to stderr during
NORMAL successful parses at every optional-skip retreat, polluting
interactive help/parse output for noise-word-modelled commands. Behaviour
unchanged; the retreat logic they marked is exactly this goal fix target.
Full punk::args suite 193 pass / 1 pre-existing skip / 0 fail (tclsh
9.0.3).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
58da288d45 |
G-041 prework: if/switch/try/lseq real-vs-model probe findings recorded; punk::args 0.8.2 debug-leak fix (project 0.12.9)
Probing (punk902z kit, Tcl 9.0.2) of the tclcore moduledoc models against the real builtins, driven by user concerns about variable-length clauses with optional elements before G-041 activation. Findings recorded in the G-041 detail file (auto-selection evidence on real commands, the allocator prerequisite, parse_status -form gap) and the G-055 detail file (modelability over-acceptance list: try compound handler types, reserved-word clause allocation, "-" fallthrough constraints, switch two-argument option suppression, unvalidated -type expr, TIP 746 version-conditionality for lseq operands; plus the user doc-direction guidance that definitions split into @form entries where source docs simplify). Key result: the per-form models are doc-faithful (lseq.n synopsis maps 1:1; switch separate/block parse correctly under explicit -form; try mixed on/trap interleaving and finally positioning all agree with the real command) - but the value allocator mishandles an optional single-word choice value followed by a required value plus trailing optional-member clause, so lseq range arglists without the ../to noise word ("0 10 2", "0 10 by 2") fail in-form. No lseq form accepts them, so G-041 form selection alone cannot fix "i lseq 0 10 2" - allocator fix flagged as a candidate prerequisite goal. Fix included (punk::args 0.8.2): unconditional debug puts on the clause type-check path (get_dict_can_assign_value) commented, companion to the 0.2.3 find. Full punk::args suite 186 pass / 1 pre-existing skip / 0 fail. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
66df76c82e |
G-045 achieved: punk::args 0.8.1 define quoting documentation; flip + archival edits (project 0.12.8)
Increment 5 (final): the container quoting rules pinned by defquoting.test now appear in the punk::args::define -help documentation - braced values fully literal (backslash sequences survive as typed); double-quoted values get Tcl backslash semantics at record parse while $ and [] stay literal with no substitution outside tstr placeholders; the backslash-escaped placeholder idiom renders a literal placeholder. Rendered section verified in punk902z src (meta-escapes display correctly). punk::args suite 186 pass / 1 pre-existing skip / 0 fail. Acceptance review recorded in the detail file: all criteria satisfied across increments 1-5 (@cmd -unindentedfields 0.6.1, i help alignment punk 0.2.4, -& record continuation 0.7.0, @normalize + define_docs consumer proof 0.8.0/punk 0.2.5, quoting documentation 0.8.1; suite grown 128 -> 187 tests, GAPs flipped, none weakened, full source-tree suite zero regressions). Flip edits: G-045 index entry moved to GOALS-archive.md (achieved 2026-07-12), detail file Status flipped with evidence in Progress, reference sweep updates G-053 notes. The detail file move to goals/archive/ follows in the next commit as a pure rename (per the goals/AGENTS.md archive rules) - goals_lint is transiently unclean between the two. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
22606faebe |
G-045 increment 4: punk::args 0.8.0 @normalize directive; define_docs converts as consumer proof (project 0.12.7)
New bare @normalize directive: opts a definition into indent normalization of BLOCK-FORM multi-line field values (first line whitespace-only, as authored by opening a braced literal with a newline). The structural first newline and a whitespace-only trailing line are dropped, the content lines' common leading whitespace is the block's base indent, the first content line is unindented fully and subsequent lines are re-based to the standard 4-space continuation convention (deeper relative indents preserved; whitespace-only inner lines become empty). Fields in a record's -unindentedfields are exempt. Implemented as a resolve pre-pass over the split records (private::normalize_records / rebase_multiline_value); @normalize with options is an error. Head-form values are never altered - their base indent is unknowable (continuations uniformly at 6 may be base-4 with the deliberate +2 relative convention, or base-6 flush; re-basing would flatten the former). The idempotence test caught exactly that on a file-style definition during implementation, narrowing the user-confirmed re-base semantics to block form only - which also makes @normalize a proven no-op on conforming file-style definitions. Consumer proof (punk 0.2.5, per the recorded user decision): ::punk::helptopic::define_docs converts from interim left-margin authoring to indented block-form values under @normalize, dropping its -unindentedfields declarations; 'i help' and 'i help_chunks' verified aligned in punk902z src, including the blank-line separator in the combined basehelp+extra block. Tests: new normalize.test (5 tests: block re-base, block left-margin, head-form boundary, exemption byte-exactness, file-style idempotence); rendering.test P4 characterization stays pinned as the deliberate unopted default with its text updated to reference @normalize. punk::args suite 186 pass / 1 pre-existing skip / 0 fail; punk::ns 53/53; full source-tree suite 806 pass / 13 skip / 1 fail = exec-14.3 only (known baseline) - zero regressions (tclsh 9.0.3). define doc documents the directive. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
52ad1211a2 |
G-045 increment 3: punk::args 0.7.0 - record-continuation token -& (project 0.12.6)
An unquoted trailing -& element on a definition record line continues the
record on the next line. Implemented in
private::split_definition_records: the token is dropped and the next line
joins after a single space with its leading whitespace collapsed - exactly
how the Tcl parser joins backslash-newline continuations before a braced
definition ever reaches the splitter - so a -& record assembles
byte-identical to its backslash-continued equivalent. Motivation:
constructed (string-built) definitions cannot author backslash-newline
ergonomically (the building code's own quoting consumes it); -& is plain
text and survives any construction.
Collision rules (analysis and decision recorded in the goal detail file):
bare word preceded by whitespace (or whole line), trailing whitespace
tolerated; braced/quoted -& is data ({-&} escapes a literal trailing
value); mid-line -&, word-suffix abc-&, and -& inside still-open
braced/quoted values are data. Element-count disambiguation rejected
(action-at-a-distance; positional rule is locally decidable). Backslash
authoring unchanged - continuation is additive.
Tests: new recordcontinuation.test (6 tests) incl. backslash-twin
parse+render byte-equality and the constructed-def chaining case. Full
punk::args suite 181 pass / 1 pre-existing skip / 0 fail; full source-tree
suite 801 pass / 13 skip / 1 fail = exec-14.3 only (known baseline) - zero
regressions (tclsh 9.0.3). define doc documents -& alongside backslash
continuation.
Also recorded: tclparser considered and rejected for the splitter (ANSI
unbalanced-bracket data, dialect semantics outside Tcl grammar, binary
dependency vs G-004); dev-time parse cross-check lint flagged as candidate.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
bb9ff66f51 |
G-045 increment 1: punk::args 0.6.1 - @cmd honours -unindentedfields for -help (project 0.12.4)
arg_error's cmd-help display transform (undent " "+help, max 4 - the '#unindentedfields ?' todo site) is now gated by "-help" membership in the @cmd line's -unindentedfields list, mirroring the existing per-argument gate. The single transform site feeds both the table and string renderers, so left-margin-authored @cmd help renders its first line flush with continuations in both. @cmd -summary carries no indent transform in any renderer, so -unindentedfields for -summary is vacuously honoured. No in-tree definitions set -unindentedfields on @cmd - existing rendering is unchanged. define doc for -unindentedfields now states where the option is valid. Tests: rendering_unindentedfields_cmd_help_GAP flipped to rendering_unindentedfields_cmd_help (aligned expectation, both renderers measured). Full punk::args suite 175 pass / 1 pre-existing skip / 0 fail; punk::ns suite 53/53 (arg_error consumer); make.tcl modules builds clean (tclsh 9.0.3). Also: G-045 flipped proposed -> active (user direction 2026-07-12); progress and remaining-work recorded in the detail file. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
bac122da9f |
G-039 achieved: punk::repl 0.5.0 dead-console watchdog stops orphaned-shell CPU spin (project 0.12.2)
An interactive shell orphaned by its hosting console dying (killed conhost/terminal) previously spun ~2 cores forever: the Tcl 9 windows console driver never delivers the dead-console state to the script as a fileevent (tclWinConsole.c ConsoleEventProc only notifies on buffered data) while its reader thread busy-loops on the persistent channel error, so the script level is completely blind and nothing ever closes the channel. Fix: repl::console_watchdog - a self-rescheduling liveness poll (default 5s, repl::console_watchdog_ms; read-only GetConsoleMode probe via chan configure -inputmode) armed by repl::start only for a tcl9 console input channel serving the process-default console on windows. On probe failure it closes the input channel (stopping the driver's reader thread) and finishes the repl via the normal eof done-path; app-punkshell then finds no console reopenable and exits cleanly. Piped, foreign-console and tcl 8.6 inputs never arm it. repl::start's post-vwait reader deregistration now tolerates a watchdog-closed channel. Verification (2026-07-12): kill procedure post-fix exits the orphan in 1.5-2.0s with no traceback (src mode and rebuilt kits punkbi/punk91/ punk902z); 25s live-console soak shows no spurious trigger, CPU delta 0; piped stdin unaffected; repl consolebackends 3/3 and punk::console suites 88 pass / 1 skip; root cause verified against plain tclsh 9.0.3. Upstream ticket filed: https://core.tcl-lang.org/tcl/tktview/f10d91c2d3 Included: - goals: G-039 flipped achieved 2026-07-12 and archived (index entry to GOALS-archive.md, detail file to goals/archive/ with full root-cause, repro and verification record); reference sweep adds the eof done-value producer note to G-038 - src/modules/punk/AGENTS.md: watchdog contract documented - project version 0.12.1 -> 0.12.2 + CHANGELOG entry - vfs payload sync: _vfscommon.vfs punk/repl 0.4.0 -> 0.5.0 Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
c309ed4782 |
punk::args 0.6.0: small restricted choice sets display as literal alternates in synopses
An argument whose choice pool (-choices plus -choicegroups members, deduplicated) has 1-3 members and -choicerestricted true (the default) now renders those words unitalicised joined by | in synopses - e.g 'after cancel' shows literal cancel, a 3-choice option shows (left|centre|right) - matching the display style of literal()/literalprefix() type-alternates. Larger or unrestricted choice sets keep the italicised argname/<type> display, and an explicit -typesynopsis always takes precedence (textblock::frame -type unchanged). New shared helper punk::args::private::synopsis_choice_literals feeds both synopsis render paths (leaders/values via synopsis_form_arg_display, options inline in synopsis); applies only to single-element -type lists. Superseded commented-out single-choice sketches removed; define doc for -choices documents the rule. tests: synopsis.test 4 -> 13 - characterization coverage for literal/literalprefix/stringstartswith/stringendswith type-alternates, option alternate parenthesization, multi-element clause display (?type? members, argname tail-word hints), -typesynopsis value-element lists and option passthrough incl documenter ANSI, plus the new choice-literal rule (leader/option/value positions, choicegroups counting, >3 and unrestricted fallbacks, -typesynopsis precedence). rendering.test choicelabel fixtures padded to 4 choices so markercol keeps matching the choices cell rather than the now-literal synopsis line. Known residue (deliberate): option-path -typesynopsis ?-trim edge cases remain (todo comments at the render site) - resolve-time rejection deferred; any future normalization surgery belongs to punk::ansi::ansistring/opunk::Str. project 0.12.0 Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
ab75a78b06 |
punk::repl 0.4.0: launch-time console selection (G-001)
repl::init -console <spec> selects the console the repl reads/writes (any punk::console::console_spec_resolve form); repl::start's inchan is now optional, defaulting to the selected console's input. Per-repl channel state (conin/conout/conerr) routes rputs (stdout/stderr mapped per-repl) and doprompt; for a foreign console the code interp's stdout/stderr are diverted via shellfilter 'var' junction stacks and emitted to the console after each run (repltype punk/0). New helpers console_is_default/console_at_eof/ console_get_size dispatch eof/size to the selected ::opunk::Console object's (possibly overridden) methods. Process-console behaviours (tcl_interactive prompt gating, stdin reopen on eof, raw-mode re-enable, windows utf-16be line re-decode experiment, mode-line on exit) now apply only to the default console. Default stdin/stdout behaviour unchanged. Also fixes rputs pseudo- channel mapping in the 3-arg -nonewline form (mapped value previously written over the -nonewline flag). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
3970b8e695 |
punk::libunknown 0.1 -> 0.2.0: adopt major.minor.patch + manual-versioning guidance
Verified nothing depends on the old version or filename before renaming: all 'package require punk::libunknown' sites are unversioned; punk_main.tcl and punk::repl locate the module by globbing libunknown-*.tm and picking the highest by vcompare (so the renamed dev copy now also outversions the stale bootsupport and project.vfs 0.1 copies deterministically, instead of relying on tm path order for a same-version tie); bootsupport's include_modules.config lists it by name only. The 0.2.0 number retroactively versions the two changes shipped against the 0.1 filename earlier today (register_all_tm deep discovery - a minor API addition - and the source_pkgindex sourcing-scope fix). A version-history comment block in the module header now substitutes for the buildversion.txt changelog other modules carry. src/modules/AGENTS.md: the punk::libunknown exception bullets now spell out the manual-versioning mechanics for agents - same Patch/Minor/Major bump rules as buildversion-tracked modules, executed as a file rename plus Meta line, manpage_begin, provide-block and version-history updates, with a check for exact-version/filename dependents before any first bump. discovery.test/libsearch.test: the source-tree libunknown locator now picks the highest libunknown-*.tm by vcompare instead of plain lsort (robust to future version bumps). Verified live in punk902z src: package provide reports 0.2.0, register_all_tm present, lib.search deep discovery intact. Suites green under tclsh90 and tclsh87. Build artifacts synced (root modules/ and _vfscommon.vfs carry only libunknown-0.2.0.tm). punkshell 0.10.2. Stale 0.1 copies remain in src/bootsupport/modules (pending 'make.tcl bootsupport') and src/vfs/project.vfs (pending layout maintenance) - both now cleanly outversioned at runtime. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
d35e055efc |
punk::libunknown: isolate pkgIndex.tcl sourcing - stop clobbering global 'dir'
zipfs_tclPkgUnknown previously declared 'global dir' and executed pkgIndex.tcl scripts via 'namespace eval ::' - the pkgIndex $dir contract was met by writing the global namespace's dir variable, silently overwriting any user global named 'dir' whenever a package require fell through to the pkg unknown handler (observed misdirecting a file write into the user's Tcl installation during test development), and each index's stray unqualified variables (ver, pkg, script, _CawtSubDirs, ...) leaked into ::. Index scripts now execute in a source_pkgindex proc frame: $dir is a formal parameter and auto_path/env are global links - exactly the environment stock tclPkgUnknown documents (its indexes see dir as the handler's proc-local plus 'global auto_path env'), without stock's incidental exposure of all its other proc locals. tcl::Pkg::source uplevels into the caller's frame, so the scheme works unchanged for the 8.6 pre-tip459 fallback. The legacy non-epoch branch already sourced in the handler frame and simply gains stock parity from the 'global dir' removal. Reviewed against tcllib 2.0's vendored index behaviours (all compatible): qualified '$dir ni $::auto_path'/'lappend ::auto_path' extension in the top-level index, its own apply-scoped subindex sweep (the same isolation idiom), vsatisfies guards with early return, 'package provide' during index sourcing (try/pkgIndex.tcl on 9+), and critcl-generated ifneeded strings (md5c, tcllibc) whose proc definitions run at require time, not source time. One deliberate divergence from stock: each index file gets its own frame, so unqualified variables no longer persist between index files within one sweep (stock shares its handler frame across the sweep) - nothing in tcllib relies on that. discovery.test: the GAP pin flips to libunknown_pkgunknown_preserves_global_dir, plus new pins for the index contract - $dir-based ifneeded/source works, unqualified 'lappend auto_path' extension reaches the real ::auto_path, and stray index-script sets don't leak to ::. Verified live in punk902z src: ::dir no longer set at startup, user dir global survives package activity, tcllib md5/struct::set/json load through the new frame, lib.search deep discovery unaffected. Remaining startup globals def/pkg/ver come from punkshell's own boot code (punk_main.tcl foreach loops), not the handler. punkshell 0.10.1. punk::libunknown remains manually versioned at 0.1; vfs artifact synced, bootsupport copy untouched as before. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
0c243a9ba9 |
dev lib.search: deep module discovery by default; -refresh = genuine re-scan
punk::libunknown gains register_all_tm: walks every tcl:™️:list path
recursively and registers ifneeded scripts for .tm modules at every
namespace depth (the tm unknown handler only registers siblings at the
requested depth, leaving never-requested subfolders like test::* invisible
to 'package names'). First registration wins - parity with the handler and
the shadowing pins. Reuses/populates the per-epoch directory index cache
(zipfs whole-tree listing; per-dir globs for filesystem paths; #modpod-*,
#tarjar-* and _build skipped) and runs at most once per tm epoch per
interp - the guard is the interp-local tm_fullscan variable, deliberately
not in the shareable epoch dict since ifneeded registrations are
interp-local.
punk::mix::commandset::loadedlib 0.2.0: search runs register_all_tm plus
the auto_path pkgIndex sweep by default when punk::libunknown is active,
so 'dev lib.search test' now shows deep modules without -refresh.
-refresh is repurposed to mean a genuine filesystem re-scan: package epoch
incr (invalidating the scan caches) then rediscovery - picking up .tm
files added/removed on disk. Without punk::libunknown (or with an older
copy lacking register_all_tm) -refresh falls back to the previous
dummy-require deep walk. Dependency fixes: highlight ansi computed only
when -highlight 1 via qualified punk::ansi with inline require (previously
relied on the shell-global a+ alias unconditionally and errored in bare
interps), inline requires for punk::path (fallback walk) and textblock
(table output).
New test suites (green under tclsh90 and tclsh87):
- modules/punk/libunknown/testsuites/discovery/discovery.test: lazy-depth
sibling registration, register_all_tm all-depths/cached-per-epoch/
head-wins-parity, package epoch shape and trace-driven increments,
epoch-cache short-circuit + incr recipe, and a GAP pin of
zipfs_tclPkgUnknown clobbering a user global 'dir' variable (stock
tclPkgUnknown keeps dir proc-local; fix candidate).
- modules/punk/mix/testsuites/loadedlib/libsearch.test: search match
semantics, default deep discovery, -refresh re-scan contract, highlight
without shell-global ansi aliases.
Both suites source the source-tree punk::libunknown directly by path:
'package require' would tie-break the same-version bootsupport copy by tm
path order (testinterp order favours bootsupport; child-interp
'tm::add {*}list' reverses precedence).
Verified live in 'punk902z src'. Build artifacts synced via make.tcl
packages + vfscommonupdate (loadedlib-0.2.0.tm, libunknown-0.1.tm).
Note: src/bootsupport copy of punk::libunknown intentionally untouched -
becomes stale until the next 'make.tcl bootsupport' sync; loadedlib
degrades gracefully against it. punk::libunknown remains manually
versioned at 0.1.
punkshell 0.10.0 (see CHANGELOG.md; also records the 0.9.1 doc-only
-refresh help rewrite).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
ce31d8623c |
update punk::sshrun with wiki documentation
|
2 weeks ago |
|
|
4bb7b3d68f |
G-054 achieved: tclcore string is class choices harvested from the running interpreter (tclcore moduledoc 0.2.0, punkshell 0.8.2)
- the ::tcl::string::is definition harvests its class set at define time from the bad-class error message of a deliberately invalid probe (safe, side-effect-free) - accept/reject parity with the loading interpreter by construction: 8.6.13 = 21 classes (no dict - the previous static 9.0 list wrongly ACCEPTED string is dict there), 8.7a6 = 23 (+dict +unicode), 9.0.3 = 22 (unicode removed). Fallback to the 9.0 set if the message format ever changes - hand-written man-page descriptions (kept verbatim, tstr-processed as before so the A_WARN highlights are unchanged) apply only to classes the runtime accepts; accepted-but-undescribed future classes get a generic label; static version notes added to dict (not in 8.6) and the new unicode entry (unreleased 8.7 only - removed in tcl 9). The per-class virtual docids (::tcl::string::is <class>) follow the harvested set automatically - new tclcoreparity.test (4 tests, gated on have_tclcoredocs): choices equal the live-harvested set and every documented choice is really accepted; per-class docids exist for every class; error-vs-ok outcome agrees between real string is and parse_status across the 23-shape probe matrix (missing args, trailing flag-like str, option/class prefixes + ambiguity, unknown option/class, -failindex var consumption, per-version dict/unicode presence, divergent-classification shapes); version-note labels conditional on presence. Expectations derived from the LIVE interpreter, never version arithmetic - green on 9.0.3, 8.7a6 and (via a direct tcltest driver, since runtests infrastructure does not run under the plain 8.6 kit) 8.6.13 - full punk/args + punk/ns trees green (219 pass + 1 pre-existing skip) incl the have_tclcoredocs cmdhelp pins Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
d3d81c1c39 |
G-058 achieved: boot honours statically-linked runtime packages (punk::lib 0.4.0, punk::repl 0.3.0, punk::packagepreference 0.2.0, shellthread 1.7.0)
- punk_main.tcl captures the runtime static baseline at kit boot: empty-filename [info loaded] prefixes probe-loaded in a throwaway interp (configurable denylist tk*/vfs/mk4tcl/vlerq/tdbc* for side-effecting/composite inits), recording only packages a load actually PROVIDES (diff on provides, not package names - probe loads can trigger index scans) into ::punkboot::static_packages/static_prefixes; the boot interp is seeded with ifneeded {load {} <prefix>} mappings
- punk::lib interp_sync_package_paths/snapshot_package_paths propagate the baseline and seed fabricated interps/threads; punk::repl codethread init (new %staticprefixes%/%staticpackages% scriptmap) and shellthread worker init do the same - the repl code interp on a static runtime resolves Thread again (punk91 = tclsfe-x64 + punk9win.vfs failed with "can't find package Thread"; the appended vfs replaces the stub's //zipfs:/app mount taking its static pkgIndex files with it, and the tclsfe PostInit hook seeds per-interp auto_path only)
- punk::packagepreference static-vs-bundled policy: requiring a baseline package ensures the static mapping and triggers the package unknown scan BEFORE resolution so bundled copies register and the highest version wins (newer bundled reachable, static not masked by older bundled); static registrations excluded from the loaded-shared-object same-version pinning
- composite statics defer correctly: static twapi provides nothing under the probe (script layer lived in the replaced stub zip) so the bundled complete twapi is the resolution; punk91 vfs/vfs::zip warning re-diagnosed as kit content (tclsfe bundles no tclvfs) - recorded in the goal detail, not a seeding defect
- tests: staticseed.test (4) + staticpolicy.test (4) un-gated simulated-baseline units (green 9.0.3 + 8.7); staticruntime.test (4) kit integration behind the capability-probed statickitavailable constraint (probes ::punkboot baseline incl Thread; env PUNK_STATICKIT_TEST_EXE override, default bin/punk91.exe) - 4/4 against the rebuilt punk91; punk902z/full shell tree/full source-tree suite baselines unchanged (exec-14.3 only)
- verification runtime tclsfe-x64.exe pinned in the punkbin artifact repo (separate repo, commit b2dbbe6) with sha1sums + new AGENTS.md scaffolding
- punkshell 0.6.0: CHANGELOG entry; AGENTS updates (src/vfs capture contract, tests indexes incl new punk/lib + punk/packagepreference entries, shell staticruntime contract)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
ce2ba184cb |
punk::args 0.5.0 + punk::ns 0.2.0: G-049 parse-status data model + machine-parsable cmdhelp returns
- new punk::args::parse_status: documented status structure from a parse attempt (overall ok / status valid|invalid|incomplete / scheme / message / errorcode minus -argspecs / failureclass / badarg / form / receivednames + per-argument argstatus with class, status ok|bad|unparsed, received count/positions, value-in-effect incl -default fill); validation failures reported in the structure, not raised
- arg_error -parsestatus: both renderers derive goodarg/badarg row marking and choice value-in-effect highlighting from the structure (transient goodargs/badarg locals replaced; built internally from -badarg/-parsedargs when not supplied)
- per-render scheme colour resolution: documented -scheme choice value 'nocolour' now takes effect and scheme renders no longer mutate the shared arg_error_CLR array (strike-only goodarg leak fixed)
- parse: new -caller option overriding the %caller% frame-walk substitution (included in parse cache key); get_dict missingrequiredvalue/missingrequiredleader now carry -badarg (type/allocation failures get badarg marking, not just choice violations)
- punk::ns::cmdhelp: -return dict {origin docid cmdtype args_remaining parsestatus}; advisory parse via parse_status on both alias and main paths; explicit -scheme honoured on the parse-failure render; failure messages name the queried command instead of leaking the internal parse source line at top call depth
- tests: parsestatus.test new (12); usagemarking.test G-049 GAP pins flipped + -parsestatus parity/badarg render tests (17); cmdhelp.test G-049 GAP pins flipped + cmdhelp_return_dict_* (25); punk/args + punk/ns trees green on Tcl 9.0.3 and 8.7; full source-tree suite baseline unchanged (exec-14.3 only)
- punkshell 0.5.0: CHANGELOG entry; src/tests/modules/AGENTS.md test-index blurbs updated
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
02da46eb74 |
punk::args 0.4.2 + punk::ns 0.1.4: G-046 achieved - deferred display-field expansion, rendering/value-shape fixes
Argument resolution no longer tstr-expands display-only content (-help on @cmd/@examples/argument records, @formdisplay bodies): ${...} there is masked with inert tokens (spec key DISPLAY_DEFERRED) and expanded at display time via private::expand_display_fields (hooks in arg_error/eg/resolved_def/@default copyfrom; separate display cache for non-dynamic defs; @dynamic re-expands per render preserving provider refresh; reentrancy guard substitutes raw sources when expansion of the same id re-enters). First parse of heavily documented commands drops accordingly (punk::ansi::mark_columns first call ~4.3s -> ~12ms; tclcore ::lseq resolve ~184ms -> ~2ms) and -help content that calls punk::args-parsing commands - including against its own definition id - resolves cleanly instead of stalling or looping. -choicelabels stays eager (punk::ns reads it from parse specs in the subcommand walk). Record splitter factored to private::split_definition_records. Also per G-046 acceptance: - @dynamic multiline -help substitutions align at the insertion column (rendering_atdynamic_multiline_help_insertion GAP flipped) - prefix/alias choice normalization keeps single-element-clause values plain-string ({\Deleted} list-wrap shape bug; choicegroups_imap_prefix_shape GAP flipped) - -return string renderer aligns cmd-help continuations under the Description: label (characterization updated) and its Example: line shows the example, not the doc url - punk::ns cmdhelp shows plain info-scheme usage when no argument words are supplied for a leader/value-requiring definition ('i string is', 'i punk::args::define') - advisory parse runs -errorstyle minimal so the discarded error no longer renders a second usage table (timing parity with pre-change: ~5.3s/4.1s on punk91 src) Tests: deferredhelp.test (new); suites green on tcl903 + tcl87; full source-tree run baseline-clean (exec-14.3 only). GOALS.md: G-046 -> achieved 2026-07-10 (activated this session at user direction); design + verification evidence in the detail file. Project 0.4.15. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
383e4e5057 |
punk::args 0.4.1: ensemble autodef loads lazily-registered subcommand argdocs before id_exists checks
First 'i <ensemble>' in a fresh shell (e.g 'i ansistring') rendered the autogenerated ensemble help without subcommand-help markers/choicelabels: ensemble_subcommands_definition tested punk::args::id_exists against argdocs whose registered namespace (::punk::args::register::NAMESPACES) had not yet been lazily loaded - the punk::ns doc-lookup entry path only loads the ensemble command's parent namespace. The generator now runs update_definitions for the namespaces its id checks could resolve in. Self-healed on later calls (autodef regenerates per 'i' invocation), which is why the defect went unnoticed; no prior test pinned the load ordering. Tests: punk/args ensembledef.test (new), punk/ns cmdhelp.test cmdhelp_ensemble_lazy_registered_argdocs. Project 0.4.14. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
fe85dfadd0 |
punk::ansi 0.1.2: PUNKARGS argdoc coverage for codetype/sequence_type/ta/ansistring + characterization tests
- 34 documentation-only PUNKARGS blocks added: punk::ansi::codetype (is_sgr_reset, has_sgr_leadingreset, is_cursor_move_in_line, has_all_effective, get_effective_types, is_gx/is_gx_open/is_gx_close, sgr_merge), punk::ansi::sequence_type (is_Fe7/is_Fe/is_Fe8, is_Fp, is_Fs, is_nF, is_3Fp, is_code7/is_code8/is_code, classify), punk::ansi::ta (detect_in_list, detectcode, detectcode_in_list, detect_g0, detect_open, detect_st_open, detect_csi, detect_sgr, split_at_codes, split_codes, split_codes_single, get_codes_single) and punk::ansi::ansistring (VIEW, COUNT, length, trimleft/trimright/trim, INDEX, INDEXCHAR, RANGE, INSERT, INDEXABSOLUTE, INDEXCOLUMNS, COLUMNINDEX). - ::punk::ansi::sequence_type added to the punk::args::register NAMESPACES list - the escape-form classifiers live there (a separate namespace from codetype) and were previously undiscoverable by the doc system. - New characterization suites: ta.test (12 tests - detect vs detectcode lone-CSI distinction, split_codes/split_codes_single/split_at_codes shapes and join round-trip, length/extract), codetype.test (11 tests - reset/leading-reset semantics, effective-state queries incl. bold-via-intensity, sgr_merge, sequence_type classify taxonomy); ansistring.test extended 1 -> 12 tests (INDEX/INDEXCODE/INDEXCHAR/RANGE/INSERT grapheme indexing with merged SGR-prefix tracking incl. end+1 state-after-string, INDEXCOLUMNS/COLUMNINDEX double-wide column mapping via a CJK fixture, INDEXABSOLUTE resolution, styled-whitespace trim, VIEW control-picture substitution). - Tests use literal escape strings (not a+) so results are independent of the punk::console colour state. Origin notes added to the usage-marking suites' local SGR helpers pointing at these canonical mechanisms and their coverage. - src/tests/modules/AGENTS.md child DOX index: entries added for the punk/ansi, punk/args and punk/ns suites (GAP-pin/goal mapping documented). - Verified: 44/44 ansi suite and the full ansi+args+ns sweep (232 passed, 1 pre-existing skip) on Tcl 9.0.3 and 8.7; make.tcl modules clean. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
83b7e2a0de |
punk::ns 0.1.3: usage-marking characterization tests (usagemarking.test, cmdhelp.test) + cmdhelp subcommand doc fix
- punk::args level (usagemarking.test, 14 tests): pins -parsedargs/-badarg/-scheme marking primitives, goodchoice highlighting of selected and default-in-effect choice words, and scheme border selection - asserted by SGR-parameter subset against the live colour arrays. GAP pins for the documented -scheme choice 'nocolour' falling through to 'na' (renders with the previous scheme's leftover colours) and the dash-spelling '-nocolour' leaking strike-only goodarg into the shared colour array (G-049 candidates). - punk::ns level (cmdhelp.test, 19 tests): pins scheme selection (error scheme on failed parse of supplied args, info scheme + goodarg marking on success), badarg marking via choiceviolation, the early alias-resolution branch, -return string parity, goodchoice highlighting through cmdhelp, and the cmdinfo result shape. GAP pins: pseudo-command cmdtype 'notfound' despite resolved docid + space-form docid exact-word-only jump (G-051; real 'string is true'/'is tr' pins behind the have_tclcoredocs constraint), TclOO undocumented-method class-summary fallback with info-scheme parse of bogus args (G-052), synopsis marking absence and curried-alias braced-target substitution (G-050), explicit -scheme ignored on the parse-failure path and caller-attribution leaking cmdhelp's internal parse source line at top-level call depth (G-049). - punk::ns 0.1.3 (doc-only): cmdhelp 'subcommand' argument help rewritten - was described as ensemble-subcommands-only; now covers tcl::oo methods and argument words, and documents the info/error scheme display driven by argument validity. - Verified: full punk::args + punk::ns suites green on Tcl 9.0.3 and 8.7. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
d579760e68 |
punk::mix::commandset::project 0.2.1: -layout prefix-match validation fix
project::new documented -choices on -layout with -choiceprefix defaulting to true (prefix matching promised), but the manual dict merge parser accepted arbitrary values with no validation or normalization. Added tcl::prefix::match against the documented layout choices so the parser now validates and normalizes -layout values, matching the PUNKARGS documentation. Assisted-by: harness=opencode; primary-model=openrouter/z-ai/glm-5.2; api-location=openrouter.ai |
2 weeks ago |
|
|
e57cf74605 |
punk::nav::fs 0.1.1: d/ v argument -choiceprefix 0 PUNKARGS fix
d/ documented -choices on the v argument with -choiceprefix defaulting to true, but the manual parser uses an exact string comparison. PUNKARGS now declares -choiceprefix 0 so documented behaviour matches the implementation (exact match required). Assisted-by: harness=opencode; primary-model=openrouter/z-ai/glm-5.2; api-location=openrouter.ai |
2 weeks ago |
|
|
d6cd1585e2 |
punk::console 0.7.2: console_fact_get/console_fact_set key -choiceprefix 0 PUNKARGS fix
console_fact_get and console_fact_set documented -choices on the key argument with -choiceprefix defaulting to true (prefix matching promised), but the manual positional parser feeds key directly into a dict lookup with no prefix normalization. PUNKARGS now declares -choiceprefix 0 so documented behaviour matches the implementation (exact match required). Assisted-by: harness=opencode; primary-model=openrouter/z-ai/glm-5.2; api-location=openrouter.ai |
2 weeks ago |
|
|
52dab2457d |
punk::args 0.4.0: internals to private ns, dev-test procs culled, full PUNKARGS coverage; project 0.4.13
Pre-G-046 tidy-up of punk::args:
- deleted dead developer procs define2, parseXXX and the unused ::punk::args::TEST definition
- Get_caller diagnostics renamed __test_get_dict/__test_get_by_id/__test_callers (+ __test1 id)
and lib tstr demo renamed __tstr_test_one - unexported (punk::args::lib now exports {[a-z]*})
- new internal namespace punk::args::private (namespace path punk::args + lib + system):
_get_dict_can_assign_value, _split_type_expression, _check_clausecolumn,
_synopsis_form_arg_display, _argerror_load_colours and lib::_parse_tstr_parts moved there
with underscore prefixes dropped; argerror_load_colours reaches arg_error_CLR* state via upvar
- PUNKARGS definitions added for every remaining exported command (main ns incl. get_dict and
choiceword_match; lib utilities; helpers and argdocbase B/N/I/NI); resolve's empty -help filled;
punk::args::argdocbase added to registered definition namespaces
- tests: punk/args suite 127 pass + 1 known skip, punk/ns suite 28/28 (tcl87)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
87eafd63b0 |
Tcl 9.1 compat: punk::lib 0.3.1, punk::args 0.3.2 - lseq TIP 746, safe-interp disassemble; project 0.4.12
TIP 746 (Tcl 9.1) removed lseq's expr-operand behaviour. punk::lib::range (lseq branch) now normalizes int[+-]int offsets via offset_expr so callers like `range 0 [llength $list]-1` keep working (punk::ansi::grepstr broke under 9.1b0, taking example-block highlighting and the punk::args examples.test with it). The lseq branch is also aligned with the tcl8 fallback contract: default 'by' now infers direction (descending ranges previously returned empty under tcl9) and 'by 0' returns empty (Tcl 9.1 lseq changed by-0 to return one element). Direct lseq expression operands expr-wrapped: punk::lib lzipn_tcl9b/c, cols, cols2; punk::args zero_based_posns. check::has_tclbug_safeinterp_compile falls back to interp invokehidden tcl:unsupported:disassemble - Tcl 9.1 safe interps hide tcl::unsupported::*. New modules/punk/lib range.test pins the range contract on 9.0 and 9.1; core tests AGENTS.md documents native-tclsh vs punk-exe exec.test baselines. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
4541944928 |
punk::args rendering/quoting/choicegroups/examples characterization suite; helpers::example [a] fix
Tests-first coverage pass (user-directed) before any changes to the definition-parsing/indentation machinery. punk/args suite: 128 tests, 15 files. - rendering.test (15): nesting independence (plain + tstr definitions render identically regardless of source-block indentation), relative-indent preservation (2-space help and 1-space choicelabel conventions, single and multiline - preservation, not enforcement), -unindentedfields (arg -help works left-margin; @cmd accepts-but-ignores it - GAP pinned), constructed (string-built) definition absolute-indent characterization ('constructed' to avoid confusion with the @dynamic directive), multiline ${[cmd]}/${$var}/ resolved_def insertions (aligned at insertion column, nesting-independent), and @dynamic ${$DYN_X} double substitution: stable across repeated resolutions, provider refresh honoured in help text, choice display and parse acceptance, textblock::frame-style art choicelabels byte-aligned - but multiline -help insertions land lines 2+ at insertion-4 (GAP pinned: the second-round subst path lacks paramindent re-alignment) - choicegroups.test (5): group/-choices union parsing, cross-group prefixes, duplicate-entry dedup, per-group titled choice tables (the punk::imap4 multi-table display), imap4-style {\Deleted}/{$MDNSent} values with labels incl. through tstr-bearing blocks; GAP pinned: prefix-normalization list-quotes special-character choices (exact '\Deleted' stores the plain string, prefix '\De' stores a one-element list) - value shape depends on input style - 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/title/-tstr toggle (no-dedent direct-call contract pinned), ${[example ...]} insertion into @cmd help (bars at insertion column, content +2, automatic 'Example: eg <id>' row), @examples -> punk::args::eg with #<nodisplay>/@#<nodisplay> stripping (ANSI-tolerant), strip_nodisplay_lines unit, live tclcore ::lseq smoke - punk::args 0.3.1: helpers::example -title path called bare [a] (resolvable only where a punk shell's global alias exists - errored under plain tclsh); now punk::ansi::a. Found by examples.test in the runtests environment. - investigated punk::ansi::mark_columns first-call slowness (3.94s first, 60us after): argdoc -help calls a proc that calls mark_columns, whose parse resolves the same still-resolving definition - hazard already documented in-source with candidate fixes; recorded in CHANGELOG for goal consideration, deliberately not patched - project 0.4.11 (CHANGELOG entry) Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
850b7f23cc |
G-040 achieved: punk::args -choicealiases with shared choiceword_match resolver; doc-lookup parity; punk::help topic collapse
Activated and completed under user direction (2026-07-08). Aliases for choice
values are now first-class: accepted at parse, normalized to their canonical
choice in results, folded into the canonical entry in usage display, and
resolved identically by the punk::ns doc-lookup walk.
- punk::args 0.3.0:
* -choicealiases {alias canonical ...} on argument lines; dict shape
validated in the option switch, alias->existing-choice and no-collision
cross-validated after spec merge (surfaces at resolve time - define is
lazy)
* the choice-word matching chain extracted from get_dict into the shared
resolver punk::args::choiceword_match {word nocase allchoices
choicealiases choiceprefix denylist reservelist} -> {matched exact
canonical}; get_dict delegates to it (writeback/lset logic stays at the
call site) - one implementation for parser and doc walk
* exact aliases match under any -choiceprefix/-nocase setting; alias names
join the prefix-calculation pool when -choiceprefix is true; deny applies
to the matched NAME (denied alias requires the full alias; a canonical
reached via its alias is exempt from the canonical's own deny entry)
* display: aliases fold into the canonical entry as an '(alias: x)' /
'(aliases: x|y)' label note (single convergence point covers all render
paths); alias names join the display prefix calculation so highlighted
minimal prefixes stay truthful
* define doc gains the -choicealiases section
- punk::ns 0.1.2: cmd_traverse resolves subcommand words via choiceword_match
- -choiceprefixdenylist/-choiceprefixreservelist now honoured in doc lookup
(the two pinned parity GAP tests flipped to agreement), aliases normalize
before choiceinfo lookup, -nocase honoured in the walk
- punk 0.2.3: punk::help adopts the feature - 'i help' lists one entry per
registered topic (topics+help, tcl, env+environment, console+term|terminal);
topic words accept aliases and unique prefixes with the user-decided
minimum-prefix policy recorded in ::punk::helptopic: denylist {help}
(h/he/hel stay command words), reservelist {c to tc} (fall through to
command lookup; e/en and te/ter fall through naturally as ambiguous).
Argless 'help' output byte-identical to the strict-80 baseline.
- tests: choices.test +5 (alias exact/prefix normalization, noprefix exact-
only, nocase, the punk::help policy matrix, resolve-time validation);
cmdflow.test parity tests flipped from GAP to agreement + alias-traverse and
display-fold assertions (+flowaliased fixture)
- suites: punk/args 98 pass + 1 skip, punk/ns 28 pass, punk/lib 21 pass
- G-040 flipped active -> achieved 2026-07-08; detail file records
implementation and verification
- project 0.4.10 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
3 weeks ago |
|
|
48dccbe8c1 |
G-036 achieved: tcludp thread-exit bug detection (punk::lib 0.3.0 has_libbug_udp_threadexit, surfaced via 'help tcl')
Completes G-036's remaining acceptance item - version-based detection of the vulnerable combination (tcludp < 1.0.13 on Tcl 9 Windows: the per-thread exit handler closes the process-global sockListLock/waitForSock events, silently freezing every other udp-using thread's event loop after any udp-loaded thread exits; root-caused and fixed-by-upgrade in 0.4.3). - punk::lib 0.3.0: has_libbug_udp_threadexit gathers live facts (loaded udp version, else best available registered version discovered without loading the binary via an unsatisfiable package require triggering the index scan) and delegates the verdict to the pure classifier libbug_udp_threadexit_applies (facts in, verdict out - testable). has_libbug_* is the new check family for bundled/vendored library bugs; buginfo dicts may carry a full 'url' reference key for non tcl-core trackers. - punk 0.2.1: 'help tcl' scans has_libbug_* alongside has_tclbug_*, renders the url key when present, and no longer errors on a triggered check carrying a reference without a description (latent unset-indent fix). - new checkbugs.test: classifier combination matrix, live-check dict shape and classifier consistency, and a buginfo-contract test across all existing check procs. - verified: current kit (udp 1.0.13) reports bug=0 with no warning; a simulated triggered has_libbug_* check renders description + url in the help tcl warning block. Suites: punk/lib 21 pass, punk/ns 26 pass. - G-036 flipped to achieved 2026-07-08 (index acceptance REMAINING annotated DONE; detail file gains the Detection section). Open non-gating decisions recorded in the detail file: punk8win (8.6) kit udp 1.0.12 swap; optional upstream tickets for residual tcludp trunk weaknesses. - project 0.4.7 (CHANGELOG entry) Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
93730dfda7 |
punk::ns 0.1.1: silence doc-lookup trace puts; -ensembleparameter characterization tests
- commented out five development trace puts in the doc-lookup machinery:
"PROC auto def"/"ENSEMBLE auto def" (generate_autodef) were emitted on STDOUT
and polluted 'i'/'s' output in script/exec contexts (agent-facing per the
G-015 piped-call pattern); "cmd_traverse - skipping to documented subcommand"
(space-form id path), "---> cmd_traverse ensembleparam" (ensemble -parameters
traversal) and "cmd_traverse 10 ... - review" (fallthrough return) were
stderr noise. No functional change.
- cmdflow.test: 8 new tests characterizing ensemble -parameters handling in the
doc-lookup flow (the punk::netbox::man pattern - leading apicontextid before
the subcommand at every ensemble level):
* generate_autodef models each -parameters entry as a -ensembleparameter 1
leader with @leaders min/max = nparams+1 (single- and two-param fixtures)
* cmd_traverse consumes parameter words and resolves the subcommand's
explicit or autodef docid, re-presenting the parameter in args_remaining
so the subcommand's own leader-based definition (as punk::netbox::man's
explicit defs model the curried parameter) can parse it
* nested sub-ensembles with their own -parameters re-consume the curried
parameter at each level
* punk::args::parse treats -ensembleparameter leaders as ordinary named
leaders; cmdhelp renders a documented subcommand's usage through the
parameter (end-to-end smoke)
- suites: punk/ns 26 pass (was 18), punk/args 93 pass + 1 skip (unchanged)
- project 0.4.6 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
3 weeks ago |
|
|
e624bdc057 |
punk::args 0.2.3: fix @opts -any adhoc option crash; forms + validation test coverage
- fixed "@opts -any 1" (arbitrary/adhoc option passthrough): an option not in
the definition crashed get_dict with "can't read argname" at the name-mapping
stage - adhoc opts now fall back to their raw supplied name, under which
argstate/arg_checks were already populated at scan time (real consumers:
vendored tomlish definitions declare -any 1)
- commented out a debug puts stderr (">>>_get_dict_can_assign_value NOT
alloc_ok...") that fired on every failed clause type assignment (visible on
any multiform parse miss; its happy-path twin was already commented)
- new forms.test (8 tests): @form spec structure (form_names, shared
{a b}-prologue blocks), explicit -form by name/index with cross-form
rejection, multiform synopsis rendering, and GAP pins for G-041 - default
parse is effectively form-0-only, -form rejects the documented list-of-forms
usage, and @form -synopsis overrides are stored in the spec but ignored by
synopsis rendering
- new validation.test (11 tests): -type validation matrix, -range/-minsize/
-maxsize, -nocase choice normalization, option -multiple accumulation,
required-option enforcement, unknown-option rejection vs -any adhoc
passthrough (the bugfix's regression test), -- end-of-options marker,
@values -max enforcement, received-key clause ordinals, solos list, and
default-vs-received distinction
- src/tests/AGENTS.md: note that tcltest compares the -body return value -
bodies ending in a loop must end with an explicit 'set result'
- suites: punk/args 93 pass + 1 skip (was 70+1), punk/ns 18 pass; full
source-tree run 569/581 with only the known exec-14.3 baseline failure
- project 0.4.5 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
3 weeks ago |
|
|
e45fea9b16 |
G-040 proposed (punk::args -choicealiases); choice-flow characterization tests; -choice* doc clarifications
- GOALS.md: G-040 punk::args choice aliasing with parse normalization, display folding, and doc-lookup parity (user-approved); detail file records the prefix/deny/reserve collapse analysis from the punk::help work, the cmd_traverse divergence, the c/to/tc minimum-prefix policy question, and the test-first sequencing - new punk/ns cmdflow.test (10 tests): cmdwhich/cmdinfo/cmd_traverse docid flow - direct, via-alias and subhelp-choiceinfo resolution (exact + unique prefix), unknown-word fallback to parent docid, -choiceprefix 0 exact-only, space-delimited ids, cmdhelp -return string smoke; the parse-vs-doc-walk divergence (deny/reserve lists honoured by punk::args::parse, ignored by the cmd_traverse walk) pinned as GAP tests pending G-040 - choices.test: 4 new unrestricted-mode (-choicerestricted 0) tests - prefix normalization to the canonical choice, unknown/ambiguous passthrough, denylist and reservelist passthrough, and the punk::help collapse recipe (prefix+deny+reserve on a -multiple leader) - punk::args 0.2.2 (doc-only): define doc -choice* fields now state the -choicerestricted 0 passthrough semantics, -choiceprefix result normalization + minimal-prefix display highlighting, denylist behaviour for shorter prefixes in both restricted modes, and the reservelist phantom-entry idiom for per-choice minimum-prefix control - suites: punk/args 74 pass + 1 skip (was 70+1), punk/ns 18 pass (was 8) Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
b8371e0587 |
script subcommand: lib:<name> scriptlib support; punk::path 0.2.2 - 0.4.0
app-punkscript accepts lib:<name> (with or without .tcl - extensionless appends it) as the shell subcommand does: `punkexe script lib:hello` or bare `punkexe lib:hello` via reclassification. The prefix always wins; a literal path beginning lib: (pathological - colon is illegal in Windows filenames) is reachable via ./lib:... Not-found errors list every searched location; only .tcl runs via the script subcommand. Resolution policy is factored into punk::path::scriptlib_resolve (PUNKARGS-documented) rather than copied inline: kit-internal app/scriptlib first and deliberately not externally overridable, then scriptlib dirs relative to the executable - the same policy app-punkshell encodes inline (todo noted: refactor the shell path onto the shared proc). Share definitions via modules, not launcher control flow. Verified on both generations (punk902z, punksys): lib:hello extensionless and explicit, bare-arg reclassification, not-found candidate listing (bin/scriptlib then <root>/scriptlib for a bin/ exe). Project version 0.4.0 (backward-compatible behaviour addition). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
935f597c0b |
script subcommand: core-command doc parity (i list works in piped scripts)
app-punkscript loads punk::args::moduledoc::tclcore (catch-guarded, mirroring the punk::repl code-interp setup) so core Tcl commands are documented in script runs as at the repl: `''i list'' | punkexe script` now renders the doc table instead of "Undocumented command". Cost ~40ms; kit script startup ~0.33s. REVIEW note added: the default-punk-shell package set is now expressed in app-punkscript AND the repl codethread setup - consolidation into one shared definition is the G-015-noted follow-on. punk::packagepreference 0.1.1: moduledoc auto-load success notice moved stdout -> stderr (stdout must stay machine-clean for script/exec contexts; the failure branch already used stderr). Verified on both generations (punk902z, punksys): i list doc table on stdout, notice on stderr, timing unchanged. Build-order footnote: lib changes need make.tcl libs before vfscommonupdate - the modules-only first rebuild shipped a stale app-punkscript payload. Project version 0.3.1. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
28106ac4b2 |
punk::console 0.7.1: idle-reader hostage guard - fail fast instead of timeout + phantom input
On a tcl 8.6 windows console in cooked (line) mode with a readable handler
armed on stdin - the idle-at-a-line-mode-prompt condition, e.g. a query
fired from an after-script or worker thread while the shell waits for
input - the 8.6 channel driver has a blocking cooked-mode ReadConsole
parked (arming posts it; driver reads sample the console mode at issue
time), so a terminal query's response is swallowed until Enter and then
leaks to the line reader as phantom input. This is the one remaining
hostage window after the 0.7.1 detection fixes and repl 0.2.2 read
discipline: it is the reader legitimately doing its job, so no repl-side
change can remove it (and line mode remains supported for user
scripts/mini-apps even once raw becomes the default).
get_ansi_response_payload now detects the condition before emitting
(cooked + no -inputmode key + twapi console handle + armed readable
handler) and refuses fast with errorcode
{PUNK CONSOLE QUERY HOSTAGE_COOKED_READ} - no emission, no ~500ms timeout,
no input corruption. Mid-command queries (repl reader disarmed) and raw
mode are unaffected. Best-effort by design: a parked read can outlive a
removed handler, so the guard catches the systematic case only. The G-007
routing wrapper now preserves the owner-side errorcode so brokered callers
can discriminate the refusal.
Tests: constraint-gated guard test in probes.test (engages on a real 8.6
console, self-skips on 8.7/9 via the -inputmode key and in piped runs);
ownerrouting.test passes with the errorcode-preserving wrapper. Full suite
at baseline (exec-14.3 only) under Tcl 9.0.3; probes suite also verified
under Tcl 8.6. Project version bumped to 0.2.2 with CHANGELOG entry per
the versioning policy (user-visible failure-mode change).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
3 weeks ago |
|
|
c19c1167c8 |
punk::console 0.7.1: compound emit-then-query operations flush before querying
get_size on tcl 8.6 returned 'columns 1' (real size e.g. 260x49): with the 0.7.1 console-detection fixes in place, 8.6 takes the ANSI size mechanism (no -winsize shortcut) for the first time under G-007 routing - and that mechanism is compound: the far-corner cursor move was written unflushed into the calling thread's stdout channel instance while the routed position query executed and flushed in the console-owning thread's separate instance of the same OS handle. The terminal answered before the move reached it. Pre-routing this was masked because emit and query shared one channel instance, so the query's own flush pushed the emissions too. All compound emit-then-query operations now flush their emissions before querying: get_size_using_cursormove and get_size_using_cursorrestore (the far-corner move), test_char_width (both the positioning emission and the measured test emission - the latter would silently corrupt character-width results), and test_string_cursor (alt-screen/move/erase). Error paths flush their cursor-restore emissions likewise. Interactively verified on punksys (tcl 8.6.13, src launch): get_size reports the true terminal dimensions and test_char_width \t returns 8. Full suite passes at baseline (exec-14.3 only) under Tcl 9.0.3. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
d68d4d4f26 |
punk::console 0.7.1: ensure_object_integration hardening - graceful no-op + catch-up ownership registration
Two wiring-order holes surfaced during the G-007 interactive verification: 1. Calling ensure_object_integration before opunk::console is loaded errored into the nonexistent namespace (can't set "::opunk::console:: waiting_chunks_arrayvar": parent namespace doesn't exist). It now returns 0 as a graceful no-op without latching object_integration_done, so a later call after opunk::console loads still performs the wiring; the wired/latched path returns 1. 2. 'package require opunk::console; opunk::console::create ...' with no intervening punk::console object operation left the created console without a registered owner: the lifecycle callback that records ownership is only installed by ensure_object_integration, which is wired lazily from punk::console's object-spec paths. Behaviour was unaffected for the owning thread (share qualifiers fall back to the calling thread) but other threads could not address that console's facts. On wiring the callback, ensure_object_integration now retro-registers ownership for anchors already present in the interp - anchors are per-interp/per-thread so the anchoring context is the calling thread. Only empty registry entries are filled; existing live registrations are preserved (and the default console keeps first-registration-wins semantics). Tests: new objectintegration.test covers the no-op return (unlatched), retro-registration of a pre-wiring anchor with lifecycle forget clearing the entry, idempotency of the latched path, and normal post-wiring registration - passing under Tcl 9.0.3 and 8.6. Full suite at baseline (exec-14.3 only). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
552a311d6e |
punk::repl 0.2.2: waiting-chunks path avoids drained-channel read on tcl 8.6 consoles
Companion to punk::console 0.7.1 (three-site 8.6 console misdetection fix). The line-mode waiting-chunks path in repl_handler performed an unsized read that, entered via 'after idle' with the channel drained, made the tcl 8.6 windows console driver park a blocking cooked-mode ReadConsole (driver reads sample the console mode at issue time - a later raw flip cannot cancel one). After typed-ahead was stashed during a terminal-query raw window, that parked read swallowed every subsequent query response in the session until Enter, with the responses later leaking to the reader. On hostage-prone consoles (windows, no -inputmode configure key, real twapi console handle) the path now consumes only data already in the Tcl channel buffer (chan pending input + sized read - no driver probe). With nothing buffered it processes the stashed complete lines directly - preserving the recovered-typeahead execution order - and arms the readable handler for any remaining partial line, replacing an after-idle reinvoke that, without the read, could never have progressed; the parked read that arming creates is the reader legitimately waiting for the user to finish typing. Behaviour on tcl 9/8.7 (-inputmode consoles) and in raw mode is unchanged. Interactively verified on punksys (tcl 8.6.13, src launch): the previously failing case - typing a full command during a line-mode brokered query loop - now runs with all queries answering, the typed line executing after the loop, and no timeouts, response leakage or chan-blocked diagnostics; the session remains healthy afterwards. Full suite passes at baseline (exec-14.3 only) under Tcl 9.0.3. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
528d1eca72 |
punk::console 0.7.1: fix tcl 8.6 windows console misdetection - one root cause, three sites
Tcl 8.6 windows console channels expose no -inputmode configure key, so punk::console guards testing -inputmode/-mode classified a real 8.6 console as a pipe. A twapi console handle for stdin is now treated as definitive console detection at all three affected sites (stdin only - pipe probes still never touch the process console; mintty-as-pipes has no console handle and falls through to the env heuristics as before): 1. get_ansi_response_payload's raw-cycling gate (introduced 0.1.5) skipped the raw cycle for 8.6 line-mode queries. 2. is_input_console_or_tty returned a false negative, making settle_can_respond's layer-2 heuristic settle a real 8.6 console as unable to respond. 3. input_at_eof (introduced 0.1.2) took the pipe branch and performed its probe read on the drained console channel. This was the line-mode query killer: verified empirically against clean tclkits 8.6.13 and 8.6.17, a read on a drained 8.6 console channel makes the channel driver park a blocking cooked-mode ReadConsole; driver reads sample the console mode when issued, not when data arrives, so the query's subsequent raw flip cannot rescue it and the terminal response is swallowed until Enter. Since get_ansi_response_payload calls input_at_eof immediately before its raw cycle, every 8.6 line-mode query timed out (~500ms) with the response later leaking to the line reader as phantom input - also the source of increased ANSI artifacts (e.g. 'help env') once 0.7.0 brokering made code-interp queries actually reach the terminal. Interactively verified on punksys (tcl 8.6.13, src launch): line-mode get_cursor_pos and dec_get_mode succeed mid-command, brokered query loops run clean, and typed-ahead lines are recovered without phantom input. Known residue (documented in the G-007 detail notes): queries fired while the repl reader is armed and idle at a line-mode prompt (including some repl-init detection queries) still hit the parked-read limitation on 8.6 - repl init ordering is a follow-up; raw mode is unaffected. Tests: probes.test gains constraint-gated wiring tests for the twapi console branch of is_input_console_or_tty and input_at_eof (skip in piped runs, engage on a real console). Full suite passes at baseline (exec-14.3 only) under Tcl 9.0.3; probes suite also verified under Tcl 8.6. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
6314312aa4 |
punk::console 0.7.0: G-007 slice 2 - choke-point brokering of terminal queries to the console-owning thread
A terminal query (internal::get_ansi_response_payload and every query proc
layered above it - get_cursor_pos, dec_get_mode, ...) on the process-default
console {stdin stdout} issued by a thread that is not the registered owner is
now forwarded whole to the owning thread via synchronous thread::send, so the
query queueing, raw-mode cycling, cooperative reader handling
(input_chunks_waiting) and settled can_respond gating all execute in the
owner's context. Owner-side errors propagate to the caller with routing
context. Routing happens before the local can_respond gate deliberately: a
non-owner context's anchored view of the default console may be unsettled
while the owner's is settled.
New internal::console_route_owner makes the decision: routing applies to the
default console pair only - non-std channel names are thread-local, so an
{in out} pair spec always names the calling thread's own console and operates
locally (a console constructed and owned by code-interp/worker code
round-trips nowhere). Unregistered, owner==caller and dead-owner
(liveness-validated) cases also operate locally, preserving single-interp
behaviour exactly.
The synchronous send relies on the owner servicing events while the caller
blocks - the property the repl-installed vt52/colour/mode aliases already
depend on. Those aliases are unaffected: a call arriving in the owner
resolves to owner==self and takes the local path, so no double-hop and no
ping-pong.
Tests: new ownerrouting.test covers the routing decision (unregistered/self/
other-live-thread/non-default-pair/dead-owner) and the transport (recorder in
a worker-thread owner: args marshalled intact, execution in the owner thread,
query procs above the choke point inherit the routing, owner-side error
propagation). Full suite passes (baseline exec-14.3 only).
G-007 remains active: the remaining acceptance verification is interactive -
a terminal query from a live punk session's code interp against the default
console (cooperating with the repl reader), which needs a real responding
terminal.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
3 weeks ago |
|
|
05b977fb3d |
punk::path 0.2.1: filter '.' and '..' by tail in treefilenames hidden-dir glob to fix non-Windows recursion loop
|
3 weeks ago |
|
|
aca967e1a5 |
punk::console 0.6.0: G-007 slice 1 - tsv-backed console facts + ownership registry
Per-console facts are now visible to every thread of a punk session: the
default console {stdin stdout} keeps its legacy namespace variables as
authoritative local storage, with write traces mirroring every write
(including direct variable writes) into tsv punk_console_facts; non-default
consoles store facts only in tsv with owner-qualified keys (non-std channel
names are thread-local and would otherwise alias). console_fact_set from a
non-owner thread forwards to the owning thread (vt52-alias transport) and
always writes the tsv mirror itself (covers unreachable or older-version
owners). New console_fact_clear for tests/maintenance.
New console ownership registry (console_owner_register/get/forget, tsv
punk_console_owners keyed by canonical {in out} pair): ownership is captured
when an opunk::console instance is anchored - via the new pluggable
::opunk::console::lifecycle_callback (opunk::console 0.4.0, base class
unchanged) wired by ensure_object_integration - and by default_console.
Consult-time liveness validation clears entries for exited threads. For
{stdin stdout} first registration wins and only the owner's forget releases
the entry, so a thread anchoring a local view cannot steal ownership.
dec_has_mode/ansi_has_mode caches moved to tsv punk_console_modecache
(single-key atomic entries shared process-wide).
Infrastructure tsv arrays are now punk_-prefixed to avoid collisions with
application tsv usage in subshells: console -> punk_console (is_raw), with
call-site patches in punk::repl 0.2.1, punk::lib 0.2.1, punk::basictelnet
0.1.1 (rule recorded in src/modules/AGENTS.md; legacy repl/codethread_*/
zzzload_pkg* arrays left for a coordinated follow-up).
punk::console is now loadable in secondary threads without ::argv0
(powershell consolemode fallback guarded).
Tests: consolefacts gains ownership-registry and cross-thread visibility
coverage (worker-thread punk::console load, trace-mirror, forwarded set with
deadline-polled sync - see comments re runtests child-interp topology);
cleanups use console_fact_clear / tsv instead of poking removed internal
stores. Full suite passes (baseline exec-14.3 only).
G-007 flipped proposed -> active (user-confirmed); remaining acceptance work
is the choke-point brokering slice.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
3 weeks ago |
|
|
e2e142faa2 |
punk::console 0.5.0: -console migration complete - remaining query procs converted to hybrid pattern
Migration plan phase 4 (final phase): - get_cursor_pos, get_cursor_pos_list, get_checksum_rect, get_device_status, get_device_attributes, get_device_attributes_tertiary, get_terminal_id, get_tabstops, get_tabstop_apparent_width, get_dimensions, get_xterm_size, get_xterm_pixels, dec_get_mode_line_wrap and ansi_get_mode_LNM accept -console <consolespec> (any spec form) or the legacy trailing positional, parsed by new internal::hybrid_console_spec; each carries a PUNKARGS definition (@leaders per the Argument Order rule) - get_size refactored onto internal::hybrid_console_spec (behaviour unchanged) - documentation-only PUNKARGS for input_at_eof, is_input_console_or_tty, size_via_query_mechanisms, console_size_provider and the get_size_using_* mechanism helpers (signatures unchanged - internal size mechanisms remain canonical-pair only, per the updated AGENTS.md contract) AGENTS.md migration bullet rewritten from 'incrementally migrating' to the completed-state contract. New queryprocs.test (6 tests, fed-response coverage for every converted proc across spec forms); full console suite 58/58 on Tcl 9.0.3. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
3a85fa85f5 |
punk::console 0.4.0: mode setters resolve console specs, -minsize 2 removed, mode caches canonicalised
Migration plan phase 1:
- dec_set_mode/dec_unset_mode/ansi_set_mode/ansi_unset_mode and
cursor_style resolve -console via console_spec_resolve instead of
'[lindex $terminal 1]' - anchored opunk::console instance names and
::opunk::Console object values now work (previously silently wrote
to the wrong target)
- the fourteen '-console -type list -minsize 2' declarations replaced
with new shared fragment ::punk::console::argdoc::console_opts (the
-minsize 2 constraint rejected 1-element instance-name specs at
parse time); show_input_response and cell_size -console docs unified
on the fragment
- dec_has_mode/ansi_has_mode cache on the canonical {in out} pair -
all spec forms addressing the same console share one cache entry
- test_is_vt52 option -inoutchannels renamed to -console per the
documented convention (experimental/broken proc, no callers)
- set/unset mode argdocs corrected: <codes> are semicolon delimited
AGENTS.md records the fragment usage and the -minsize 2 prohibition.
3 new tests in consolespec.test (setter spec forms, cache
canonicalisation via mixed specs, test_is_vt52 -console); full console
suite 52/52 on Tcl 9.0.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
3 weeks ago |
|
|
b21c804641 |
punk::repl: remove redundant tm list, auto_path, and libunknown init from code interp punk/0 path
|
3 weeks ago |
|
|
51f744a17e |
wire interp_sync_package_paths into punk::repl safe repltype and zzzload loader thread
|
3 weeks ago |
|
|
28f11ad023 |
punk::libunknown: add PUNKARGS argdoc for init, package_query, zipfs_tm_UnknownHandler, and zipfs_tclPkgUnknown
|
3 weeks ago |
|
|
bf8aa4c80d |
punk::console 0.3.0: emit-side -console targeting + per-console facts
0.2.0 (emit-side console targeting, migration plan phase 2):
- punk::console::ansi::* emit functions, mouse/paste toggles,
start_application_mode, vt52, set_tabstop_width, titleset, top-level
move, test_char_width and test_string_cursor accept an optional
trailing '-console <consolespec>' (channel pair, anchored
opunk::console instance name, or ::opunk::Console object value),
parsed by new internal::opt_console_out/opt_console_channels helpers
(+_var variants for triple-tail procs); documentation via shared
PUNKARGS fragment ::punk::console::argdoc::console_emit_opts
- fallback chains keep the console spec (get_tabstop_apparent_width ->
test_char_width; set_tabstop_width -> get_size)
- move_call_return now actually emits its cursor moves (previously
discarded the string-returning ansi::move results)
- get_size_using_cursorrestore uses string-returning
punk::ansi::cursor_on (was emitting to stdout mid-sequence)
0.3.0 (per-console facts, migration plan phase 3):
- is_vt52, tabwidth, cell_size, last_da1_result,
grapheme_cluster_support and check::has_bug_* keyed by canonical
{in out} pair via console_fact_get/console_fact_set; the default
console {stdin stdout} stores facts in the legacy namespace variables
so external readers (punk::repl, textblock, overtype, punk::ansi,
punk::ns) are unaffected
- vt52 state, size_via_query_mechanisms, get_cursor_pos and all
vt52-aware emit wrappers consult the spec'd console's is_vt52 fact
- grapheme_cluster_support and check::has_bug_* accept -console;
TERM_PROGRAM shortcut restricted to the default console
- check::has_bug_zwsp: cached-true path no longer errors; query
verdicts are now actually cached
- ansi_wanted/colour_disabled, ansi_available and raw-mode state
deliberately remain process-global (documented at the store)
PUNKARGS definitions follow the new Argument Order rule (@leaders for
leading positionals); internal helpers carry documentation-only
definitions. New suites: emitconsole.test (13) + consolefacts.test (9);
full console suite 49/49 on Tcl 9.0.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
3 weeks ago |
|
|
91178a458f |
punk::repl 0.2.0: wire interp_sync_package_paths into codethread and code interp for package prefer propagation
The codethread init_script now propagates package prefer via a new %packageprefer% scriptmap entry. The code interp (punk/0 repltype) creation replaces the manual epoch-only copy with punk::lib::interp_sync_package_paths code -libunknown 1, which propagates tm list, auto_path, package prefer, and libunknown epoch+init from the codethread to the code interp. This fixes the issue where package prefer latest set in punk_main.tcl was not inherited by the REPL's code interp, causing 999999.0a1.0 dev modules to be passed over in favour of stable VFS-bundled versions. |
3 weeks ago |
|
|
d9ea04ecb3 |
punk::lib 0.2.0: add snapshot_package_paths + extend interp_sync_package_paths with package prefer and -libunknown flag
snapshot_package_paths returns a script string reproducing the caller's tcl:™️:list, auto_path, and package prefer for use in thread::create init scripts. With -libunknown 1 it also copies the punk::libunknown epoch and sources+inits libunknown in the target. interp_sync_package_paths now propagates package prefer (was missing) and accepts optional -libunknown 1 flag for epoch copy + libunknown init in the child interp. Both procs have PUNKARGS argdoc documentation. Includes 6 tcltest tests covering basic propagation, version selection with package prefer latest, ordering preservation, snapshot script validity, -libunknown flag, and regression.
|
3 weeks ago |
|
|
4bd27338e7 |
tcltestrun 0.3.0: fix tm_path_additional_ifneeded project_root scope bug + dynamic #modpod version extraction
tm_path_additional_ifneeded referenced an out-of-scope \ variable that was never a parameter or local, causing 'can't read project_root: no such variable' whenever a #modpod module was found. The proc now requires project_root as a 2nd parameter. Additionally, the #modpod directory pattern was hardcoded to 999999.0a1.0 which the build system replaces with the real version (e.g 0.3.0) during make.tcl modules — breaking pattern matching in built bootsupport copies that looked for #modpod-*-0.3.0 directories which don't exist on disk. The proc now extracts both modname and version dynamically from the #modpod-<modname>-<version> directory name by splitting on the last dash, making it version-agnostic. Punk::lib::tm_version_magic convention was considered but dynamic extraction is preferred here as it will also work in the future src package_mode boot context where punk modules aren't loaded yet. |
3 weeks ago |