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
Remove src/vendormodules/tablelist-6.22.tm and tablelist_tile-6.22.tm
in favour of the multi-file src/vendorlib/tablelist7.11/ (pure Tcl,
upstream layout with pkgIndex.tcl). _vfscommon.vfs follows via
make.tcl vfscommonupdate: modules/tablelist*-6.22.tm removed,
lib/tablelist7.11 added.
Note: src/vendormodules/include_modules.config still lists the
tablelist/tablelist_tile module sources; a future make.tcl
vendorupdate would regenerate the 6.22-era .tm files unless those
entries are removed.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Replace the single punk9win.vfs payload with two per-Tk-version kits:
- punk9wintk90b2.vfs: content-identical copy of punk9win.vfs (same Tk
9.0b2-era bin/tcl9tk90.dll) except the main.tcl punk_main fauxlink
was not carried over (kit is parked; its tclsh90b4_piperepl mapping
remains commented out in mapvfs.config)
- punk9wintk903.vfs: same payload with a newer Tk bin/tcl9tk90.dll
(Dec 2025 build, Tk 9.0.3) and the old 9.0b2-era dll set aside as
bin/tcl9tk90xxx.dll; adds lib_tcl9/apave4.4.10 (pure Tcl); drops the
modules_tcl9 Thread-3.0b3 modules (Thread is static in the tclsfe
runtime); now the mapping target for tclsfe-x64.exe (punk91 kit)
src/runtime/mapvfs.config and src/runtime/vendorlib_vfs.toml (tcludp
install targets) retargeted from punk9win.vfs to the new kit names.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-directed removal of the two pipeline-based development iterations flagged
as candidates in the 0.7.0 hygiene pass. Both were undocumented, unexported
global aliases superseded by the plain proc nscommands (which adds
weird-namespace handling); no callers existed in the repo and nscommands1 was
broken - it referenced nonexistent commands (nsthis2, inspect at global
scope) and errored on first use. Recoverable via git history.
ns/nav/repl suites 111/111 green. buildversion 0.7.1 -> 0.8.0 (command
removal); project 0.12.36 + CHANGELOG (patch - the aliases were never part of
the documented shell contract).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved from the serversecretsync tm-path-shadowing incident
(8.6 require-before-path-setup silently selected a stale tomlish from the
machine-default tm paths over the project's vendored copy). Default
mechanism per user: vendor punk::libunknown + punk::packagepreference as
the light layout's bootstrap minimum. Related: G-012/G-027/G-029/G-035.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The -return summarydict choicelabel claimed the linemap key appears only when
-n is supplied - actual behaviour (pinned in ansi/grepstr.test since the
characterization wave) is that linemap is always present. Help text corrected
to match; deferred-to-the-hygiene-pass item from the grepstr characterization.
ansi suites 63/63 green. buildversion 0.1.2 -> 0.1.3; project 0.12.35 +
CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Both fixes were pinned as known warts before the change; the pins flip with it:
- get_nslist: the -types default sat inside a braced dict-create literal, so it
was the literal string $known_types - any call without -types (notably bare
user-level `nslist`) errored with the malformed "Unrecognised namespace
member type: $known_types". An unsupplied -types now defaults to all known
member types. Pin flipped: nslist.test nslist_types_default_error_QUIRK ->
nslist_types_default (bare nslist renders children + commands). nslist's own
PUNKARGS -types gained help text, deliberately without a -default so the
passthrough stays absent when unsupplied.
- nsjoinall: the non-empty-prefix-vs-absolute-path error message carried a
copy-paste "nsjoin:" prefix - now "nsjoinall:". Pin flipped in
nsprimitives.test nsjoinall_edges.
- nscommands: commented out a development trace puts (">>> base: ...") that
polluted stdout on the weird-namespace path (same treatment as the 0.1.1
doc-lookup trace-puts cleanup; not pinned).
Suites green: ns/nav/repl 111/111; full source-tree run at the known baseline
(only core exec-14.3, pre-existing). buildversion 0.7.0 -> 0.7.1; project
0.12.34 + CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
No change to shipped behaviour (ns+nav+repl suites 111/111 green). Minor bump
because unused procs were removed.
Removed (~1200 lines, recoverable via git history):
- the fully commented-out predecessor help command arginfo (~930 lines) -
its own header marked it replaced by cmdhelp
- superseded/deprecated name-primitive twins nsparts1, nsprefix1,
nsprefix_orig, nstail1, nstail_orig (never exported, no callers; NOT
drop-in equivalents - divergence on 5+ colon runs was pinned in
nsprimitives.test before removal; those divergence pins are removed with
the twins and replaced by a direct nsprefix long-colon-run pin - the
divergence record lives in the test file history, commit 0c7168a1)
- obsolete nsglob_as_re1, empty stubs ns_relative_to_location/
ns_absolute_to_location, obsolete internal::_pkguse_vars, an if-0 block in
nstree_list, unused interp_aliases assignment in get_ns_dicts, assorted
commented-out remnants (pre-punk::args defaults blocks, pipedata width
calcs, corp default-retrieval experiments, cmdtrace trace-add alternates)
Documentation accuracy:
- nsprefix comment corrected (:::a prefix is :: not ::a - per pins)
- nsglob_as_re stale "should be fixed" note replaced with an accurate
description of the in-place negative-lookahead fix (* matches an inner
single colon, never crosses ::)
- nstree_list previously empty PUNKARGS summary/help fields filled
- nstail gained a doc comment; nseval_ifexists gained the native-vs-punk
p:::x divergence note; the dangling "string functions" sentence completed
- cmdhelp help typos (auto-gnerated, commands commands); corp -syntax help
truncated sentence completed
Flagged, deliberately unchanged (comment only):
- get_nslist red-strike/masked alias display branches appear unreachable
from current bucket derivation (nslist.test fixture findings) - reassess
at the planned display rework
- nscommands1/nscommands2 pipeline aliases: superseded removal candidates
(nscommands1 errors on first use - references nonexistent nsthis2)
- cmdtrace stdout/stderr noise deferred to proposed G-085
- test_switch* marked as live cmdtrace test fixtures (used by cmdtrace.test)
All inserted/updated comments carry 2026-07-14 Agent-Generated/Agent-Updated
marks. buildversion 0.6.0 -> 0.7.0. Known-wart fixes sanctioned by the pinned
backlog (nslist -types default, nsjoinall error prefix) follow separately.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com