The '### runtests DONE at <ts>' human line gains '(elapsed <N>s)', the
RUNTESTS_RESULT summary line gains a trailing elapsed_seconds=<N>
key=value, and the json report gains a top-level "elapsed_seconds"
field - matching the name already used by the watch-mode run-end event,
which now shares the same computed value. Additive only; the parity
tool reads named keys and is unaffected (verified on all three report
styles).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-directed from the G-092 measurement findings: a single
-include-paths value with four deep patterns matched only one subtree,
and repeated -include-paths flags matched zero files, both under the
default *.test tail glob - contradicting the documented accumulate
semantics. Context records the full repro matrix (multi-pattern forms
with explicit tails worked; standalone globmatchpath matched the same
patterns, implicating the treefilenames walk/prune or option-value
shape), the candidate root causes, and the tail-glob workaround. Notes
record that treefilenames already implements -exclude-paths unexposed
by runtests - the planned middle-ground option should be pinned by the
same regression suite.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
multishell.test (10 tests, ~105s solo child - the -jobs floor) split five
ways along shared-fixture boundaries, every test moved verbatim with its
provenance lines: multishell.test keeps wrap + structure/LF-only + exec
smoke (incl WSL); multishell_wrapverify.test (fresh-wrap checkfile) and
multishell_wrapdeterminism.test (byte-identical re-wrap) each re-pay the
wrap fixture; runtimecmd_checkfile.test and runtimecmd_roundtrip.test
guard the committed bin/runtime.cmd and its source round-trip with no
wrap fixture at all. argparsingtest.test (17 tests, ~32s) split into
timeit/discover/contract/first_call (11) + argparsingtest_compare.test
(compare_*, 6). Assessed and left unsplit: dtplite.test (24.6s solo),
scriptexec.test (12s); exec.test excluded as imported core material.
File headers point at the src/tests/modules/AGENTS.md punk/mix bullet
for the sibling map; the runtests longest-first weight table carries
measured post-split weights.
runtests_parity.tcl gains a -names mode: multiset comparison of
'- testname:' lines from '-report markdown -show-passes 1' captures,
file attribution ignored - verbatim moves compare identical, lost/
duplicated/renamed tests are reported.
Verified (native tclsh 9.0.3): repeated -jobs 8 full-suite runs 1m26.3s
/ 1m26.8s (was 2m16s at G-091, ~5m40s sequential - 4.07x vs the
pre-parallel baseline, 36.6% vs the G-091 reference); slowest child
30.7s / 31.3s (bound 45s); NAMES identical (989 occurrences) vs the
pre-split sequential capture; tallies identical in every run (989/973/
15/1, exec-14.3 sole failure, files 87 -> 92); PARITY ok -jobs 8 vs
-jobs 1 and between repeats; repo clean after runs. Notable finding
recorded in the goal file: child-wall contention inflation (~45% with
50s+ dominant children present) collapsed to ~15% once the work
distribution was flattened - splitting reduced both the critical path
and the contention itself.
G-092 flipped to achieved 2026-07-19 and archived (GOALS-archive.md
record, detail file with full verification evidence to goals/archive/).
goals_lint clean. Also noted in the goal file, out of scope: runtests
-include-paths multi-pattern/repeated-flag matching misbehaved during
measurement (single value with four deep patterns matched one; repeated
flags matched zero) - contradicts documented semantics, needs its own
investigation.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved draft from the G-091 verification data: multishell.test's
~2m child wall is the -jobs floor (full-suite -jobs 8 = 2m16s); splitting
the long suites (multishell, dtplite, argparsingtest, scriptexec if
worthwhile; exec.test excluded as imported core material) along
shared-fixture boundaries targets no child wall above 45s and at least a
25% full-suite improvement, with name-level test conservation, provenance
lines travelling with moved tests, weight-table updates, and parity
gating. Context records the fixture-duplication tradeoff (total CPU up,
wall down) and the complementary lean-children candidate.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- User Preferences: never open/update fossil checkouts with tip (newest
check-in on ANY branch); name the branch explicitly and verify the
fossil status tags line. Prompted by TEMP_REFERENCE/tcl9 being parked
on manifest-in-rc-only since 2026-07-08 via a tip checkout race.
- Child DOX Index: add missing TEMP_REFERENCE/ entry (VCS-ignored,
machine-local reference area; tcl9 nested fossil checkout stays on
trunk). The local TEMP_REFERENCE/AGENTS.md carries the refresh
procedure but is unversioned by design.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
-jobs N (implies -singleproc 0; explicit -singleproc 1 conflicts) runs
test files through a tpool of N concurrent child processes with
per-child capture files and tcltest -tmpdir subdirs, longest-first
static-weight submission, and a -serial-paths serial tail (default: the
console-state suites modules/punk/console/** + modules/opunk/console/**;
piped-child-driven suites proved parallel-safe and each serial file
costs its full child boot strictly after the parallel phase). Cached
results feed the unchanged processing loop in discovery order, so
reports are identical in shape and order to sequential runs. Watch mode
emits file-collected events (completion order, output relayed there);
file-end (tallies) stays discovery-order. The runner now reports jobs
phase times and the ten slowest child WALL times (child wall includes
boot + file-level fixture cost that per-test usec misses).
Two Tcl-core-level behaviours found and worked around in the child
spawn (see the verification record in the archived goal file):
- concurrent BLOCKING execs from worker threads convoy on Windows (all
return at the longest concurrent child's exit; plain sleepers 2-12s
from 8 workers all walled at 12.0s) -> spawn via 'exec ... &' and
poll per-pid tcl::process status; blocking fallback retained for
runtimes without tcl::process (tcl 8.6).
- Tcl_ReapDetachedProcs runs on every exec and purges finished
background children process-wide, racing the poll (nondeterministic
'key <pid> not known in dictionary') -> tcl::process autopurge false
+ explicit per-pid purge after the status read.
Verified on native tclsh 9.0.3: repeated -jobs 8 full-suite runs
2m16.2s / 2m15.6s with PARITY ok vs -jobs 1, between repeats, and vs
the pre-parallel baseline (987-test identity, exec-14.3 sole expected
failure); 2.58x vs the ~350s sequential baseline (2.41x vs one
cooler-machine 5m28.8s sequential run - recorded in the goal file);
repo clean after every run.
G-091 flipped to achieved 2026-07-19 and archived (entry to
GOALS-archive.md, detail file to goals/archive/ with the verification
record; reference sweep updated runtests.tcl comments and the
src/tests/AGENTS.md marker). goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Convert punk::config from a manually-versioned module (config-0.1.tm) to
the standard magic-version scheme (config-999999.0a1.0.tm +
config-buildversion.txt, real version 0.2.0) per user direction -
punk::config was never in src/modules/AGENTS.md's manual-versioning
exception list (punk::libunknown, punk::mix::base only). No callers pin
the old version; built/bootsupport/vfs copies remain 0.1 until the next
make run, as usual.
Includes the user-authored registration of PUNK_TEST_UDPTEE in the known
punk env vars table (runtests UDP watch mode / runx -teelog, a65f9e5b -
see src/tests/AGENTS.md). CHANGELOG 0.15.0 entry extended accordingly.
Verified: package require punk::config resolves 999999.0a1.0 under the
dev module paths (package prefer latest); focused runtests spot run
green. The env vars table is materialized inside the config init proc,
so registration is exercised at shell boot rather than package load.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Both user-approved 2026-07-18 from the runx -teelog / runtests watch-mode
work (a65f9e5b) and the -singleproc 0 completion (218fbb1c).
G-090 records the probe evidence deliberately not addressed in that work:
float-placement starvation of a tee under the float-locked capture
junction, insert_transform re-instantiation churn, parked-worker adoption
never re-applying settings (silent cross-target log misrouting), the
per-file teehandle worker-thread leak in unwatched singleproc runs, and
the tcludp Tcl 9 receive-fileevent first-datagram-only behaviour.
G-091 is the phase-2 parallel test plan over the phase-1 child spawn:
tpool -jobs N, per-child tmpdirs, serial group for console-sensitive
suites, parity + >=2.5x acceptance (floor ~90s, multishell.test bound).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
runx -teelog {-tag/-syslog/-file/-raw settings}: live tee of the
captured stdout/stderr to shellfilter::log workers (log sources
<tag>stdout/<tag>stderr) while captured/returned data is unchanged.
Implemented as write traces on the capture variables rather than extra
channel transforms: probing showed a tee_to_log float combined with the
float-locked capture junction is starved or loses its worker settings
through add/remove churn (float-placement logic is unaudited - README
'very unripe parts'), and shellthread's parked-worker adoption does not
re-apply settings (writes silently misroute to a previous target). Both
findings deliberately not addressed here - recorded for a proposed
shellfilter/shellthread audit goal. Tag workers stay open for reuse;
conflicting reconfiguration errors explicitly.
runtests.tcl watch mode: env PUNK_TEST_UDPTEE=<port>|<host>:<port>
streams runner lifecycle events (tag 'runtests', tcl-list
RUNTESTS-EVENT messages: run-start/file-start/file-end/run-end with
tallies) and test output (tags teststdout/teststderr) to a local UDP
listener via the same mechanism - live per chunk in singleproc mode
(runx -teelog inside the testinterp), relayed per completed file by the
parent in multiproc mode. Watch mode terminates the per-testinterp log
worker threads after each file; unwatched runs are unchanged (including
the pre-existing teehandle-worker leak, also noted for the audit). The
parent extends auto_path with <projectroot>/lib_tcl<N>/<arch> so
workers load tcludp 1.0.13+ (1.0.12 UDP_ExitProc = G-036 exit-hang
class).
Verified on native tclsh 9.0.3: full-suite result parity (87 files, 989
tests, exec-14.3 sole failure) for watch-off and watch-on singleproc
runs vs the pre-change baseline; focused watch runs in both modes
captured over UDP (events + live/relayed output). Viewer-side caveat
documented: tcludp's receive fileevent under Tcl 9.0.3/Windows
delivered only the first datagram (send side unaffected; .NET UdpClient
received all).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Multi-process mode previously execd bare test files with no environment
(children died on their first package require) and misreported the
crashes as missing-cleanupTests warnings with the stderr discarded.
- testsupport/child_test_runner.tcl (new): per-file child bootstrap.
Applies a runtests-generated environment payload (prefer latest, test
tm paths, auto_path, modpod ifneeded defs, tcltest options; per-file
-testdir computed child-side), warms 'clock format' before the
module-path wipe (first script-level clock use loads msgcat from the
runtime default paths, which the test paths do not supply), and
mirrors the testinterp preload: package require shellrun plus one
no-op runx -tcl call (runx execution pulls punk::lib; several suites
depend on preloaded punk::* commands).
- runtests.tcl: generate the payload per run; spawn children via plain
exec with file-captured stdout/stderr and immediate-EOF stdin
(mechanism reusable for future parallel -jobs scheduling); classify
nonzero child exits as file-level failures with the stderr tail
surfaced in all report styles (exit-0-no-summary remains the
missing-cleanupTests warning); warn under kit executables (children
boot with kit-stamped punk packages preloaded, shadowing src dev
modules - prefer a native tclsh).
- scriptlib/developer/runtests_parity.tcl (new): compares two
'-report json' captures on result identity (per-file counts,
failure/skip/warning identities; timings ignored), tolerating
preamble noise and the ANSI SGR reset emitted on the JSON line.
Verified on native tclsh 9.0.3: full suite singleproc vs multiproc
PARITY ok (87 files, 989 tests, 973/15/1 with the documented exec-14.3
baseline as the sole failure); crash and warning classification
exercised. Wall time ~5m50s in both modes.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Refresh via make.tcl modules + vfscommonupdate after the argparsingtest
1.0.0 restructure: _vfscommon.vfs swaps argparsingtest-0.2.0.tm for the
version-stamped 1.0.0 build. argparsingtest is not in the bootsupport
include_modules.config, so no bootsupport snapshot is affected (the
stale src/bootsupport/modules/argparsingtest-0.1.0.tm remains a known
prune leftover). Kit builds (make.tcl project) not run this change-set.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Restructure of the parser-timing module around three calling styles:
- parser procs move into per-style child namespaces argparsingtest::opts /
::tkstyle (2 leading positionals) / ::tclstyle (2 trailing positionals),
with identical short proc names across styles; the test1_ prefix is gone
- hand-rolled parsers share a manual_ prefix (manual_ni, manual_switch,
manual_prefix, ...) so they group visually in the comparison tables;
test1_prefix2 removed (not meaningfully distinct from test1_prefix)
- tkstyle/tclstyle carry a representative roster (manual_switch baseline +
punkargs/punkargs_by_id/punkargs_parsecache + opt + cmdline + tepam);
style parsers return a {p1 p2 opts} list
- new 'unsupported' discovery status for library/style combos the backing
library cannot express: cmdline with leading positionals (getoptions stops
at the first non-option word - probe verified), argp with any positionals
(parseArgs walks the whole list as option pairs - source verified).
compare renders these as N/A rows below the timed rows so every library
still appears in every style's table
- harness procs (discover_parsers/timeit/first_call/compare) gain
-style all|opts|tkstyle|tclstyle and return results keyed by style;
-args requires a single -style (each style has its own default vector);
external probe keys drop the test1_ prefix (getopt/parse_args/argparse/cmdr)
- punkargs_by_id variants keep the eager punk::args::define as sole doc
source (the former duplicate argdoc lappend made the lazy namespace scan
undefine/re-register the id on first introspection); unused struct::set
require dropped; opt/cmdline/tepam requires hoisted to module top;
first_call library warm-ups extended with positional coverage
- test suite rewritten: 17 tests including per-parser {p1 p2 opts} contract
checks across both positional styles, N/A table rendering, roster counts
and the -style/-args error paths
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New goal (user-approved wording): make.tcl bakes a curated scriptlib into
kit vfs app/scriptlib so standalone binaries have working lib: scripts, with
precedence following the packagemode mental model - kit-internal-wins only
for the default 'internal' launch, src/dev modes putting the live project
scriptlib first, and proj: (G-033) adding the visited project's scriptlib.
Context records the 2026-07-18 findings: kit-internal resolver branch never
exercised (no build path exists), not-overridable policy scoped to default
mode per user direction, missing boot->runtime packagemode hint, cookfs
mount-root gap, and the out-of-scope app-shellspy mapping. goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Batch refresh via make.tcl packages/bootsupport/vfscommonupdate: punk::path
0.2.2 -> 0.3.0 (extensionless lib: tcl identification - this change-set),
plus promotion of punk::args 0.12.6 and punk::ns 0.9.0 built at the previous
source commit. vfscommon lib copies of app-punkscript/app-punkshell/
app_shellrun pick up the shared scriptlib_resolve refactor. Includes the
project-layout bootsupport snapshot copies (punkboot-bootsupport installer).
Kit deploys to bin/ for punk91.exe and punk902z.exe were blocked by running
shell instances holding the executables (build reported the failed deletes);
rerun make.tcl project (or close the shells first) to deploy - tests were
run against the freshly built kit from src/_build.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
scriptlib_resolve now lets an extensionless (or unknown-extension) lib:<name>
call match a file named exactly <name> when its first lines identify it as
tcl: a leading '# tcl' comment (prefix, case-insensitive), a shebang naming
tclsh/tclkit/wish, or the portable sh-trampoline ('#!/bin/sh' with a
commented 'exec tclsh' continuation - detected within the first 4 lines).
New internal punk::path::system::scriptfile_is_tcl does the bounded sniff
(512 bytes, UTF-8 BOM and CRLF tolerated, directories/unreadable files
rejected). When both <name> and <name>.tcl exist, the spelling matching the
call wins, checked per scriptlib location so kit-internal directory
precedence is never crossed by a spelling preference.
.kit joins the known extensions: lib:<name>.kit previously had .tcl appended
(searched <name>.kit.tcl), which made the shell subcommand's do_tclkit
dispatch arms unreachable - lib: kit dispatch is now restored. Result dict
reworked: scripttype (tcl/kit/py/pl/ps1/sh or empty) + notes keys added,
scriptname is now the matched relative name, and matches require file isfile.
app-punkshell and app_shellrun lib: handling refactored onto the shared
resolver (previously independent inline copies of the policy), fixing two
silent-failure bugs in that copy: no message at all when a scriptlib dir
existed but lacked the script, and the error listing showing
<kit>/scriptlib rather than the <kit>/app/scriptlib actually checked.
app-punkscript's post-resolve gate now uses scripttype and its not-found
report includes the identification skip notes. The unused has_globchars
vestige is dropped.
Fixtures scriptlib/_punktest/{extless,dual,dual.tcl,shebang_sh,notatcl} and
5 new scriptexec.test cases (extensionless resolve, both precedence
directions, trampoline shebang + argv, non-tcl skip note on not-found);
suite passes 17/17 against a freshly built punk902z kit. Sniff helper unit
checks pass under tclsh 9.0.3 and 8.6. punkshell project 0.13.0 -> 0.14.0.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
punk::ns 0.9.0: cmdhelp (i) gains -return text - plain-text argument
documentation for machine/LLM consumption: no ANSI, no table layout, the
argument section of every command form rendered in one output under a common
header ('i -return text after' shows all six forms), G-041 form selection
still honoured when argument words are supplied, no advisory-parse error
preamble (-return dict remains the parse-status surface). Implementation
delegates resolution to the -return dict recursion and renders per-form via
the string renderer.
punk::args 0.12.6 (user direction; string-form layout explicitly not frozen -
no external consumers yet):
- arg_error renders the error message + per-form match detail exactly once,
BELOW the usage display (was above and below); bottom append suppressed for
empty messages.
- string renderer argument rows are single-line
'name TYPE:type(constraints) ?DEFAULT:'val'? ?MULTI:yes?' - type
constraints parenthesize onto the base type instead of line-breaking
mid-row; empty DEFAULT/MULTI labels and whitespace-only help blocks omitted.
- choices render as markdown-subset bullets '- `choice` - label' with label
continuations at a fixed deeper indent - choice names are now
machine-distinguishable from label text without ANSI. Structural contract:
column-0 lines bearing TYPE: are argument rows, indented lines are
documentation, backticked bullets are choices. Table cells unchanged.
New scriptlib/developer/whatis.tcl (runtime command introspection for
agents): resolved name, subcommand-chain resolution via punk::ns::cmdinfo
('whatis string is'), kind, providing package + loaded version, origin file,
proc definition file:line, punk::args synopsis; -body appends the runtime
body with file-relative line numbers, -doc the full plain-text argdoc via
cmdhelp -return text (with fallback for older punk::ns). Backing the
cross-framework tcl-whatis agent skill: canonical .agents/skills/tcl-whatis/
(Agent Skills standard - pi/OpenCode/Codex) with byte-identical copy in
.claude/skills/ for Claude Code; .gitignore gains !.claude/skills/ with the
fossil ignore-glob comment + exception-set docs updated per the dual-VCS
contract (fossil adds staged). Root AGENTS.md: .agents/skills index entry,
whatis pointer in Repo-wide Notes, scriptlib/developer example.
Tests: new pins cmdhelp_return_text_all_forms/_argword_form_selection/
_single_form_plain_marker (cmdhelp.test), rendering_stringmode_singleline_argrows
+ rendering_stringmode_choice_bullets (rendering.test); deliberate-change pin
updates: errorselection.test message matches gained leading * and cmdhelp.test
message pins sample the last line (message placement). Full source-tree suite
963/979 pass, sole failure the pre-existing exec-14.3 baseline; make.tcl
modules clean.
Project version 0.12.42 -> 0.13.0 with CHANGELOG.md entry.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
make.tcl modules/bootsupport(x2, 2nd pass copied 0)/vfscommonupdate/project
sequence per the workflow overview. Kit vfs payload and bootsupport module
sets (incl project_layouts bootsupport copies) updated to the new built
versions; superseded 0.12.4/0.8.0/0.1.0 copies removed.
Kits: punkbi.exe and punksys.exe rebuilt and deployed (punksys verified
carrying 0.12.5/0.8.1/0.2.0); punk91.exe and punk902z.exe deployment skipped -
target binaries in use by running shells - redeploy after closing them.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Goal for embedding a short marker in the usage/error table's bottom frame edge
(bottom-right @examples indicator, counterpart of the top 'Usage' title). Two
severable deliverables: frame-parity -subtitle/-subtitlealign on
textblock::class::table (must work with or without footer rows), and footer
rows with column spans independent of the body via configure_footer mirroring
the header API (the -show_footer/-ansibase_footer/-ansiborder_footer styling
knobs already exist but no footer-row methods do). arg_error's interim
'Example:' header row retires when this lands.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
parse -cache overhaul:
- VALIDATION trap's parse_cache write now explicitly gated on -cache (formerly
unconditional but landing in a discarded proc-local for -cache 0 by scoping
accident - 'variable parse_cache' only ran on the -cache 1 branch)
- cached validation errors stored as per {errorstyle callertext} render
variants under a {arglist definition form} main key (-caller dropped from the
main key - results don't depend on it); a missing variant falls through to a
fresh render. Previously the first caller's errorstyle and %caller%
attribution were baked in and replayed verbatim to later callers.
- @dynamic definitions (and legacy leading '-dynamic 1') are never cached so
re-evaluated substitutions always take effect; dev/dynamic-cache.test
known-bug pin flipped
- new punk::args::parse_cache view/clear proc (sgr_cache style); guarded
variable init; -errorstyle definition default corrected to the operative
'standard'. New parsecache.test (7 tests).
synopsis notation + internal @form -synopsis retirement:
- ::punk::args::parse/::parse_status dropped their stale @form -synopsis
overrides (omitted -cache/-caller) for auto-generated lines shaped with
-typesynopsis {<int|formname>...} on -form; drift pin
synopsis_parse_generated added
- punk::ns::synopsis no longer errors on custom @form -synopsis lines that are
not valid Tcl lists (e.g Tcl manpage style '?-form {int|<formname>...}?' -
's parse' raised 'list element in braces followed by ...'): non-list lines
take a textual command-head replacement fallback
- @form -synopsis directive help rewritten (display-only, any style, prefer
auto-generation, known warranted case: script-level/constructed ids);
::punk::args::synopsis -help gains a notation legend and a new @examples
block comparing Tcl man-page ?...? style with the bracket style (punk::args::eg)
eg usability + examples indication:
- punk::args::eg resolves relative/unqualified command names (punk::ns::cmdinfo
from calling context when loaded, else global qualification) - in namespaces
where it shadows the global 'eg' alias (e.g ::punk::args) 'eg list' returned
empty while 'i list' worked; unknown ids now return a message naming the id;
punk::ns::eg hands the typed name through on unresolved docids
- usage-table 'Example: eg <id>' header row now uses scheme colour CLR(check)
(interim display until G-088 footer/subtitle support)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New procs timeit/compare/discover_parsers/first_call for rough cross-parser
performance comparison (punk::args variants vs hand-rolled dict/switch/prefix,
tcllib opt/cmdline/tepam, argp), with PUNKARGS argdoc coverage throughout.
first_call times each parser twice in fresh child interps:
- cold: first call after package load (includes byte-compilation of the parser
proc body and any backing-library procs it invokes)
- warm: the backing library is pre-exercised via per-library sacrificial
warm-up scripts (library_warmups dict) so the timed call isolates per-proc
first-use cost. Replaces an earlier punk::args-only
'punk::args::parse {} withdef {}' warm hack that was unfair to the other
libraries under test and only partially warmed punk::args itself.
Child interps pin package requires to the parent's loaded versions
(punk::args, punk::lib when present, argparsingtest) - plain package require
prefers stable versions, so children otherwise timed older stable copies
visible on the module paths instead of the dev module under test; under
Tcl 8.6 the punk::lib pin also supplies the lpop compat shim punk::args::parse
needs, unbreaking punk::args timing in bare child interps there.
compare renders first_cold/first_warm columns (table), nested cold/warm
sub-dicts (dict/json). New test suite under src/tests/modules/argparsingtest.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Prints the release-ready command sequence, source -> built-packages ->
bootsupport / kit-vfs / kit-executable folder-flow diagrams, and keyed notes
(magic-version stamping, punkcheck provenance, staleness gate, -confirm
policy, locked-exe deploys, VCS-tracked output targets). The text is embedded
in make.tcl (::punkboot::workflow_text) rather than a data file so it travels
with the make.tcl copies seeded into generated-project layouts; content is
project-generic accordingly. A MAINTENANCE key in the output states the
update contract.
punk::args-documented via the existing constructed-definition machinery
(SUMMARIES/HELPTEXTS/SUBOPTS + informational SUBGROUPS entry) so tabled help,
'help workflow' and the top-level subcommand table all cover it; also
registered in known_commands and the plain punkboot_gethelp fallback, and
exempted from the bootsupport staleness gate alongside check/projectversion.
Verified in normal and PUNKBOOT_PLAIN dispatch; stray arguments raise a
punk::args toomanyarguments usage error; output is pure ASCII, width <= 100.
src/AGENTS.md Work Guidance gains the agent update contract: change the
workflow text in the same change-set as any build data-flow change, keep the
ASCII/width/structure rules, verify with 'make.tcl workflow' (+ one
PUNKBOOT_PLAIN run), and the registration-point checklist for subcommand
changes. Layout make.tcl copies propagate via 'make.tcl bootsupport' - never
hand-synced. punkshell 0.12.42.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
make.tcl vfscommonupdate -confirm 0 after the 0.12.4 modules build. Besides
punk::args 0.12.3 -> 0.12.4 (collision-aware resolve miss path), the REPLACE
pass brought _vfscommon.vfs up to date with built modules that had not been
propagated since the 0.12.37 refresh: cap handlers templates 0.2.0, mix
base 0.1.1, mix commandsets layout/module/scriptwrap 0.1.1 + project 0.2.2,
mix templates 0.1.5, fauxlink 0.1.2/0.2.0, tomlish 1.1.12 + test module
catch-up (test/tomlish-1.1.5 content matches built copy).
make.tcl project -confirm 0 rebuilt the kits: punkbi.exe and punksys.exe
deployed to bin/; punk91.exe and punk902z.exe builds succeeded but
deployment to bin/ was blocked by running shell instances holding the
binaries (fresh kits left in src/_build - redeploy after closing shells).
Kit executables are not tracked; this checkin is the vfs source tree only.
argparsingtest work (module 0.2.0, tests) deliberately left uncommitted;
its derived vfs artifacts (argparsingtest-0.1.0.tm removal / 0.2.0.tm
addition) are likewise excluded from this checkin.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
resolve's first-sighting path for a rawdef whose @id is already registered
with different content now purges the id's existing cache entries (quiet
undefine) before registering, mirroring define's re-creation behaviour.
Previously it repointed id_cache_rawdef while stale rawdef_cache_about /
rawdef_cache_argdata entries lingered - two rawdefs claimed the same id and
a subsequent define with the original text was a silent no-op (stale
cache-about hit), leaving withid lookups stuck on the inline definition.
The disabled blanket "called with undefined id" stderr warning is removed -
it flagged supported inline usage (parse ... withdef, direct resolve
calls). Guard checks id_cache_rawdef directly (id_exists also matches
aliases, where the rawdef lookup would error). Known residual: the miss
path still records no -defspace for @dynamic definitions first seen via
resolve.
New define.test pin define_resolve_id_shadow (characterized pre-fix: the
re-define no-op reproduced with the purge disabled). punk::args suite green
under Tcl 9.0.3 (228 passed, 0 failed). punkshell 0.12.41.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The layout custom/_project bootsupport sync picks up files newly arrived in
src/bootsupport on the following run (same two-pass propagation as the guarded
prune tooling); punk.project-0.1 and punk.shell-0.1 copies now carry the
stage-2 handler/modpod versions with the superseded copies pruned.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
make.tcl bootsupport refresh following the stage-2 cutover; superseded 0.1.1
handler and 0.1.4 modpod pruned (the modpod copy required manual deletion -
the running make.tcl mounts it and the prune self-locks; flagged in the G-087
detail file). Layout custom/_project bootsupport copies mirrored by the build.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
punk::cap::handlers::templates 0.2.0: layout refs are fauxlink files
(<alias>#<encodedtarget>.fauxlink|.fxlnk, target relative to
<projectroot>/src/project_layouts, resolved via the fauxlink module).
get_itemdict_projectlayoutrefs selects *#*.fauxlink/.fxlnk with fauxlink-derived
names; get_itemdict_projectlayouts derives the layout folder from the resolved
targetpath; the <alias>@<target>.ref parser is removed and .ref files are no
longer recognised. Alias-less (leading-#) refs and unresolvable refs are
skipped with a warning - punkcheck-based tooling excludes leading-# filenames,
so layout refs must carry a non-empty nominal name. Also fixes the ignore*
skip, which previously matched against the full glob path and never applied.
All 7 live-tier refs renamed via a fauxlink::link_as-driven migration script
(each generated name round-trip-verified through fauxlink::resolve before
rename): decktemplates vendor/punk x4 (alias-less refs gained their target-tail
aliases: basic, minimal, sample-0.1), custom/_project x2, and the
module-shipped modpod ref (punk::mix::templates 0.1.5). Zero-byte property and
all visible layout names unchanged. src/project_layouts/README.md ref-grammar
section rewritten for fauxlink.
Note: git's rename pairing crosses two of the zero-byte vendor/punk refs
(sample-0.1 <-> project) - content-identical empty files; the true mapping is
alias-preserving as described above.
Verified: stage-2 scratch checks 7/7 (name parity incl exact punk.project,
decoy alias-less ref warned+skipped, old-grammar decoy ignored); runtests
prune/fossilmove/multishell/libsearch pass; end-to-end dev project.new
materializes a full project from the default punk.project layout.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
make.tcl bootsupport: fauxlink 0.1.2 -> 0.2.0 in src/bootsupport and the
custom/_project layout copies; superseded 0.1.2 pruned, along with the layout
copies' templates-0.1.3.tm prunes deferred by the earlier transient lock.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- CHANGELOG + version bump for the fauxlink 0.1.2 vendor pull, tomlish catch-up
and bootsupport refresh.
- G-087 detail Notes updated: fauxlink 0.1.2 upstream work record, punkshell
fauxlink consumer survey (fcat follows only .fauxlink not .fxlnk; make.tcl
merge_over + startup-script check; kit boot fallback), the (package) id
status relative to G-075, and the recorded intention that punk::nav::fs
should gain fauxlink handling analogous to its punk::winlnk shortcut
treatment (candidate goal).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
make.tcl bootsupport batched build-output refresh (punkcheck-managed): fauxlink
0.1.1 -> 0.1.2, plus catch-up of source versions that had moved since the last
refresh - punk::ansi 0.1.3, punk::args 0.12.3, punk::lib 0.5.0, punk::ns 0.8.0,
punk::repl 0.5.2, tomlish 1.1.10 -> 1.1.12, test/tomlish-1.1.5 modpod, and this
morning's G-087 hygiene bumps (cap handlers templates 0.1.1, punk::mix::base
0.1.1, commandset layout/module/scriptwrap 0.1.1, commandset project 0.2.2,
punk::mix templates 0.1.4). Superseded versions pruned; the same refresh is
mirrored into the custom/_project layout bootsupport copies by the build.
templates-0.1.3.tm prune initially failed with a transient file lock and was
removed manually after verification.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Pulled by the same vendorupdate run from the clean tomlish upstream checkout
(c:/repo/jn/tclmodules/tomlish): tomlish 1.1.12 added alongside earlier
versions per existing practice; test/tomlish-1.1.5.tm modpod refreshed in
place from its source.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Vendored from the now-committed upstream project (c:/repo/jn/tclmodules/fauxlink,
checkins c82c9bb9 + ed1eebdb): punk::args documentation blocks including a
(package)fauxlink id (inert PUNKARGS + registration, no punk::args dependency;
full surfacing awaits G-075), decode_unicode_escapes hexless-%U first-char-drop
fix, 3-segment comment validation/decoding parity, link_as stub now errors
instead of silently no-oping, and a 62-test upstream suite (src/tests/fauxlink.test)
covering resolve/decode behaviour and the documentation metadata.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Two independent list-flattening bugs made `runtests.tcl foo.test bar.test`
match zero files, forcing agents to run files individually:
- the trailing glob value is -multiple 1, so its parsed value is a list;
plain lappend nested it as a single space-containing element
- punk::path::treefilenames declares tailglobs as a -multiple 1 positional
(one glob per argument), but the whole file_globs list was passed as one
argument, re-collapsing it (this also broke multiple globs supplied via
-tcltestoptions {-file {...}})
Single names always worked because a one-element Tcl list flattens to
itself, which masked both bugs. Verified: two file tails now discover and
run both suites (files=2, 40/40 pass).
Also note multi-file-tail support in src/tests/AGENTS.md Work Guidance.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- punk::mix::templates modpod (0.1.4): dead templates/layouts/project payload
subtree removed - design-generation residue with no reader; layout payloads
live in src/project_layouts, located via layout_refs.
- src/make.tcl: unused old_layout_update_list (referencing the long-gone
src/mixtemplates and modules/punk/mix/templates paths) removed; bootsupport
help text now names src/project_layouts/custom/_project/<layoutname> instead
of mixtemplates.
- src/project_layouts custom/_project make.tcl copies: punkcheck-managed sync
outputs refreshed by the verification 'make.tcl modules' run.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- @vendor+punk+project-0.1.ref renamed to project@vendor+punk+project-0.1.ref:
the alias yields the exact layout name 'punk.project', so project.new's
defaulted -layout resolves unambiguously (previously tcl::prefix::match saw
only punk.project-0.1 / punk.project-0.1_overrides).
- Junk/test refs removed from the selectable layout list: test2, the
custom/_project duplicate sample-0.1 ref, and the alias-less punk.shell-0.1
ref whose target was an a.txt-only folder (folder removed too; the real
shell layout remains exposed as punk.shell-0.1_overrides).
- src/project_layouts/README.md rewritten to describe the implemented
punk.templates + layout_refs mechanism including the ref filename grammar,
the not-yet-implemented overlay semantics, and a G-087 pointer; the dead
punk.projectlayout capability description is gone.
Layout names after this change: punk.sample-0.1 punk.project punk.minimal
punk.basic punk.shell-0.1_overrides punk.project-0.1_overrides.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- put -> puts at all six no-handler warning sites (commandset layout x2,
project, module, scriptwrap, mix/base get_template_basefolders - the sweep
found three sites beyond the review's list). Three procs also dereferenced
an unset result variable after the warning; the no-handler paths now warn
and return an empty dict. layout references_as_dict and module templates_dict
warning messages no longer misattribute their owning proc.
- punk::cap::handlers::templates: brace the absolute-pathtype existence test
('if {!file exists $normpath}' raised an expr syntax error on any
absolute-pathtype provider registration), and add the missing dict-exists
check in pkg_register's duplicate-registration guard (errored 'key not known
in dictionary' for any second provider package registering a capability).
- Versions: commandset layout 0.1.1, project 0.2.2, module 0.1.1,
scriptwrap 0.1.1, cap handlers templates 0.1.1; punk::mix::base 0.1 -> 0.1.1
(manually versioned: file renamed, provide block updated, history comment
added).
Verified: scratch no-handler/registration checks 13/13 (see
goals/G-087-thin-project-layouts.md Progress); runtests prune/fossilmove/
multishell/libsearch all pass; make.tcl modules builds clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New goal from the 2026-07-16 layout-system review: thin layouts with
generation-time infrastructure injection, fauxlink layout refs, and a working
overlay merge primitive. Detail file carries the review findings (unimplemented
merge, dead module-pathtype refs, stale fat snapshots, latent bugs), the staged
approach (hygiene first), and the hygiene-stage completion record.
Activated at user direction 2026-07-17.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Vendored library payloads and vfs kit payloads legitimately carry CRLF
endings (upstream files are kept as-is; the LF preference governs authored
text). Without the globs, large vendor/vfs checkins block on fossil''s
interactive CRLF prompt - the tablelist 7.11 catch-up (fossil 3316d3c7)
had to use --no-warnings. Policy documented in .fossil-settings/AGENTS.md
alongside the binary-glob rationale. crlf-glob is fossil-only (no
.gitignore-style counterpart), so no dual-VCS derivation applies.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The old Tk dll set aside during the punk9win.vfs split is no longer
wanted in the tk903 kit payload; the 9.0b2-era dll remains available in
punk9wintk90b2.vfs.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Closes the loophole flagged in the 6.22 -> 7.11 swap: with the .tm
files deleted, a future make.tcl vendorupdate would have regenerated
them from these entries. tablelist now ships solely as the
src/vendorlib/tablelist7.11 pkgIndex lib.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The punk9win.vfs kit was split into punk9wintk90b2.vfs and
punk9wintk903.vfs; the treectrl/Img/twapi/cffi payloads G-020 relies on
live in punk9wintk903.vfs/lib_tcl9 (the actively mapped tclsfe/punk91
kit). Path-only update, user-approved; goal contract otherwise
unchanged. goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New vfs_startup_script_warning check runs for each .vfs folder about to
be built against a runtime: it passes if the folder has a root main.tcl
or a root fauxlink resolving to the name main.tcl whose target exists
and is a .tcl file. Otherwise a noticeable warning is emitted and the
build proceeds (a kit with no startup script is legal).
Warnings use a new general-purpose ::punkboot::print_build_warnings
channel: column-0 BUILD-WARNING: token for greppability, ANSI highlight
for humans, and recap at end of run via the wrapped ::exit (same
treatment as PROVENANCE-WARNING). Overlay-only folders with no runtime
mapping (e.g _vfscommon.vfs) are not checked. Contract documented in
src/vfs/AGENTS.md.
Motivated by the punk9win.vfs split initially dropping the main.tcl
punk_main fauxlink from punk9wintk90b2.vfs.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Adds the main.tcl fauxlink omitted from the punk9win.vfs split, and
points the commented-out tclsh90b2/tksfe-twapi-x64 mapvfs.config
entries at the new kit names.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com