Defect: the G-113 ansistrip transform was pushed onto Tcl 8.6 windows CONSOLE
channels, which encode utf-16 ('unicode') - at byte level ESC arrives as 1B 00
so sequences passed through unstripped and the hold-back carry deferred/
dropped real content, seriously mangling interactive punk86/punksys
'src/make.tcl help' layout (user-reported). Chunk-boundary handling itself is
sound: a rig proved strip output invariant across chunk sizes 1..4096 over
byte-transparent encodings; the failing dimension was encoding, not cutting.
(Comparison recorded: shellfilter::chan::ansistrip is the complement - it
decodes per the channel encoding and buffers undecodable tails, but assumes
line-buffering for sequence splits.)
Fix is detection, not utf-16 stripping: only 8.6 windows console channels
report -encoding unicode (pipes/files get the system encoding; hidden-console
probes confirmed across bawt tclsh86 8.6.13, punk86 8.6.17, punksys 8.6.13;
tcl9 consoles report utf-16 but are caught by -winsize first). The policy now
treats that signature as tty: mode=tty, colour ON, no transform - interactive
8.6 windows colour with no env var and no twapi. The transform push is now
PER CHANNEL and skips utf-16-class channels ('> file' from an 8.6 console
wraps stdout only - stderr console keeps its ANSI); ansistrip_pushed is the
wrapped-channel list, shell pops exactly those, policy/check lines print
ansistrip=stdout+stderr|stdout|0.
Verified: hidden-console 8.6 x3 mode=tty ansistrip=0; half-redirected punk86
console run ansistrip=stdout; piped 8.6/9 batteries unchanged (zero ESC,
force re-colours); punkexe suites 54/0 (maketclcolour pins updated to the
channel-list format). punkshell 0.23.2 + CHANGELOG; src/AGENTS bullet updated.
8.6 unix/WSL stays plain-by-default pending the probe-ladder goal.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
use wart fixed (both payloads + rewrapped bin/punk-runtime.cmd, checkfile
ERROR-free, scriptwrap roundtrip + binscripts freshness suites green 35/0):
candidate lookup falls back to <name>.exe when the exact name is absent -
exact names (incl. extensionless unix artifacts in foreign -platform staging
folders) still match first. Verified live in a throwaway platform folder via
the .cmd (ps1 payload) and the bash payload driven directly (msys exe-magic
already masked the wart under msys bash; the fallback serves real unix shells).
make.tcl: new ::punkboot::runtime_materialization_warning (warn-only, local,
no network) - the kit loop compares each wrapped working runtime's beside-toml
revision against the highest -r<N> artifact revision in the same folder and
emits a recapped BUILD-WARNING naming the repair command. Verified live: toml
demoted to revision=1 fires the warning once + recap (and would have caught
today's stale-r1 punk9_beta incident at the first bake); current state silent;
no spurious rewraps. Pre-family runtimes (no toml) and direct -r<N> references
stay silent.
Docs: bin/AGENTS.md runtime-manager contract (suffixless use + guard note),
src/AGENTS.md Work Guidance bullet; G-121 Notes records the guard as
bakelist's acting-path complement; G-031 Notes records the make.tcl-shell
punkexe-surface question with the boot-core vehicle recommendation.
punkshell 0.23.1 + CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
buildsuite group added as a declared passthrough (punk::args + fallback paths):
list discovers suites (dirs carrying suite.tcl; _build excluded), info renders
the manifest-derived detail, build forwards driver args untouched streaming
output and exiting with the driver's status (punk-kit-hosted runs launch the
driver via the kit's script subcommand, selected by the G-058 marker).
Self-description = manifest option: sources.config gains description/product/
doc/zigpin records parsed by both suite.tcl (strict; pinned-zig default now
reads zigpin - one source of truth) and make.tcl (tolerant). suite_tcl90
seeded with its records. Copied trees appear automatically (verified with a
throwaway copy). Contract documented in new src/buildsuites/README.md +
AGENTS.md, indexed from src/AGENTS.md. CHANGELOG extended under 0.23.0.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
vfs -> bake (kit assembly; vfslibs phase folded in so a bake cannot ship stale
binary libs), project retired -> bakehouse (packages + bake, -dirty-abort
default ON, refusal names the granular developer flow). project/vfs remain as
deprecated aliases: one-line stderr notice + pre-dispatch mapping; alias
argdocs mirror their targets so flags parse identically. vfslibs survives as a
standalone narrowing (in-session decision recorded in the goal file).
SUBOPTS/SUMMARIES/HELPTEXTS/SUBGROUPS/known_commands, end-of-run guidance,
plain gethelp and workflow text rewritten to the two-persona model (groups:
build & bake / promotion gates / source maintenance / deprecated aliases).
Verified: tabled + PUNKBOOT_PLAIN help; dirty-tree refusal via bakehouse and
via the project alias; alias help renders. punkshell 0.23.0 + CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Activation: proposed->active flip (user-confirmed), goals_xref score re-run
recorded in detail Notes (nothing beyond the drafting survey).
Holder named: punk::libunknown zipfs_tm_UnknownHandler's builtin-static
shortcircuit leaked its version-probe child interp 'ptest' whenever an
UNVERSIONED package require of a true static reached the handler -
'package vsatisfies $v' with zero requirement args throws wrong#args,
skipping both interp-delete lines. The leaked non-safe child holds
registrations on the process std channels, so 'chan close stderr' left the
OS handle alive and the slot occupied; the next open got a fileN name and
puts stderr failed (punk91/tclsfe-9.1b0 only: Thread is a true static there,
punk905 loads it from a dll so the block never fires).
Fix (0.2.2): auto-named probe interp deleted in try/finally; zero-requirement
requires accept any provided static version; probe errors fall through to the
normal tm search. Disposition recorded in the goal detail: leak, fixed - not
console-ownership machinery.
Verified: bin/punk91 src script recipe yields channel auto-named stderr with
working puts stderr; libunknown+console+repl suites 105/105 pass (tclsh90).
punkproject 0.22.1 + CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The starred active row previously never changed across 'use' switches
(every -rN materializes to the same working name) and carried the
name-keyed dead end '(not listed on server)' - true of the name,
unexplanatory for a working copy whose bytes match a server artifact.
Rows the server listing does not name now carry an untitled identity
middle column: from=<artifact> for materialized working copies (the
beside-toml source; content verified against that artifact's server
sha1 so the Remote cell shows a real status - Same version, CONTENT
DIFFERS for the immutable-artifact anomaly, or '(artifact not listed
on server)'), sha1=<name> for tomlless byte-copies (default-first-
then-ordinal pick, the same rule as the freshness fallback so row
identity and freshness verdict always name the same artifact).
'(not listed on server)' remains only for genuinely unknown files;
the (server default) row annotation follows artifact identity onto
working copies of the default. Table header/rules widened to the
three-column layout, payload row formats now column-aligned across
ps1/bash; help text updated; bin/punk-runtime.cmd rewrapped
(checkfile clean).
Chosen shape (user-approved from mockup variants): untitled middle
column with self-keyed from=/sha1= tags - consistent with the plain
list metadata summary's from= vocabulary and self-describing when a
row is pasted without its header.
runtimecmd_freshness.test +3 row-shape tests (identity columns, the
identity-following default annotation, anomaly statuses) with ps1/bash
parity: 10/10 pass; scriptwrap + binscripts battery 35 pass /
1 pre-existing skip / 0 fail (roundtrip + checkfile pins green, WSL
row pins unaffected). bin/AGENTS.md + shell tests AGENTS updated.
punkshell 0.22.0.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
list -remote now states the relationship between the ACTIVE runtime and
the SERVER DEFAULT whenever both are known: explicit freshness: AHEAD/
BEHIND verdicts naming both revisions (BEHIND adds a fetch+use update
guidance line), an equivalent current verdict where the (= server
default) identity annotation did not fire, a different-series
incomparable note, and a stated no-revision-basis note for pre-family
actives - with sha1 VALUE-matching against the server sha1sums
identifying a byte-copy of a server artifact by content (support-file
rows excluded; first ordinal/C-collation match in both payloads). A
NO-NAME fetch prints the same verdict as a one-line note when the
active diverges from the resolved default (BEHIND carries an inline
'use <default>' hint - the artifact was just fetched). Revision basis:
-r<N> parsed from artifact-named actives, else the beside-toml revision
field (materialized working copies); the default's revision parses from
its defaults.txt name. Verdict lines are byte-identical across the
payloads; guidance lines keep each payload's program-name convention.
Help text (list/fetch sections) mentions the new surface;
bin/punk-runtime.cmd rewrapped (checkfile clean, no spacer resize).
New fixture-server suite
shell/testsuites/binscripts/runtimecmd_freshness.test: a child-process
http file server (new src/tests/testsupport/httpfixture.tcl) serves a
crafted punkbin layout behind the PUNKBIN_URL override; the ps1 payload
runs as the staged committed .cmd via cmd.exe (wrap-pinned path), the
bash payload directly under a probed msys/git bash (on windows the
polyglot routes unix shells to the powershell payload; WSL bash
rejected - WSL2 cannot reach a 127.0.0.1 fixture server). Covers the
five G-119 acceptance scenarios with per-scenario ps1/bash verdict-line
parity plus bash-side extras (different-series incomparable, fetch-mode
BEHIND hint): 7/7 pass; scriptwrap + binscripts subtrees 32 pass /
1 pre-existing skip / 0 fail (roundtrip, checkfile, WSL, dtplite
unaffected).
bin/AGENTS.md runtime-manager contract records the verdict surface;
src/tests + src/tests/shell AGENTS docs cover the new suite and helper.
punkshell 0.21.0 + CHANGELOG entry.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New punk::args::moduledoc::punkexe 0.1.0: (script)::punkexe dispatch
definition (package modes, subcommand enumeration, default reclassification)
+ (script)::punkexe::tclsh full contract (stock arg-form parity incl the
deliberate no -e boundary (G-077), lib: refusal, piperepl ::tclsh state
array + env gates, intended divergences recorded per item decisions 2/6/8)
+ summary definitions for script/shell/punk/shellspy. G-032-compatible: the
launcher help/parse wiring renders from these ids later.
punk::args 0.12.7: update_definitions handles tag-prefixed id namespaces
first-class - namespace_docpackages consulted with the tagged key (usage/
real_id on registered-but-unloaded (script)::* ids no longer no-such-id),
generic tag strip for the real-namespace probes, unqualified-ns warning no
longer fires for tag ids. args/ns/repl suites 352 pass 0 fail.
punk::repl 0.5.3: code-interp setup catch-requires the punkexe moduledoc
beside tclcore (both sites) so the docs are queryable in any punk shell.
ARCHITECTURE.md: tclsh subcommand bullet in the boot/launch chain
(architecture_lint clean). punkproject 0.20.1 + CHANGELOG.
Verified: fresh-interp usage-first render (real_id path); rebuilt punk902z
kit self-carries 0.1.0 (5298-char tclsh render); piped punk session renders
(script)::punkexe with no manual require.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- no-script forms set ::argv0 to the executable path (was the kit boot script)
- missing script file: file-exists pre-check, clean message, exit 1 (existing-file
source errors keep their full trace)
- no piperepl machinery (unpatched runtime or TCLSH_PIPEREPL=0): terminal stdin
fails fast with usage guidance (app-punkscript probe) instead of blocking in a
raw read; piped degraded eval unchanged; patch-missing notice now 'note:' and
a deliberate TCLSH_PIPEREPL=0 opt-out is quiet (old debug lines deleted)
- project_main.tcl mirrors the full tclsh dispatch (script-arg/dash/-encoding/
lib: forms; was single-arg-only with stale gate default 0); layout _config
copies byte-synced (interim duplication pending G-031)
- tclshcmd.test 17 -> 19 (tclsh_noscript_argv0, tclsh_script_notfound); shell
subtree 64 pass / 2 goal-gated skips / 0 fail against rebuilt kits
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- a leading '-' argument is no longer treated as a script name: all args stay in
::argv and the subcommand proceeds to the repl (tty) or stdin evaluation
(piped), matching stock tclsh
- '-encoding name fileName' sources the script with the named encoding;
incomplete -encoding forms fall through to the argv path as stock does
- lib: scriptlib names are refused with a pointer to the 'script' subcommand
(exit 1): the tclsh subcommand keeps plain-tclsh semantics, no punk modules
- also carries the piperepl dispatch work-in-progress this session's review
validated: TCLSH_PIPEREPL gate default enabled-unless-0 (G-103 patched-runtime
policy) and the no-arg branch (tty -> tclsh repl via dorepl; piped -> read
stdin + eval with tcl_interactive/dorepl 0)
- punkproject 0.19.0 + changelog entry
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-requested audit of naive [package versions] selection: punk::apps'
appinfo 'latest' used a plain lexical lsort (misorders 1.10 vs 1.9) AND
took lindex 0 - the LOWEST version - as latest (the '#todo - natsort!'
site). Now lsort -command {package vcompare} taking the highest, with
empty (unversioned-main) entries excluded before comparison since
vcompare errors on empty operands; only-unversioned yields latest "".
Audit sweep results: every other punk-owned consumer already sorts with
vcompare (punk::lib repl/udp checks, libunknown, repl autocomplete,
loadedlib copy/promote, punk_main/project_main starkit selection - the
latter even carries the 'package versions does not always return
versions in increasing order!' warning comment); packagepreference's
uses are mappings/exact-pins, not max-picks. Naive sorts remain only in
VENDORED third-party code (tcllib doctools docidx/doctoc/doctools.tcl,
vendormodules pattern-1.2.8.tm:267) - flagged, not edited, per the
vendorlib no-edit policy. Project 0.18.9.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Publication side-effects handled ahead of the punkbin push (b5c258f
there - first family -r1 artifacts + metadata + defaults flip to
tclsh9.0.5-punk-r1.exe):
- remote-only rows skip support files (the six metadata tomls now ride
in the server's sha1sums beside the runtimes; same extension set as
the local candidate filter).
- the '(= server default)' active marker also matches via the active's
beside-toml artifact identity: the default names an immutable -r<N>
artifact while the active is typically its materialized WORKING name,
so exact-name matching alone would never fire post-family.
Live-verified against the pushed server: no-name fetch resolves
tclsh9.0.5-punk-r1.exe + metadata; list -remote shows all three -r1
artifacts Same version, the default row marked, active
tclsh9.0.5-punk.exe annotated '(= server default)' through its toml
identity, and no toml leakage. G-067 note records publication done
(r1 immutable - next republish takes -Dfamilyrev=2). Rewrapped;
roundtrip pin PASS; layout copy refreshed. Project 0.18.8.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The user-observed ordering discrepancy decomposed into two edition
divergences, both now handled:
- launch paths run DIFFERENT powershells: the .ps1 twin executes under
the invoking shell (pwsh 7) while the .cmd routes via the wrap-pinned
'cmd.exe /c powershell' (Windows PowerShell 5);
- between those editions BOTH Hashtable key enumeration order AND
culture-sensitive Sort-Object collation differ (NLS vs ICU treat
hyphens differently). Fix: ordinal comparison for every name ordering
(candidates, platforms dirs, list -remote local+remote-only rows) in
ps1, LC_ALL=C glob/ls/sort in bash - verified byte-identical
list -remote output across cmd->powershell5, pwsh7-on-twin, and bash.
bin/AGENTS.md .ps1-twin paragraph corrected (was stale): the twin is
SELF-MATERIALIZED by the polyglot's batch layer - created when missing,
fc-compared and re-copied when content differs - so it self-heals after
a re-wrap on the next .cmd launch; no manual copy step (verified:
deleted twin regenerated byte-identical). Documented caveats: a
direct-.ps1-only user can ride a stale twin until a .cmd launch heals
it, and payload code must avoid edition-specific behaviour. Rewrapped;
roundtrip pin PASS; layout copy refreshed (twin deliberately NOT
hand-copied - the mechanism owns it now). Project 0.18.7.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Both payloads in parity (rewrapped; roundtrip pin PASS; twins + layout
copy refreshed): the remote comparison now answers "is my active runtime
the recommended one?" at a glance - summary lines show the platform's
server default (defaults.txt, best-effort fetch with cache; absent
server = markers gracefully omitted) and the locally active runtime
(annotated '(= server default)' on match); rows gain the local listing's
'*' active marker and a '(server default)' annotation on the default's
row, whether it is locally present or remote-only.
Also fixes the latent bash bug the verification exposed: CRLF server
sha1sums made locally-present runtimes ALSO appear as remote-only rows
(bash read keeps the \r that msys grep strips, so the \r-suffixed name
failed the local-existence test) - the remote-only loop now strips \r,
and punkbin's build_sha1sums.tcl writes LF sha1sums going forward
(punkbin 4b403a3). Project 0.18.6.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The per-platform default fetch runtime is a punkbin RELEASE DECISION, so
it now lives as server data (punkbin defaults.txt, c4d948f there) rather
than values baked into the payloads: updating the recommendation is a
one-line punkbin edit in the same change-set that publishes the artifact
it points at - immediate effect for every deployed punk-runtime, no
punkshell release, validated by punkbin's maintenance script, and
mirror-curatable. No pre-convention fallback per user direction (no
mirrors exist yet) - a server without the file gets an actionable
name-it-explicitly message, as does a platform without a recorded line.
Both payloads in parity (rewrapped; roundtrip pin PASS; twins + layout
copy refreshed): baked rt_default/runtime_available prong values removed
(the linux-arm one had already drifted from the server's actual artifact
name - the config-in-code failure mode this removes); default lookup
keys on the RESOLVED platform, so no-name 'fetch -platform <p>' now
works for foreign staging too (supersedes the foreign-name-required
rule); cached-copy fallback on network failure. ps1 fix: $arch? in
usage strings parsed as a variable NAMED 'arch?' - brace-delimited.
Verified: file:// happy path (local + foreign default), no-entry
platform, missing-manifest, and the LIVE server's 404 path (graceful
until punkbin c4d948f is pushed). Project 0.18.5.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User direction: 32-bit windows joins the canon marked for what it is -
status supported with runtime+lib tiers (hosting for available
third-party runtimes/libs), buildsuite CANDIDATE (zig can target it;
whether we add a buildsuite is undetermined) - the hosting-vs-building
axis expressing exactly that split. Name win32-ix86 = platform::generic's
own 32-bit x86 token (no normalization needed); normalize additionally
folds hand-typed i386/i486/i586/i686.
- vendorlib_tcl8/9 gain win32-ix86 dirs per the tree sync contract.
- punk-runtime local detection: ps1 returns win32-ix86 on genuine 32-bit
windows hosts (PROCESSOR_ARCHITECTURE x86 without ARCHITEW6432 - a
32-bit shell on a 64-bit OS keeps the x86_64 default: the runtime
store serves what the OS can run); bash MINGW32/CYGWIN prongs key off
the i*86 machine arch. Rewrapped; roundtrip pin PASS; twins + layout
copy refreshed.
Project 0.18.4.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The powershell payload's list -remote built its local-file dict with an
older inline filter (only .txt/.tm excluded), so active.toml, artifact
metadata tomls and stray .log files showed as local runtimes in the
server comparison. Now routed through Get-PunkRuntimeCandidates - the
same filter 'list'/'use' use (directories, *_BUILDCOPY*, .txt/.toml/
.tm/.tmp/.log excluded) and the bash payload's -remote loop already
used (list_candidates). Verified against the LIVE pushed punkbin: no
toml/log leakage, comparison rows correct; 'platforms -remote' also
live-verified over the network (all five served platforms). Rewrapped;
roundtrip pin PASS; layout copy + .ps1 twin refreshed. Project 0.18.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Raw-file artifact servers have no directory listing, so served-platform
discovery rides a root-level platforms.txt manifest, now part of the
punkbin layout contract (generated by punkbin's src/build_sha1sums.tcl;
committed in punkbin locally - 7b8a244 - push remains the maintainer's
call; third-party mirrors using the layout carry the same file).
Both payloads in parity (rewrapped; roundtrip pin PASS; layout copy +
.ps1 twin refreshed): 'platforms' lists local bin/runtime/* folders with
the local platform marked; 'platforms -remote' fetches the manifest
(cached-copy fallback), marks local platform / local-dir presence /
local-only dirs, and points at 'list -remote -platform <name>' for
per-platform runtimes. Servers without the manifest get an actionable
message naming the -platform escape hatch and the canon reference
('help platforms'). Verified end-to-end through the wrapped cmd against
a file:// mirror simulation of the local punkbin checkout, including the
no-manifest fallback path. Project 0.18.2.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- platform records + 'help platforms' gain buildsuite
(supported|planned|candidate|none): whether OUR zig buildsuites produce
runtimes for a platform. Deliberately a separate axis from tiers -
punkbin-structured repos (or third-party equivalents) can host runtimes
built by any mechanism, so runtime-tier hosting coexists with
buildsuite=none (netbsd/dragonflybsd-class examples, per user review).
openbsd/netbsd/dragonflybsd records now carry the runtime tier.
Current values: win32-x86_64 supported (suite_tcl90), linux-x86_64
planned (G-105), linux-arm64/linux-arm/macosx/freebsd-* candidate,
rest none.
- G-109 notes record the binary-.tm platform reality the user's fat-tm
experience established (retracting this survey's earlier
'tm-are-cross-platform' shorthand): multi-platform fat .tm are the
wrong shape (oversized downloads; same-version shadowing leaves no
drop-in path), platform segregation must ride tcl:™️:path via
per-platform TM ROOTS selected by boot - and platform dirs cannot nest
inside an existing tm root (subdirs are namespace components), so those
roots must be sibling trees. Candidate manifest field: declared target
platform so libunknown can skip wrong-platform binary .tm.
Project 0.18.1.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Survey outcome (punkbin vs punkshell platform folders): five naming sites
had drifted - punkbin folders, bin/runtime, vendorlib_tclX dirs, the
punkboot platform_generic snips (an old platform::generic copy), and the
Tcl platform package itself whose outputs vary by version (1.1.x renamed
modern macOS to 'macos', aarch64/amd64 pass through unmapped).
Canon: <os>-<cpu> punkshell platform-dir names, cpu normalized
amd64->x86_64 and aarch64->arm64 (arm = 32-bit; on macosx arm folds to
arm64 - Apple silicon is 64-bit only), os macos->macosx. The universal
'macosx' name is the runtime-tier convention (punkbin + bin/runtime keep
one macOS folder, per make.tcl's existing collapse); per-arch
macosx-x86_64/macosx-arm64 serve the lib tier.
- new module punk::platform 0.1.0: platforms (canonical records with
status supported/dormant/recognized + tiers), normalize, local
?-tier lib|runtime? - full PUNKARGS argdocs. Tcl's platform package
stays the raw identifier underneath.
- punk 0.2.7: 'help platforms' topic (alias 'platform'; all prefixes
mutually ambiguous so they fall through to command lookup, per the
env/environment precedent) - canon table with the local interpreter
marked and raw platform-package identifiers for comparison.
- boot: punkboot platform_punk (inline normalization copy, sync-comment
contract with the module) in punk_main.tcl/project_main.tcl/make.tcl;
all platform-dir call sites switched to it. make.tcl exercised live;
main.tcl copies brace-verified.
- vendorlib_tcl8/9 synchronized to canon: freebsd-amd64 -> freebsd-x86_64
(READMEs updated), freebsd-arm64/linux-arm64/macosx-arm64 added, tcl8's
untracked-empty linux-arm now tracked + tcl9 gains linux-arm, stray
untracked macosx-arm empties removed, msys-x86_64 marked dormant
pending a utility decision, top-level READMEs state the canon contract.
- punk-runtime bash prongs emit canonical names: aarch64 -> linux-arm64
(no fetch default until punkbin carries that folder), arch-aware
freebsd/openbsd/netbsd/dragonflybsd via normalized cpu tokens.
Rewrapped; roundtrip pin PASS; layout copy + .ps1 twin refreshed.
Flagged for user decisions (recorded in G-105 Notes): punkbin linux-arm
holds an arm64-named kit (recommend linux-arm64 folder at next arm
publish; artifacts immutable), msys-x86_64 disposition, optional
platform-1.1.x re-vendor, src/vfs stays mapvfs-categorized (recommend a
mapvfs platform column when cross-wraps land, not a .vfs tree
restructure). Project 0.18.0.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Cross-build staging surface (both payloads in parity, rewrapped polyglot,
layout copy + .ps1 twin refreshed, roundtrip pin PASS):
- fetch/list/use accept -platform <p> (punkbin platform-DIR names, never
zig triples); resolution: -platform arg > PUNK_RUNTIME_PLATFORM env >
detected local platform; shape-only lowercase validation (server URL
paths are case-sensitive - ps1 uses -cnotmatch; default -notmatch is
case-insensitive and passed Win32-X86_64-class typos in testing).
- foreign fetch requires an explicit runtime name (fetch defaults only
make sense for the platform you stand on).
- use -platform manages that folder's active.toml/materialization - the
marker travels with the folder when deployed (provisioning story; unix
exec bits restored at deploy time).
- list flags !TARGET-MISMATCH when a runtime's metadata target disagrees
with the folder it sits in (cross-fetch misfiling guard).
- run stays LOCAL ONLY: rejects a leading -platform, ignores the env
override, later args pass through to the runtime untouched.
- new 'help' action (actions, options, env vars, examples) and a real
usage block on no-args invocation (was a bare action list).
- bash FreeBSD platform dir aligned to punkbin's actual freebsd-x86_64
(was freebsd-amd64; the G-105 platform-dir naming-alignment item).
Verified on both payloads directly and through the wrapped cmd: noargs,
help, local list unchanged, foreign use-materialization + mismatch flags,
foreign-fetch refusal, run guard, env override (and run's immunity to
it), bad-name validation. Project 0.17.9.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Raw mode on twapi-less windows runtimes made dependable and quiet: lazy
singleton server (tsv-shared per process, spawn no longer at module
load), parent-pid self-reaping (no orphan pwsh), the 20s
keepalive-without-pinger and the first-message listener kill (reader
Close disposing the pipe stream) both fixed, disableraw served on
no-inputmode runtimes (8.6 path), enable confirmed via live tcl9
-inputmode before return, script resolution env -> argv0 -> module-dir
-> embedded copy (pwd fallback gone; kits need no scriptlib on disk).
PUNK_PS_CONSOLEMODE_DEBUG=1 for diagnostics both sides.
scriptlib/utils/pwsh reconciled: canonical consolemode_server_async.ps1
rewritten (protocol enableraw|disableraw|ping|exit, parent-pid watch,
posh-git MIT attribution for the C# snippet), five experiment variants
retired (consolemode_server.ps1, *_async1.ps1, *_async.2ps1,
consolemode.ps1, consolemode_enableraw.ps1), README labels the folder.
New console suite psfallback.test pins the embedded-copy/file sync and
the resolution chain. punk::repl stale comment fix (no behaviour
change). Verified per the recipe recorded in the goal detail file:
hidden-console selftests on suite tclsh90spr + zipfs kit tclsh90sprzip
(25s-idle survival, stop/respawn, zero orphans), live make.tcl-shell and
bare-repl sessions driven by injected keystrokes (console mode
0x1E7<->0x1E1 read externally), embedded-resolution forced run, console
testsuite 76/76. G-106 acceptance met - achieved flip recorded in the
detail file; archive move follows in the next commit.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Scriptset extension (ps1 + bash payloads in parity, rewrapped polyglot,
layout-shipped copy + untracked .ps1 twin refreshed, roundtrip pin PASS):
- list: per-runtime summary parsed from the <rootname>.toml metadata record
beside each runtime (variant, tcl patchlevel, revision, piperepl on/off,
from=<artifact> on materialized working copies).
- use <artifact-r<N>-name>: materializes the immutable artifact into its
WORKING name (minus -r<N>) with the metadata toml copied alongside, then
selects it - the G-103 naming decision's artifact->working mapping, so
republishing never churns consumers. use <workingname> unchanged.
- fetch of -r<N> artifacts also retrieves the metadata toml from punkbin
(absence tolerated for pre-family runtimes).
- rootname handling strips only .exe (dotted patchlevels break last-dot
stripping for extensionless unix names); same exe_split fix applied to
family_artifacts.tcl artifact/toml naming for the G-105 cross-target
future. Candidate listing excludes directories and .log files (parity
cleanup; bash side previously listed directories).
Verified on the wrapped bin/punk-runtime.cmd (powershell 5 branch) and the
bash payload under git-bash: all three family members materialized from
their -r1 artifacts with metadata shown in list, and 'punk-runtime run'
launched the active punk family runtime (9.0.5, piperepl machinery,
//zipfs:/app/tcl_library). Project 0.17.7.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The runtests toplevel guard loads the bootsupport punk::lib snapshot -
this re-vendor puts the parity-fixed compat family there (the
testinterp guard already resolved the dev module via prefer-latest).
punkproject.toml 0.17.4 + CHANGELOG entry.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Acceptance verified in full (evidence in the detail file's Progress
section): concurrency suite green on Windows Tcl 9.0.3 (runtests) and
Tcl 8.6.17 (direct tcltest drive) plus a linux WSL tclsh 8.6.14 run
from a native-filesystem staging - two-writer no-corruption/no-loss
with a clean polling reader, lock timeout naming the holder, dead-pid
and age stale-breaks, non-interactive duplicate-INSTALLER recovery.
Real builds under the re-vendored 0.6.0 run with zero lock timeouts,
zero tripwire warnings and unchanged decisions.
Index entry moved to GOALS-archive.md; reference sweep: G-027's
punkcheck note updated to achieved tense, G-028 gains the
advisory-lock name-the-blocker precedent pointer. Detail file moves to
goals/archive/ in the adjacent commit (pure rename).
punkproject.toml 0.17.3 + CHANGELOG entry.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Acceptance verified in full (evidence in the detail file's Progress
section): characterization suites pass with one recorded pin flip,
lifecycle.test pins batch/OO field equivalence (-targets_cksums incl)
and o_record_list coherence across sequential events, the retired-trio
grep is clean, and a full make.tcl build completes with skip/copy
decisions unchanged against pre-refactor .punkcheck state.
Index entry moved to GOALS-archive.md; reference sweep: G-095 notes gain
the chokepoint-achieved pointer, the transient concurrent-save evidence
observed during verification, and the inherited MAX_PATH rider pointer
(G-087/G-094, unaddressed); G-027's punkcheck note updated to achieved
tense. Detail file moves to goals/archive/ in the adjacent commit (pure
rename per the doc-restructure rules).
punkproject.toml 0.17.2 + CHANGELOG entry (punkcheck ships in kits; the
in-shell punkcheck API surface changed with the retirement).
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
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
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
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
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
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
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
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
- 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
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
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
Groundwork requested for the future rework of n/ n// n/// output to punk
tables with terminal-width responsiveness: the underlying display elements
and navigation/retention semantics are now pinned so only deliberately
REWORK-flagged pins flip when the layout changes.
- punk/ns nslist.test (11): tier A pins get_ns_dicts classification buckets
(the machine contract: children/packagetails/packageprefixes per the
package-names derivation, commands/exported/imported/aliases/procs/
ensembles/oo/coroutines/usageinfo incl alias-target doc resolution and its
update_definitions dependence, alias edge cases, native via builtin ns);
tier B pins per-element marking layout-agnostically (underline/underdouble/
underdotted package styles, type tag colours, exported green / imported -I
under overtype SGR canonicalization, the punkargs doc icon); tier C pins
the CURRENT hardcoded 2-col/4-col layout and nspath subtables, explicitly
flagged to flip with the rework; KNOWN QUIRK pinned: bare nslist without
-types errors with a malformed message (literal dollar-known_types).
Findings recorded: the red-strike/masked alias display branches appear
unreachable from current bucket derivation.
- punk/nav/ns navns.test (6, new suite dir): ns/ navigation state machine
(absolute/relative/glob-no-nav/failed-nav preservation/quad-colon
normalization), v-form content selection, ensemble annotation, and the
::punk::nav::ns::ns_current variable contract.
- punk/repl nscurrent.test (4): repl retention proven against a REAL
codethread (repl::init, synchronous runscript sends): inscope evaluation,
retention across submissions, n/ navigation retained, auto-create-with-
notice for a missing current namespace.
- punk::repl 0.5.2 fix: repl::start''s codethread seeding template
namespace-eval''d the full ns_current VARIABLE name, creating a stray
namespace of that name in every code interp (phantom child in n/ listings
of the nav namespace). Now ensures only the parent ::punk::nav::ns.
Subshell namespace carry-over semantics unchanged; pinned behaviourally
(mirrored template) plus a source-text guard, pending the planned
end-to-end piped subshell test (E3) at the shell level.
Verified: punk/ns 80/80, punk/nav 6/6, punk/repl 7/7 under Tcl 9.0.3;
nslist/navns/nscurrent green under 8.7. Console queries mocked throughout
(the render path consults get_size/get_tabstops). Project 0.12.33 +
CHANGELOG; tests AGENTS.md index updated.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New check pair in punk::lib::check, in the established style (G-076
console_deadspin exemplar: pure facts-in/verdict-out classifier
tclbug_nestedswitch_tracelines_signature + has_tclbug_* proc returning the
standard buginfo dict {bug bugref description level}, auto-surfaced through
the help tcl warning report via the info procs enumeration).
Unlike the version-gated checks, this one is a LIVE behavioural probe (safe
and cheap - no console interaction): a dynamically-defined proc with a
nested 4-word switch is enterstep-traced for inner arm 1 (affected split-
list index 1 - reports line 3) and the default arm (index 5, beyond the
command word count - reports line 2 correctly), matched against the
characterized wrong/right signature. Detection therefore flips
automatically on a Tcl runtime containing the upstream fix - no fixed_in
version variable needed. Probe layout note: a 2-arm probe would put the
default body at affected index 3 and hide the signature (both arms
mismark) - the middle arm exists to push default to safe index 5 (this
initially bit the probe itself, confirming the law once more).
Followup-when-fixed documented in the proc: re-verify with
scriptlib/developer/tcl_switch_traceline_repro.tcl, flip the
ns/cmdtrace.test GAP pins and fixed-canary, update the punk::ns::cmdtrace
argdoc caveat, note the fixed-in version. New canary test
cmdtrace_upstream_bug_check_canary asserts the check still reports the bug
- on a fixed Tcl it fails first and points at that workflow.
Verified: punk/ns 69/69 and punk/lib 37/37 under Tcl 9.0.3; cmdtrace.test
6/6 under 8.7; all has_tclbug_*/has_libbug_* procs exercised help-tcl style
without error; probe self-cleans (no temp proc/var residue).
punk::lib buildversion 0.4.3 -> 0.5.0 (new API procs = minor); project
0.12.32 + CHANGELOG; tests AGENTS.md index updated.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
cmdtrace gains -pause <bool> (default 1, existing interactive behaviour
unchanged): -pause 0 bypasses the "paused - hit enter key to continue"
askuser in _cmdtrace_leave so cmdtrace runs unattended and the marked-up
traced-body report (return value) can be captured by scripts and tests.
Line-mismark investigation (all punk-free raw enterstep probes, results
byte-identical on Tcl 8.6.17 / 8.7a6 / 9.0.3 - conclusively upstream):
- with the ::switch argdoc available (punk::args::moduledoc::tclcore),
cmdtrace marks flat single-block switches and 2-word-form nested switches
correctly for EVERY arm; the residual mismarks match the raw trace data
- empirical law, predictive across 4 command shapes x 6 arms and deeper
nestings: an arm body at index j of the split pattern/body list reports
container-relative lines (shift = switch command line within its
containing script - 1) exactly when j lands on a LITERAL word of the
switch command (options, --, or the block); dynamic words and j beyond
the command word count fall back to correct arm-relative attribution.
Position-based, not call-order based. Explains the ticket observation
that the affected-arm count "varies based on switch options".
- suspected machinery: Tcl_SwitchObjCmd passes split-list index j as the
TclNREvalObjEx word; TclInitCompileEnv adopts ctx line[word] when the
index happens to be in range of a per-word array describing the switch
command itself (the splitObjs munging looks intended to prevent this)
Artifacts:
- new tests ns/cmdtrace.test (5): -pause 0 smoke + error-call count,
flat-switch and 2-word-nested correct-mark guards, upstream mismark GAP
pins (gated on have_tclcoredocs - cmdtrace arm-offset correction parses
supplied switch commands against the ::switch argdoc)
- scriptlib/developer/tcl_switch_traceline_repro.tcl: standalone pure-Tcl
repro + findings write-up, suitable as an attachment/addition to the
upstream ticket
- cmdtrace argdoc caveat updated: cites the ticket and the characterized
pattern (was "possibly an unreported bug")
Verified: punk/ns suite 68/68 under Tcl 9.0.3; cmdtrace.test 5/5 under 8.7.
punk::ns buildversion 0.5.0 -> 0.6.0 (new flag = minor); project 0.12.31 +
CHANGELOG; tests AGENTS.md index updated.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The stringstartswith(*) arm of get_dict_can_assign_value''s multi-member
tail-clause reservation walk compared the prefix against $tp (the type
string) instead of $rv (the candidate value). Consequences (pinned pre-fix
in the previous commit):
- a later optional clause mixing literal(...) and stringstartswith(...)
members never had genuinely matching trailing words reserved - a greedy
-multiple argument swallowed them and the tail clause was silently lost
- a prefix text that happened to prefix the literal type string (e.g str vs
stringstartswith(str)) wrongly reserved NON-matching words, raising a
spurious toomanyarguments overflow
One-token fix; allocation_tailclause_ssw_reservation_GAP flipped to the
correct expectations (matching words reserved; non-matching words left to
the -multiple argument with no error); literal-only and no-match guards
unchanged. Known remaining approximation (pre-existing, noted in the
buildversion changelog): the walk still requires a literal* member in the
tail clause''s typelist to run at all - a stringstartswith-only tail clause
is not reserved.
Verified: full punk/args suite 231 total / 227 passed / 0 failed (4 intended
skips), punk/ns 57/57 under Tcl 9.0.3; allocation.test 10/10 under Tcl 8.7.
punk::args buildversion 0.12.2 -> 0.12.3; project 0.12.30 + CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com