make.tcl modules + vfscommonupdate; old versions (args-0.11.2, tclcore-0.3.3)
removed by the update. All four kits (punkbi, punksys, punk91, punk902z)
rebuilt from the updated vfs and verified in kit mode: punk902z (9.0.2) and
punksys (8.6.13) both load args=0.12.0 tclcore=0.3.4, punk::args::formcheck
reports ::after as 6 forms / 15 pairs / 1 sanctioned structural overlap
(cancelid/cancelscript, zero unsanctioned) and ::lseq as the two unsanctioned
type_weakness findings ({range start_count} {range count}) on both runtimes.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
make.tcl modules + vfscommonupdate + project: all four kits rebuilt
(punkbi, punksys, punk91, punk902z). Kit-mode verification: punk902z
loads args=0.11.2 ns=0.5.0 tclcore=0.3.3 lib=0.4.3 punk=0.2.6, 'i join'
emits no bad-@dynamic warning; punksys (8.6) loads args=0.11.2 and the
after cancel-id discrimination resolves 'cancel someid' to the
cancelscript form (harvested id prefix working on 8.6).
A stale tcl_oauth2_library install leftover in the project's root lib/
tree (its src/vendorlib source was removed 2026-07-12; the libs install
step does not prune targets whose source vanished) was swept into the
vfs lib by vfscommonupdate and removed again before the kit build - it
is deliberately not part of the vendored set yet (G-065..G-068
first-test candidate). The root lib/ leftover itself was removed after
this commit was first authored; its rows remain in lib/.punkcheck.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Replaces args-0.5.0.tm with the built 0.6.0 (small restricted choice sets
display as literal alternates in synopses).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
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
Re-vendor the G-001 modules into bootsupport, the project-layout
bootsupport copies, and the runtime vfs: punk::repl 0.4.0 replaces 0.3.0
and opunk::console::tk 0.2.0 replaces 0.1.0.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
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
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
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
- 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
punkcheck-managed regeneration propagating the G-049 module releases (parse-status data model, machine-parsable cmdhelp returns) into src/bootsupport/modules, the punk.project-0.1 and punk.shell-0.1 layout bootsupport copies, and _vfscommon.vfs/modules.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Output of src/make.tcl refreshing bootsupport, vfs, and project_layouts
bootsupport trees to match the recently-bumped module versions.
Assisted-by: harness=opencode; primary-model=openrouter/z-ai/glm-5.2; api-location=openrouter.ai
New 'make.tcl vfslibs' step (also run inside 'make.tcl project' before kit vfs
assembly): propagates declared vendored platform-library packages into kit vfs
lib_tcl<N> trees, ending the hand-copying that let kits ship a known-buggy
tcludp through three make invocations (the G-036/G-037 motivating case).
- declaration: src/runtime/vendorlib_vfs.toml, parsed with bootsupport tomlish
(no ad-hoc parsing; G-024's mapvfs toml conversion NOT required first - this
file is recorded as a candidate for absorption into it). [install.<name>]
entries: source (relative to src/), targets (kit vfs lib folders relative to
src/vfs/), optional supersedes (folder names removed from each target before
install - explicit, no silent mixed-version provision per G-035 concerns).
- participation is per-package per-kit; authority is the declaration - nothing
syncs undeclared, so the known vendorlib/kit twapi drift is deliberately
untouched (resolves the direction/authority design question).
- punkcheck provenance at src/vfs/.punkcheck (gitignored, outside kit
payloads); skip-if-unchanged proven (rerun: 0 copied, 9 skipped per target);
malformed/unresolvable entries fail the build naming the entry (exit 3).
- 8.6 kits upgraded (the G-036 loose-end decision, recorded): tcludp 1.0.13 is
dual-generation (pkgIndex selects tcl9udp1013.dll on 9+, udp1013t.dll on
8.5+) so the single vendorlib_tcl9 source serves punk8win.vfs/lib_tcl8;
superseded udp1.0.12 removed.
- verified on rebuilt kits: punksys/punkbi (8.6.13) and punk902z (9.0.2) all
report package require udp == 1.0.13 loading the generation-appropriate dll
from their vfs; no udp1.0.12 remains under src/vfs; punksys piped-shell exit
smoke clean.
- G-037 flipped proposed -> achieved 2026-07-08 under user direction (no
intermediate active stop).
- includes project-build byproducts via established channels: bootsupport
snapshots refreshed to punk-0.2.1 / punk::lib-0.3.0 (from today's version
bumps) and make.tcl synced into layout copies.
- project 0.4.8 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Root cause: Tk registers a main loop (Tcl_SetMainLoop); tclsh''s Tcl_Main
services it after the script, so `tclsh gui.tcl` behaves like wish. The
script subcommand sourced-then-exited, so a Tk script''s after-callbacks
never ran (scriptlib/tktimer.tcl flashed and died; shell was the
workaround). Confirmed: native tclsh tktimer 1 blocks ~1.35s; script did
0.38s.
Fix: after the script body (success paths only), if a Tk main loop is
registered (info exists ::tk_version && winfo exists .), tkwait window .
services the event loop until the main window closes, then exit - the
script-level equivalent of Tcl_Main. A script that exits from a callback
(tktimer countdown) terminates directly. Console scripts have no main
loop and exit at once; a script error exits at once (no hanging window).
Verified both generations: tktimer via script now blocks the countdown
(punk902z 1.49s, punksys 1.57s - Tk present in both) exit 0; tkhello_exit
immediate; tk-script-that-errors exit 1 in 0.37s (no hang); tkhello (no
self-close) blocks like wish; console script unaffected. Enables G-020
GUI automation via `script` instead of `shell` (noted in G-020 detail).
Project version 0.4.1.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
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
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
New lean app package src/lib/app-punkscript behind the (previously stub)
script subcommand in punk_main.tcl:
- `<commands> | <punkexe> script` runs piped stdin to EOF - no trailing
exit needed; `<punkexe> script <file> ?args?` runs a file with
conventional ::argv0/::argv (bare non-subcommand first arg still
reclassifies to the file form). Script may itself read stdin in the
file form.
- Default punk shell environment via shared definitions (package punk
registers deck aliases e.g dev; punk::aliascore::init adds the utility
aliases) - no local alias lists, no boilerplate in piped one-liners.
- Honest exit codes: 0 success, 1 on error with errorInfo on stderr,
script''s own exit honoured. No shellfilter stacks/transforms, no
logging side effects, no interactive fallback (terminal stdin with no
scriptname is a usage error, never a blocking read or shell).
- Stdin form echoes the script''s final result when non-empty (one-shot
eval ergonomics: return-value commands like `dev projects.work <glob>`
emit their table without a puts wrapper); file form keeps pure script
semantics.
Verified on both generations (punk902z/tcl9 from _build - bin deploy was
file-locked; punksys/tcl8.6 from bin): piped success/error/exit-code,
file form with args and stdin passthrough, missing-file error, motivating
one-liner `dev projects.work *tomlish*` emitting the project table with
exit 0, `src` mode combination (dev modules load), and `shell` subcommand
regression smoke. G-015 flipped to achieved 2026-07-07 per GOALS.md
rules; goal detail records the verification and the manual console
spot-check item. Project version 0.3.0 (new user-visible shell
capability - minor bump).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
vendorupdate pulls tomlish 1.1.10 from a clean tomlish checkout: the
library API punk::config will consume now carries punk::args (PUNKARGS)
documentation - from_toml, to_dict, from_dict, to_toml,
update_tomlish_from_dict - completing the G-014 precondition
(documentation added upstream in the tomlish project, landed here by
re-vendoring, never by editing src/vendormodules copies). 1.1.10 also
carries the explicit tomlish::cmdline_main entry point (wrapped-exe
startup fix; the load-time argv side effect is gone).
vfscommonupdate refreshes the punkshell kit payload to the current built
modules: shellfilter 0.2.3 (channel-restoration try/finally), shellrun
0.1.4, punkboot::utils 0.1.1, punk::console 0.7.1 content catch-up, and
tomlish 1.1.10.
Project version 0.2.7.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Four project-layout template README.md files were untracked because the
layout templates' own nested .gitignore files are honoured by git as
nested ignores of the outer repo (fossil, which reads no nested ignore
files, already manages them). Two vendored critcl TODO.txt files were
swallowed by the unanchored 'todo.txt' ignore pattern matching
case-insensitively on Windows (core.ignorecase). All six force-added so
git's tracked set matches fossil's view; note force-adds protect only
these existing files - future files under the layout templates or new
vendored TODO.txt files will drop silently again unless the underlying
patterns are revisited.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Copies produced by the developer's src/make.tcl runs alongside the
punk::console work:
- _vfscommon.vfs: punk/console 0.1.7 -> 0.3.0 (final content),
punk/lib 0.1.6 -> 0.2.0, punk/repl 0.1.6 -> 0.2.0,
punk/tcltestrun 0.1.0 -> 0.3.0 (matching their committed source)
- bootsupport (root + punk.project/punk.shell layouts): punk/console
0.1.7 -> 0.2.0. NOTE: this snapshot was taken mid-development - it is
stamped 0.2.0 but already contains the 0.3.0 per-console facts code
(without the final PUNKARGS @leaders restructure). The next
'make.tcl bootsupport' run will supersede it with a true 0.3.0 copy.
The new 'src' package_mode loads unbuilt modules and libraries from the project's src/ tree (src/modules, src/lib, src/bootsupport, src/vendormodules) instead of built output. It differs from 'dev' mode which points at built <projectroot>/modules. The src mode also runs an inline #modpod package-ifneeded scanner using Tcl builtins only (since no punk modules are loaded at boot time) and sets package prefer latest so 999999.0a1.0 dev modules are preferred over stable bootsupport/vendored copies. The exhaustive permutation switch for package_mode parsing was replaced with token-by-token validation that scales to any number of modes. Verified: punk902z src launches an interactive shell with package provide punk returning 999999.0a1.0.
Resolves the build-maintenance TODO: built module trees no longer accumulate
superseded intermediate versions, and .punkcheck state stays consistent because
every deletion is recorded through punkcheck's event mechanism.
punkcheck (0.3.0):
- installsource_add_virtual + installevent method targetset_addsource_virtual:
'virtual' named-value SOURCE records (-type virtual -path virtual:<id> -value <v>)
compared by stored value, participating in targetset_source_changes. Needed
because successive module versions are built from the same physical source
files - the recorded virtual module_name/module_version identify which
product of the source fileset a target is, at install and delete time.
punk::mix::cli (0.5.0):
- lib::prune_superseded_target_modules: deletes lower-version .tm siblings only
when records prove the same module line (virtual module_name match, or legacy
fallback: recorded sources share the keep-version's source folder(s) and name
prefix). Unrecorded files are never deleted - reported to stderr instead.
- lib::prune_sourcevanished_targets: mirror-prune of recorded targets whose
recorded source files no longer exist (layout bootsupport copies, vendormodule
copies) - intentional multi-version vendoring is preserved.
- build_modules_from_source_to_base prunes after each module install/skip and
records virtual module identity sources on installs.
make.tcl:
- bootsupport: non-glob include_modules.config entries track only the latest
version - superseded recorded snapshot versions pruned; project-layout copies
mirror-pruned; virtual identity recorded on snapshot installs. Calls guarded
(info commands) so a stale bootsupport snapshot degrades to a warning and the
two-pass modules+bootsupport bootstrap self-heals.
- vendormodule copies in root modules*/ mirror-pruned after install.
docs/config:
- include_modules.config headers now document the entry format (non-glob =
latest-only + prune; glob chars = keep all matches; unrecorded never pruned)
- src/AGENTS.md TODO replaced with the durable prune contract;
src/bootsupport/AGENTS.md + src/tests/modules/AGENTS.md updated
tests: src/tests/modules/punk/mix/testsuites/cli/prune.test (19 tests) covering
virtual source recording/comparison and prune identity/safety rules.
Suites: punkcheck 64/64, full suite under Tcl 9.0.3 green except pre-existing
exec-14.3.
payload sync: bootsupport snapshots, project layouts and _vfscommon.vfs pruned
of superseded intermediates (~570k lines of stale .tm copies removed).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
opunk::console (0.3.0):
- base size method resolution order: -winsize fast path -> capability gate (settled or heuristic
can_respond; unresponsive consoles get default_size with no query emission) -> pluggable
::opunk::console::size_query_provider -> default_size. The provider hook follows the
waiting-store pattern: the class carries no punk::console dependency, and non-channel
subclasses (tk widget / channel-environment terminals) simply override size.
punk::console (0.1.7):
- get_size dispatches object-governed calls through the virtual ::opunk::Console::size method
after first-use settling - subclass size overrides are honoured from every punk::console
call site
- ANSI/tput mechanisms + per-pair timing cache factored into size_via_query_mechanisms, shared
by the legacy channel-pair path and the registered provider (console_size_provider)
- integration wiring consolidated into once-latched ensure_object_integration (probe-byte store
redirect + provider registration, respecting customised providers), invoked from
default_console, console_spec_resolve lazy-require sites and the get_size object path
- legacy path returns the documented 80x24 fallback instead of erroring when undetermined
tests: WidgetishConsole subclass override returned through punk::console::get_size for both
anchored-name and object-value specs; class-level provider consultation/capability-gating with
a counting fake provider; provider registration assert. Console suites 27/27 + 10/10; punkexe
6/6, goals 8/8; full suite green except pre-existing exec-14.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
opunk::console (0.2.0):
- probe-byte waiting store changed from dict to array (::opunk::console::waiting_chunks) and made
pluggable via waiting_chunks_arrayvar: integrating layers redirect it to their established
cooperative store so bytes consumed by opunk::Console probe reads stay visible to active readers.
The class remains free of punk::console dependencies - redirection is the integrator's act.
punk::console (0.1.6):
- default_console redirects the opunk::console store to punk::console::input_chunks_waiting
(closing the split-store hazard that previously made opunk-level probes invisible to the
punk repl reader)
- get_ansi_response_payload performs first-use active settling for persistable console specs,
guarded by a recursion latch around settle_can_respond's own probe: every query path
(get_cursor_pos, get_device_status, ...) now pays at most one settling probe instead of a
fresh timeout per call on unsettled ambiguous consoles
punk::repl (0.1.6):
- repl::init routes default console construction through punk::console::default_console
(deduplicates creation logic and gains the store unification)
tests: store-unification and get_cursor_pos first-use settling cases in consolespec.test
(zero-emission and persistence asserts); consoleclass.test store assertions converted to array
form. Console suites 25/25 + 9/9; punkexe 6/6, goals 8/8; full suite green except pre-existing
exec-14.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
punk::console (0.1.5):
- settle_can_respond: layered active settling of a console's response capability, persisted on
the anchored opunk::console instance. Layer 1 certainty (input eof -> 0, no emission),
layer 2 strong-negative heuristic (plain pipe, no terminal hints -> 0, no emission - piped/CI
output streams stay clean), layer 3 active CSI 6n probe with timeout, only in the ambiguous
zone (real consoles / pipe-presenting terminals such as mintty without winpty). -force
unsettles and re-probes; -timeout_ms overrides can_respond_probe_timeout_ms (default 500).
Unmatched input consumed while waiting is preserved via input_chunks_waiting.
- get_size triggers first-use settling for persistable specs only (anchored instance name or
the auto-attached default) so unanchored object values cannot cause per-call probes
- get_ansi_response_payload only cycles console raw mode when the input channel is a
console/tty: pipe-targeted probes no longer flip the real console's mode as a side effect,
and a repeat-cycle deadlock under captured-channel environments (runtests runx) is fixed.
(Latent enableRaw_twapi/disableRaw_twapi restore asymmetry noted for future attention.)
punk::repl (0.1.5) / opunk::console (0.1.1): docs reference the active settling mechanism
(no behaviour change; probe machinery stays in punk::console so the class remains free of
that dependency)
tests: 5 new settle_can_respond cases in consolespec.test - certainty and clean-pipe settling
with zero-emission asserts, ambiguous probe timeout with emission and input-preservation
asserts, response arrival settling 1 with realistic event-loop delivery then -force
transition to 0, and get_size first-use settling. Console suites 23/23; full suite green
except pre-existing exec-14.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com