diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b6dfd2b..a9b870d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ The latest `## [X.Y.Z]` header must match the `version` field in `punkproject.to Entries are newest-first; one bullet per notable change. See the root `AGENTS.md` "Project Versioning" section for the bump policy. +## [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. diff --git a/punkproject.toml b/punkproject.toml index 91c14505..ef3246a8 100644 --- a/punkproject.toml +++ b/punkproject.toml @@ -1,3 +1,3 @@ [project] name = "punkshell" -version = "0.10.1" +version = "0.10.2" diff --git a/src/modules/AGENTS.md b/src/modules/AGENTS.md index bbd99ad7..e7a3e2e4 100644 --- a/src/modules/AGENTS.md +++ b/src/modules/AGENTS.md @@ -15,7 +15,7 @@ Source of truth for all editable Punk project modules. This is where agents shou - Module filenames use the literal suffix `-999999.0a1.0.tm`. - Corresponding `-buildversion.txt` files hold the real version number. -- The exception is `punk::libunknown`, which uses its own version `0.1`. +- The exception is `punk::libunknown`, which is manually versioned: its real `major.minor.patch` version lives in the filename (`libunknown-.tm`) and there is no buildversion.txt. The same bump rules apply as for buildversion-tracked modules (see "Versioning And Releases"); the mechanics differ — see the manual-versioning bullet there. - `#modpod-*` directories contain internal files packed into `.tm` archives during build; do not flatten or edit them without understanding the modpod format. - `_build/` directory holds build intermediates and should not be manually edited. - Always declare dependencies explicitly using `package require ` near file tops. @@ -321,7 +321,7 @@ return This keeps the changelog discoverable alongside the version number without requiring a separate CHANGES file. - **Bootstrap-tracked files only** — `punkcheck-buildversion.txt`, `punk/repo-buildversion.txt`, `punk/mix-buildversion.txt` (the top-level `punk::mix` file only; `punk::mix::util`, `punk::mix::cli`, and `punk/mix/commandset/*` version independently and are not covered by this check), and `punk/tdl-buildversion.txt`: bump at least **minor** whenever a call site inside that file is updated to use a new API, even if the file's own interface is unchanged. `src/make.tcl` reads only these four files to classify bootsupport staleness (major=abort, minor=prompt, patch=silent-proceed); under-bumping one of them to patch when the call-site change is more significant causes `make.tcl` to mis-classify and either wrongly proceed without prompting or wrongly abort. See `src/bootsupport/AGENTS.md` "Bootsupport Staleness Handling" for the full contract. - **All other modules** (including `punk::mix` submodules): call-site updates follow ordinary judgement from the Patch/Minor/Major rules above — a behavior-preserving call-site change is a patch (or no bump if genuinely a no-op); reserve minor for changes that add capability to the module's *own* API. `src/make.tcl` does not read these versions, so there is no automated consequence, but keep the changelog accurate since it is the only record of the module's real semantic version. -- There may be occasional exceptions such as `punk::libunknown-0.1.tm`, which is deliberately manually versioned; new modules should use the magic version mechanism. +- **Manually versioned modules** (currently only `punk::libunknown`): the real `major.minor.patch` version is the filename suffix and the `package provide` block value; there is no `-buildversion.txt` and the build does not stamp a version. The Patch/Minor/Major bump rules above apply identically — an agent changing such a module bumps by (1) renaming the file (`git mv`) to the new version, (2) updating the `# Application ` Meta line, the doctools `manpage_begin` version and the provide-block `set version`, and (3) appending a changelog comment line to the version-history block in the module header (it substitutes for the buildversion.txt changelog). Before the first bump of such a module, verify nothing requires it by exact version or hardcoded filename (for punk::libunknown: punk_main.tcl and punk::repl glob `libunknown-*.tm` and pick the highest by vcompare, bootsupport's include_modules.config lists it by name only, and all requires are unversioned - verified 2026-07-11). New modules should use the magic version mechanism instead. - Modules with the magic version number must not appear in output paths such as `/modules`. - When referencing ranges, use bounded specs such as `1.2.3-2.0.0`. - Convert loose versions to bounded form in module metadata; helper utilities exist in boot modules for this purpose. diff --git a/src/modules/punk/libunknown-0.1.tm b/src/modules/punk/libunknown-0.2.0.tm similarity index 98% rename from src/modules/punk/libunknown-0.1.tm rename to src/modules/punk/libunknown-0.2.0.tm index 4d9468a6..6319daf0 100644 --- a/src/modules/punk/libunknown-0.1.tm +++ b/src/modules/punk/libunknown-0.2.0.tm @@ -7,17 +7,34 @@ # (C) 2025 # # @@ Meta Begin -# Application punk::libunknown 0.1 +# Application punk::libunknown 0.2.0 # Meta platform tcl # Meta license MIT # @@ Meta End +# +# Version history (manually versioned module - the real version lives in the +# filename and the 'package provide' block at the bottom; there is no +# -buildversion.txt. Apply the standard Patch/Minor/Major bump rules +# from src/modules/AGENTS.md "Versioning And Releases" - bumping means +# renaming the file AND updating the Meta line above, the manpage_begin line +# below and the provide-block version, then appending a line here): +#0.2.0 - register_all_tm: deep discovery proc registering ifneeded scripts for +# .tm modules at every namespace depth (once per tm epoch, interp-local +# tm_fullscan guard); used by 'dev lib.search' by default +#0.2.0 - source_pkgindex: pkgIndex.tcl scripts execute in an isolated frame +# ($dir formal + auto_path/env global links) instead of at :: scope - +# user global 'dir' no longer clobbered, index helper vars no longer +# leak into the global namespace ('global dir' removed from +# zipfs_tclPkgUnknown) +#0.1 - initial: epoch-based zipfs_tm_UnknownHandler/zipfs_tclPkgUnknown +# package unknown chain, 'package epoch' command, controlled forget # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # doctools header # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ #*** !doctools -#[manpage_begin punkshell_module_punk::libunknown 0 0.1] +#[manpage_begin punkshell_module_punk::libunknown 0 0.2.0] #[copyright "2025"] #[titledesc {Module API}] [comment {-- Name section and table of contents description --}] #[moddesc {-}] [comment {-- Description at end of page heading --}] @@ -2102,7 +2119,7 @@ namespace eval ::punk::args::register { package provide punk::libunknown [tcl::namespace::eval ::punk::libunknown { variable pkg punk::libunknown variable version - set version 0.1 + set version 0.2.0 }] return diff --git a/src/tests/modules/punk/libunknown/testsuites/discovery/discovery.test b/src/tests/modules/punk/libunknown/testsuites/discovery/discovery.test index e4836591..49da9a41 100644 --- a/src/tests/modules/punk/libunknown/testsuites/discovery/discovery.test +++ b/src/tests/modules/punk/libunknown/testsuites/discovery/discovery.test @@ -117,17 +117,21 @@ namespace eval ::testspace { } #The SOURCE-TREE punk::libunknown, located relative to this test file. - #A 'package require punk::libunknown' would tie-break the same-version (0.1) - #copies in src/modules and src/bootsupport/modules by tm path order - in the - #testinterp that order deliberately favours bootsupport, and in a child interp - #it depends on machine-specific env tm paths. These tests must exercise the - #source copy, so it is sourced directly by path (as punk_main.tcl loads it). + #A 'package require punk::libunknown' could resolve to another copy (e.g + #bootsupport) depending on tm path order - in the testinterp that order + #deliberately favours bootsupport, and in a child interp it depends on + #machine-specific env tm paths. These tests must exercise the source copy, + #so it is sourced directly by path (as punk_main.tcl loads it), picking the + #highest version by vcompare should multiple libunknown-*.tm coexist. variable libunknown_src "" variable script_dir [file dirname [file normalize [info script]]] set srcmodules [file normalize [file join $script_dir .. .. .. .. .. .. modules]] - set candidates [lsort [glob -nocomplain [file join $srcmodules punk libunknown-*.tm]]] - if {[llength $candidates]} { - set libunknown_src [lindex $candidates end] + foreach candidate [glob -nocomplain [file join $srcmodules punk libunknown-*.tm]] { + set thisver [file rootname [lindex [split [file tail $candidate] -] 1]] + if {$libunknown_src eq "" || [package vcompare $thisver $libunknown_ver] == 1} { + set libunknown_src $candidate + set libunknown_ver $thisver + } } testConstraint libunknownavailable [expr {$libunknown_src ne ""}] if {$libunknown_src eq ""} { diff --git a/src/tests/modules/punk/mix/testsuites/loadedlib/libsearch.test b/src/tests/modules/punk/mix/testsuites/loadedlib/libsearch.test index 9718208f..4d4b858d 100644 --- a/src/tests/modules/punk/mix/testsuites/loadedlib/libsearch.test +++ b/src/tests/modules/punk/mix/testsuites/loadedlib/libsearch.test @@ -77,18 +77,21 @@ namespace eval ::testspace { # searches and -refresh walks are deterministic and fast. # ------------------------------------------------------------------------- #The SOURCE-TREE punk::libunknown, located relative to this test file. - #A 'package require punk::libunknown' would tie-break the same-version (0.1) - #copies in src/modules and src/bootsupport/modules by tm path order - these - #tests need register_all_tm from the source copy, so it is sourced directly - #by path (as punk_main.tcl loads it). The other punk requires below are dev - #alpha versions (999999.0a1.0), which 'package prefer latest' selects - #deterministically regardless of tm path order. + #A 'package require punk::libunknown' could resolve to another copy (e.g + #bootsupport) depending on version/tm path order - these tests need + #register_all_tm from the source copy, so it is sourced directly by path + #(as punk_main.tcl loads it), picking the highest version by vcompare. + #The other punk requires below are dev alpha versions (999999.0a1.0), which + #'package prefer latest' selects deterministically regardless of path order. variable libunknown_src "" variable script_dir [file dirname [file normalize [info script]]] set srcmodules [file normalize [file join $script_dir .. .. .. .. .. .. modules]] - set candidates [lsort [glob -nocomplain [file join $srcmodules punk libunknown-*.tm]]] - if {[llength $candidates]} { - set libunknown_src [lindex $candidates end] + foreach candidate [glob -nocomplain [file join $srcmodules punk libunknown-*.tm]] { + set thisver [file rootname [lindex [split [file tail $candidate] -] 1]] + if {$libunknown_src eq "" || [package vcompare $thisver $libunknown_ver] == 1} { + set libunknown_src $candidate + set libunknown_ver $thisver + } } variable child "" diff --git a/src/vfs/_vfscommon.vfs/modules/punk/libunknown-0.1.tm b/src/vfs/_vfscommon.vfs/modules/punk/libunknown-0.2.0.tm similarity index 98% rename from src/vfs/_vfscommon.vfs/modules/punk/libunknown-0.1.tm rename to src/vfs/_vfscommon.vfs/modules/punk/libunknown-0.2.0.tm index 4d9468a6..6319daf0 100644 --- a/src/vfs/_vfscommon.vfs/modules/punk/libunknown-0.1.tm +++ b/src/vfs/_vfscommon.vfs/modules/punk/libunknown-0.2.0.tm @@ -7,17 +7,34 @@ # (C) 2025 # # @@ Meta Begin -# Application punk::libunknown 0.1 +# Application punk::libunknown 0.2.0 # Meta platform tcl # Meta license MIT # @@ Meta End +# +# Version history (manually versioned module - the real version lives in the +# filename and the 'package provide' block at the bottom; there is no +# -buildversion.txt. Apply the standard Patch/Minor/Major bump rules +# from src/modules/AGENTS.md "Versioning And Releases" - bumping means +# renaming the file AND updating the Meta line above, the manpage_begin line +# below and the provide-block version, then appending a line here): +#0.2.0 - register_all_tm: deep discovery proc registering ifneeded scripts for +# .tm modules at every namespace depth (once per tm epoch, interp-local +# tm_fullscan guard); used by 'dev lib.search' by default +#0.2.0 - source_pkgindex: pkgIndex.tcl scripts execute in an isolated frame +# ($dir formal + auto_path/env global links) instead of at :: scope - +# user global 'dir' no longer clobbered, index helper vars no longer +# leak into the global namespace ('global dir' removed from +# zipfs_tclPkgUnknown) +#0.1 - initial: epoch-based zipfs_tm_UnknownHandler/zipfs_tclPkgUnknown +# package unknown chain, 'package epoch' command, controlled forget # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # doctools header # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ #*** !doctools -#[manpage_begin punkshell_module_punk::libunknown 0 0.1] +#[manpage_begin punkshell_module_punk::libunknown 0 0.2.0] #[copyright "2025"] #[titledesc {Module API}] [comment {-- Name section and table of contents description --}] #[moddesc {-}] [comment {-- Description at end of page heading --}] @@ -2102,7 +2119,7 @@ namespace eval ::punk::args::register { package provide punk::libunknown [tcl::namespace::eval ::punk::libunknown { variable pkg punk::libunknown variable version - set version 0.1 + set version 0.2.0 }] return