Blanket /src/buildsuites ignores removed from .gitignore and
.fossil-settings/ignore-glob; retired /vendorbuilds/ ignores removed with
them. src/buildsuites/_build remains ignored via the existing _build globs.
samplesuite1 sketch marked as such, buildprefix moved to the _build
convention (vendorbuild concept retired per user decision 2026-07-20).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Sweep: G-096 detail and the punk::lib gate comment now point at the archived
path with achieved phrasing. goals_lint clean (72 active, 25 archived).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
punk::repl (pending 0.5.2): repl_handler's full 'chan configure' probe is now
guarded - on runtimes carrying the upstream f10d91c2d3 fix a dead console is
DELIVERED as a readable event and the probe errors ('couldn't read console
mode: broken pipe'); previously this backgrounded and left the repl idle with
its reader inactive. Terminal input loss now routes through new
repl::console_input_lost - the same teardown console_watchdog uses (helper
shared by both paths; watchdog probe and message unchanged).
punk::lib (pending 0.5.0): check::tclbug_console_deadspin_fixed_in = 9.0.5
after the G-039 kill procedure passed on a zig-built core-9-0-branch runtime
with the watchdog disarmed (clean script-visible eof exit 0.2s after conhost
kill). One edit flips both consumers: 'help tcl' warning and watchdog arming.
Regression-verified on affected 9.0.3: bug=1, watchdog armed, rescue at 1.9s
via the shared teardown. Suites: console+repl+lib families 115/115.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The stale copy (2026-07-19 20:55 build) survived three make.tcl bootsupport
runs: two in-session runs failed the copy with 'invalid argument' (destination
held open - a running shell's zipfs mount on the bootsupport modpod, the
G-087-era self-lock class) and the user's post-shell-close rerun left it
untouched (cause unobserved - if that run reported no copy attempt rather
than a failure, the punkcheck staleness records having absorbed the earlier
failed attempts would be worth noting for G-094). Direct file copy from the
current root modules build (22:13, md5 b1226b3d) succeeded once the lock was
gone; bootsupport now matches root modules and _vfscommon.vfs (already fresh
via the earlier vfscommonupdate).
Claude-Session: https://claude.ai/code/session_01BNUVVkYq9vHa6G3S9a3XTZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Goal/Acceptance wording updated per user approval (verification runtime need
not be an official release). Upstream f10d91c2d3 fix confirmed merged and
present in TEMP_REFERENCE/tcl9; both G-039 defects addressed. Progress
entries: toolchain policy (zig-only for project integration), known-good 2024
zig build recipe determined and duplicated (zig-out90dup2026), 9.0.5
verification runtime built (tcl905 checkout, build905.zig: fresh-checkout
preconditions tclUuid.h + tclsh.exe.manifest, mingw_unicode_entry_point for
upstream's removed TCL_BROKEN_MAINARGS). Remaining: G-039 kill procedure on
the 9.0.5 runtime.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Content-identical rename (flip edits landed in the previous commit); GOALS.md
entry removed and the summary record (amended *** acceptance) appended to
GOALS-archive.md per the achieved flip workflow. Rides along: CHANGELOG.md
gains the required [0.17.1] entry matching the punkproject.toml bump from the
previous commit (punk::path 0.4.0 *** pathglob + separable lattice; runtests
targeting rework).
Claude-Session: https://claude.ai/code/session_01BNUVVkYq9vHa6G3S9a3XTZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
In-place closeout edits ahead of the archive move (per the goals/AGENTS.md
pure-rename discipline): detail-file Status flipped to achieved 2026-07-20
(all amended acceptance clauses verified - see the detail file's Progress
record), the console-attachment finding pushed to live G-061's Notes as part
of the archive reference sweep, and punkproject.toml patch-bumped 0.17.0 ->
0.17.1 for the punk::path 0.4.0 pathglob addition shipping in kit payloads
(user-directed). goals_lint transiently red until the archive-move commit.
Claude-Session: https://claude.ai/code/session_01BNUVVkYq9vHa6G3S9a3XTZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
make.tcl modules + bootsupport + vfscommonupdate after the punk::path ***
source changes: path-0.3.0.tm -> path-0.4.0.tm snapshots in
src/bootsupport/modules and src/vfs/_vfscommon.vfs. The runtests parent
resolves punk::path from bootsupport - the refreshed snapshot is what enables
*** targeting at the runner discovery layer (discovery.tcl requires 0.4.0-).
Known ride-along not included: the bootsupport templates-0.2.0.tm modpod copy
failed to refresh ('invalid argument' - destination held open, likely a
running shell's zipfs mount; the stale copy predates this session) - reported
separately.
Claude-Session: https://claude.ai/code/session_01BNUVVkYq9vHa6G3S9a3XTZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved contract amendment replacing the day-1 file-relpath filter: one
directory-oriented pathglob semantics at every layer, with the ergonomics gap
closed in the syntax itself.
punk::path 0.4.0:
- *** as a whole segment matches ZERO or more segments (join-aware regex in
pathglob_as_re: an adjacent separator is absorbed into an optional group),
so X/*** = X and everything below - the subtree spelling; ***/f.txt matches
at any depth including the root.
- include separability fix: an exact or single-segment-glob full match no
longer sets allbelow (the deep walk previously dragged the whole subtree in
for X and X/* patterns; the zipfs walk was already separable).
- exclude separability fix (new exclude_state classifier, both walks): only
**|***-tail patterns prune the matched subtree; other matches exclude just
that directory's files - the **/_aside vs **/_aside/** argdoc distinction is
now real. Dead _path_matches_any removed.
- legacy bare-* include collapse removed (a * in -include-paths is the
one-below lattice form, not a match-everything alias; no caller used it).
- globmatchpath default-nocase driveletter exception rewritten as a direct
regex-head rewrite (the regex-text file-split broke on c:/***'s glued group
and accepted non-alpha drives).
- path.test +5 lattice/*** pins (40 total).
runtests.tcl:
- -include-paths/-exclude-paths pass through to treefilenames unchanged;
argdocs teach the separable X | X/* | X/** | X/*** lattice; directory and
file-name axes independent (tails); single-file targeting = exact dir
pattern + file tail.
- -serial-paths reconciled to the same directory-of-file reading (default now
modules/punk/console/*** modules/opunk/console/*** via
runtests_discovery::dir_matches_any) - the pre-existing file-path serial
matching was the other same-option-different-referent divergence.
- per-pattern zero-match stderr advisory (the X/**-for-subtree foot-gun points
at X/***).
- json report emitter: whitespace-padded entier-looking values now take the
quoted-escaped path ('string is entier -strict' accepts surrounding
whitespace - a failed test's "0\n" result_was embedded a raw newline and
truncated the parseable report line).
- testsupport/discovery.tcl now a thin passthrough (requires punk::path
0.4.0-); pathdiscovery.test rewritten to the directory-semantics contract
(22 tests incl. the X/** zero-match advisory characterization); AGENTS.md
targeting guidance swept to /*** across src/tests and src/modules/opunk.
Verification (native tclsh 9.0.3, piped, serialized): 45-probe matrix, path
suite 40/40, runner suite 22/22; vs the pre-G-093 baseline the default
discovery FILE SET differs by exactly the added runner suite and result
parity only by the five new path tests (+ that suite); mode parity -jobs 16
vs singleproc: PARITY ok (94/1037/failed=1 exec-14.3). Goal contract amended
in the detail file; full record there.
Claude-Session: https://claude.ai/code/session_01BNUVVkYq9vHa6G3S9a3XTZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Root cause (recorded in the goal file): punk::path::treefilenames matches
-include-paths against the DIRECTORY containing files, and its documented
X/** boundary semantics exclude files directly in X - so suites keeping
.test files at the subtree root (scriptwrap, binscripts, punkexe) were
silently missed by X/** targeting: the G-092 four-pattern (2/13 files) and
repeated-flag (zero files) failures. punk::args -multiple accumulation
probed healthy - repeated flags and a single space-separated value reach
discovery identically; no punk change was needed or made.
runtests.tcl now filters the tailbase-relative FILE paths after an
unrestricted walk (new testsupport/discovery.tcl: globmatchpath,
any-include-match, exclusion wins): X/** includes files directly in X, an
exact relative path targets a single file, a bare directory path matches
nothing (append /**). -exclude-paths exposed (same syntax and accumulation,
exclusion wins over inclusion). -discover-only prints the discovered list
plus a RUNTESTS_FILES tcl-list line and exits before any run machinery -
subsecond via a two-stage boot (discovery phase loads only punk::args +
punk::path; punk/Thread/shellrun/punk::tcltestrun and the testinterp/child
path assembly load after the exit).
New regression suite runner/testsuites/discovery/pathdiscovery.test
(23 tests: pure filter, fixture-tree walk+filter, end-to-end -discover-only
children including both G-092 characterization forms; ~7s wall,
parallel-safe). src/tests/AGENTS.md targeting wording reconciled; new
src/tests/runner/AGENTS.md. G-093 index status proposed -> active
(user-directed).
Verification (native tclsh 9.0.3, piped Bash context): pre-change baseline
default -jobs 16 (93 files / 1010 tests / failed=1 exec-14.3 only) vs
post-change -jobs 16 with -exclude-paths runner/**: PARITY ok; post-change
default run differs from baseline only by the added suite (+23 passing);
mode parity -jobs 16 vs singleproc sequential: PARITY ok (94/1033/1).
Claude-Session: https://claude.ai/code/session_01BNUVVkYq9vHa6G3S9a3XTZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
make.tcl modules + bootsupport + vfscommonupdate after the stage 4/5 source
changes: commandset layout 0.1.1->0.2.0 and project 0.3.0->0.4.0 snapshots in
src/bootsupport and _vfscommon.vfs; thin-layout sync refreshed the store
layouts' make.tcl copies and the templates modpod payload (repacked
templates-0.2.0.tm) for the retired marker exclusion comment.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Content-identical rename (edits landed in the previous commit); GOALS.md entry
removed and the summary record appended to GOALS-archive.md per the achieved
flip workflow.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Stage 4 - documented overlay semantics implemented (commandset::layout 0.2.0):
layout_materialize resolves a layout to its overlay chain (vendor tier then
custom tier per store+vendor, <name>@<base> derived-layout folders expanding
their base chain first, cycle-guarded) and composes multi-folder chains into a
disposable staging dir applying <item>.anti deletion markers (zero-byte marker
files recommended - committable, unlike the originally documented empty marker
folders, which are also accepted). Single-folder chains with no markers are
used in place, so punk.project (store and zipfs modpod) behaviour is unchanged.
project.new (commandset::project 0.4.0) copies from the materialized path and
the layout listing/scanning commands show the effective merged view.
Fixtures: punk.othersample is now a live derived layout (new custom-deck
fauxlink ref + .gitignore.anti demo marker); extra.txt/store README rewritten
to the implemented semantics. New tcltest suite
src/tests/modules/punk/mix/testsuites/layout/materialize.test (20 tests).
Anti markers deliberately stay a plain filename convention rather than
tag-bearing fauxlinks: a fauxlink is a reference tooling may follow (fcat
auto-follows), a marker is a tombstone with no target.
Stage 5 - retirements and generated-project version seeding:
- The empty unimplemented child-side src/PROJECT_LAYOUTS_CREATE_FROM_... marker
folder is deleted along with its project.new and make.tcl sync exclusions.
- The vendor/custom x _project matrix collapses for layouts: custom/<vendor> is
the one override level; _project folders join no overlay chain (the
pseudo-vendor remains for decktemplates module/utility templates only).
- project.new seeds generated projects post-materialization (only-if-missing,
never from payload): punkproject.toml ([project] name + 0.1.0), a matching
CHANGELOG.md ## [0.1.0] header, and punkorigin.toml - an interim generation
provenance baseline (utc, layout name + resolved store target,
punk::mix::templates version, punkshell version when derivable, origin path)
for the G-027 pull design to adopt (noted in G-027).
Also: script-mode/programmatic project.new robustness (explicit shellrun
require; punk::mix::util askuser/do_in_path/foreach-file fully qualified -
the util:: shorthand exists only after cli commandset import). Includes the
concurrently-landed (other session, previously uncommitted) 0.3.1 early
module-name validation fix in project.new, shipped within the 0.4.0 bump.
G-087 flipped achieved 2026-07-19 (verification in the detail file; archive
move follows in the next commit). punkshell 0.16.0 -> 0.17.0.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Outcomes of the 2026-07-19 punkcheck module review:
- G-094 [proposed]: single OO record lifecycle - installtrack/installevent
becomes the sole implementation with an eager|deferred persistence policy,
punkcheck::install rebuilt as an OO consumer in deferred mode, the
zero-caller installfile_begin/finished/skipped trio retired to shims, and
the o_record_list staleness fixed. The single save chokepoint is G-095's
attachment point.
- G-095 [proposed]: concurrent-writer safety - atomic temp+rename saves,
advisory EXCL lockfile serializing whole installer events per punkcheck
root, merge-on-flush for deferred mode, non-interactive-safe
duplicate-INSTALLER recovery. SQLite recorded as rejected for now (TDL
human readability/debugability overriding; three-part reconsideration bar).
- G-027: acceptance reframed - .punkcheck records demoted from sole
provenance basis to acceleration layer; safe-overwrite classification
survives record loss via a committed baseline record (origin identity +
pulled version, pristine content re-derivable from the origin's VCS),
degrading conservatively (report/confirm - never silent overwrite, never a
wedged pull). Approach classification bullet extended to match.
- G-095 notes carry the tiered expendability taxonomy (build trees: recopies
only; synced-targets bin/ deploy: non-self-healing skip wedge; derived
projects: G-027 baseline) and the cross-tier invariant: absent records
degrade to skip/confirm, never to overwrite.
- (The G-087 cross-pointer to G-094/G-095 already landed with the stage-3
sources commit.)
goals_lint clean (73 active-index goals, 22 archived).
Claude-Session: https://claude.ai/code/session_01L7MfuYBfYpUFpVafo5JowC
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
vendor/punk/project-0.1 loses its stored src/bootsupport snapshot (10.6MB, 254
files) and src/vfs/project.vfs lib+modules snapshots (7.7MB, 230 files);
vendor/punk/basic loses its 2023-era bootsupport snapshot. Thin layouts keep
structure, scripts, docs, fossil/git settings and now carry the three
bootsupport modules*/include_modules.config manifests plus README markers
documenting generation-time injection (bootsupport README, project.vfs lib and
modules READMEs).
custom/_project deleted entirely (punk.project-0.1, punk.shell-0.1,
punk.basic) together with their two decktemplates _overrides refs: these were
bootsupport-snapshot + make/build-script overlay fragments kept current by the
retired make.tcl sync - generation-time injection provides exactly that
content, so they were fully redundant (punk.shell-0.1_overrides was never a
working standalone layout).
The store payload store drops from ~43MB to under 1MB (bin/sdx.kit 300KB
remains, grandfathered - excluded from the module-shipped payload copy).
Claude-Session: https://claude.ai/code/session_01WS3VakZo4sgbFzcQFW3twZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
punk::cap::handlers::templates 0.3.0: module-pathtype layout refs resolve
against the providing module's own templates/project_layouts store (sibling of
its layout_refs folder) instead of the never-existing <modulebase>/src tree -
module-carried thin layouts become usable.
punk::mix::templates 0.2.0: ships the thin punk.project layout payload inside
the modpod (payload synced from src/project_layouts by make.tcl - see below);
shellproject_multivendor declaration fixed decktemplates -> src/decktemplates
(shell-project layouts/templates were invisible when cwd was outside any
project).
punk::mix::commandset::project 0.3.0: project.new injects bootsupport into the
generated project at generation time via new lib::bootsupport_inject - manifest
(include_modules.config) driven module resolution from the generating shell's
project bootsupport tree, or a standalone kit's tcl:™️:list paths (999999.*
dev versions never injected; latest-version non-glob semantics matching
make.tcl bootsupport; adjacent non-.tm support files such as struct sets_*.tcl
and textutil .tex data carried along; bootsupport lib* trees copied from a
shell project, notice emitted for manifest-less standalone kits); punkcheck-
recorded with plain-copy degradation. -layout now prefix-matches the live
layout set instead of the package-load-time snapshot.
punkcheck 0.4.0: start_installer_event no longer writes literal '$eventid'/
'$rel_source'/'$rel_target'/'$config' into event headers (braced-literal
expansion bug, latent since inception - collided as duplicate ids when install
and installtrack writers shared one db); sources with no common root vs the
punkcheck folder (e.g //zipfs:/ module-mounted layouts) are recorded as
independent absolute paths instead of erroring.
punk::mix::base 0.1.1 -> 0.1.2 (manually versioned rename): cksum_path no
longer hangs forever on vfs-mounted files - tcllib -file digest modes read via
fileevent+vwait and zipfs channels never deliver fileevents (empty
ZipChannelWatchChannel in core); non-native files are slurped and digested in
data mode (new cksum_data_command per algorithm + cksum_crc_data/
cksum_adler32_data helpers; exec-based sha3 errors cleanly for vfs paths).
make.tcl: custom/_project layout bootsupport-sync retired (project layouts
store no snapshots); sync_layouts retargeted to thin vendor layouts (make.tcl,
build.tcl + bootsupport manifest copies; punkcheck db at
src/project_layouts/.punkcheck) plus store->modpod punk.project payload sync
(excludes bin/sdx.kit and src/PROJECT_LAYOUTS_* marker; fossil settings kept
via core-exclude override); bootsupport copy onto a modpod the running
make.tcl has mounted records OK when target content is already identical
(FAILED-record churn fix); workflow text updated (DIAGRAM 1b) and help/argdoc
texts adjusted.
bootsupport include_modules.config: added previously-recordless-but-required
entries cmdline (fileutil dep), struct::set (make.tcl accelerators), textutil,
textutil::expander, textutil::patch - generated projects' make.tcl now boots
under a plain tclsh.
Docs: root/src/bootsupport/punk AGENTS.md updated for the retired sync and
build-managed modpod payload; goal detail G-087 stage-3 progress record;
CHANGELOG 0.16.0 + punkproject.toml bump.
Claude-Session: https://claude.ai/code/session_01WS3VakZo4sgbFzcQFW3twZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New scriptlib/developer/nslist.tcl backing the new cross-framework tcl-nslist
agent skill (.agents/skills/ canonical, .claude/skills/ synced copy): the
discovery counterpart of whatis.tcl - lists what a namespace/package actually
exposes at runtime via punk::ns::get_ns_dicts (the n// machinery): child
namespaces with loadable-package markers, commands classified by kind,
punk::args-documented commands, -synopsis whole-namespace usage lines,
-pathcommands namespace-path resolution. Auto-package-requires unloaded
packages and follows ensemble commands to their implementation namespace.
The tcl-whatis skill/script cross-reference it (whatis redirects with a hint
when the queried name is a namespace, not a command).
punk::ns 0.9.1: get_ns_dicts packagetails/packageprefixes initialization moved
inside the per-namespace loop - with multiple matched namespaces (path globs,
trailing **) every dict after the first carried the union of all earlier
namespaces' entries, mis-marking non-package children in nslist/n// underline
styling and in the returned data; a child with several deeper packages below
it was appended to packageprefixes once per matching package (now once).
Pinned in nslist.test (nslist_classification_multins_package_buckets_reset).
Documentation-only PUNKARGS added for get_ns_dicts (returned dict keys
documented) and nslist_dict; parsing stays manual.
Root AGENTS.md: introspection note + scriptlib/developer inventory updated.
Project version 0.15.1 + CHANGELOG entry. punk::ns suite 102/102 pass.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The multiproc child bootstrap no longer preloads shellrun + the no-op
runx warmup: 17 test files gained their missing explicit package
require lines (punk::ansi for the bare ansi suites, punk::args for the
bare args suites incl dev/dynamic-cache, punk::lib for the lib suites
and for grepstr/untabify/examples whose punk::ansi/punk::args commands
reach punk::lib internally, plus textblock for examples.test - caught
by the empirical lean run: punk::args only soft-requires textblock and
punk::args::helpers::example calls textblock::join). Children now load
only tcltest plus each file's declared deps; the singleproc testinterp
keeps shellrun as the runner's own capture mechanism.
Module-web finding recorded in src/tests/AGENTS.md and the test-file
comments rather than fixed: punk::ansi and punk::args call punk::lib
without requiring it, and a hard back-require is blocked by punk::lib's
own hard require of punk::args (cycle) - deps declared at test level;
a considered module-level resolution remains open.
UDP watch-mode note folded into child_test_runner.tcl per user
direction: no interaction today (the parent relays child output at file
granularity; verified post-lean - events + relay flow); any future live
per-child tee must be conditional on PUNK_TEST_UDPTEE so unwatched
children stay lean.
Verified (native tclsh 9.0.3): full-suite PARITY ok for lean -jobs 16
vs the pre-lean baseline, between repeated lean -jobs 16 runs, and
lean -jobs 1 vs -jobs 16 (989/973/15/1, exec-14.3 sole failure).
Timings: -jobs 16 70.7s -> 49-53s; sequential multiproc ~5m30 -> 4m32;
singleproc unchanged. AGENTS scaling guidance refreshed.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Three tests fail only under a half-attached console (stderr=console,
stdout=file): grepstr highlight tests emit empty SGR and nslist marking
loses its markers - punk::console process-global colour state under
mixed tty-ness. Fully-piped and -jobs runs green; fully-interactive
unverified. Recorded on G-061 (user direction) as a concrete
context-matrix workload for the pseudoconsole harness, alongside the
interim Start-Process selective-redirection repro technique and a
pointer to the related capture_stderr utf-16le fix (913ea749).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User request after console-context failures went unnoticed: compact
per-file status words, failure/warning list entries, the per-file
had-failures/passed/child-failed notices, the markdown
failures/warnings file lists, the tally Passed/Failed segments and a
coloured overall STATUS on the DONE line are now SGR-coloured (green
pass, bold red fail/error, bold yellow warning).
Gating: -colour auto|on|off (default auto) colours only when stdout is
a real windows console, detected via twapi GetConsoleMode on the
STD_OUTPUT handle - the isatty-equivalent; get_console_handle proved
unsuitable (it succeeds for piped children of console shells, verified
both ways). NO_COLOR honoured in auto. Machine output (RUNTESTS_RESULT,
json) is never coloured; piped output stays plain for agents (verified
zero escape bytes piped, codes present with -colour on). Raw literal
SGR is used rather than a+/a so the runner's indicators are independent
of punk::console's process-global colour state (the same 2026-07-19
console runs showed that state shifting under mixed tty-ness). The
previously UNCONDITIONAL raw-red errorInfo block in the file-error
branch now goes through the same gate, so piped error output is cleaner
than before.
Also sharpens the -jobs guidance wording: subtree runs (e.g 28-file
modules/punk/args/**: ~50s sequential vs ~11s at -jobs 16) benefit from
-jobs - only single-file/few-file runs do not.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
dynamic_bad_tag_warns_once failed (count 0) ONLY in console-attached
singleproc runs (user report; reproduced deterministically with stderr
on a real console and stdout redirected): when stderr is backed by a
windows console channel, a pushed chan transform receives the console
driver's utf-16le wide-char byte stream - every ascii char arrives
NUL-interleaved, so content regexps never match. The punk::args warning
itself emits correctly, exactly once, inside the capture window (proven
with marker writes: markers and warning all captured, all wide).
Piped/file stderr and -jobs child processes deliver plain bytes, which
is why every piped run passed.
Fix in all three capture_stderr helpers (punk/args dynamic.test,
punk/ansi grepstr.test, punk/ns corp.test - identical latent defect):
if the captured data is NUL-interleaved, decode it as utf-16le
(fallback 'unicode' for tcl 8.6) before returning. Verified: the
console-attached args subtree run is green (246/243/3/0); piped runs
unchanged.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-measured reference-machine numbers 2026-07-19: -jobs 8 ~79-86s,
-jobs 16 ~61s (~5.6x vs ~5m40s sequential), plateau by -jobs 24 (~60s).
Guidance now recommends -jobs 16 and records the plateau anatomy
(slowest single child ~31s runtimecmd pair, serial console tail ~16s
piped / larger under a real console, ~10s runner overhead).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Title broadened in both tiers; Goal/Acceptance gain the -exclude-paths
clauses: expose treefilenames' existing capability on runtests (or an
equivalent post-discovery globmatchpath filter), accumulate semantics
matching -include-paths, exclusion winning over inclusion, a
subtree-exclusion run discovering exactly default-discovery minus that
subtree, and both options pinned by the same regression-suite
combination matrix. Notes record the bundling and the middle-ground
motivation examples.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
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