Everything a bake EMITS is now keyed by the artifact's TARGET platform rather than the
driving tclsh's personality: the bin/runtime/<tier> store a runtime is read from, .exe
suffixing of runtime files and kit outputs, presence checks, and whether the pre-deploy
process sweep uses tasklist/taskkill or ps/kill. Host semantics - copy commands, path
handling, filesystem case rules, prompts - stay keyed to the host.
The default target is the host's platform canon EXCEPT for a cygwin-family host (an
msys2/cygwin-runtime tclsh, which reports tcl_platform(platform) unix on windows), which
targets win32-x86_64. Such a host now drives the identical kit set, names and store
addressing as a native tclsh; before, it reported every kit runtime=missing against a
nonexistent mingw64-x86_64 store.
mapvfs.config entries take an optional 4th element naming the kit's target platform, so a
runtime kept in another platform's tier is a first-class mapping entry. The linux tclkit
entry now declares linux-x86_64 and bakes to a suffixless bin/punkshell902.
Zip-type kits assemble without zipfs in the driving tcl: when tcl::zipfs::mkimg is absent
(any 8.6) the image is built by raw-runtime split + punk::zip::mkzip + concatenation - the
same helper the zipcat type uses. Both mount identically (archive-start-relative offsets).
Fixes exposed by the above: the runtime capability probe looked for a suffixless filename
and so reported find-fail for every runtime on windows; with real capabilities arriving,
the extraction try-list was found to test capability presence rather than value, which
would send a plain zipfs runtime down the kit path where a failed sdx mksplit replaces
raw_runtime with the un-split original; BUILDCOPY names now follow the runtime's own
filename; runtime map keys strip only .exe (file rootname would eat the last dotted
segment of tclsh9.0.5); and native windows command lines run through a guard suppressing
msys2's posix-path argument rewriting - without it taskkill /PID <n> reached taskkill as
taskkill C:/<msysroot>/PID <n>, so the sweep could find a running kit but never replace it.
punk::platform folds the msys2 family (mingw64/mingw32/ucrt64/clang*) onto one stable
'msys' tag and CYGWIN_NT onto 'cygwin' - msys2's uname renders that token from MSYSTEM,
so one binary otherwise canonizes differently per launching shell. New normalize_os;
cygwin-x86_64 added to the platform table; 'help platforms' documents the fold.
make.tcl check reports the derivation on one line; bakelist rows carry target=<platform>
for non-default targets and the detail block names the tier; workflow text gains key note
[K9]. New characterization suite maketclplatform.test (5 tests, two self-gating on
discovering and probing a real msys/cygwin tclsh). Full suite 1112 tests: 1093 passed,
18 skipped, 1 failed = the documented exec-14.3 baseline.
Verified: msys2 tclsh8.6 bakelist output identical to native Tcl 9; a changed punk91
baked and deployed from that host with the sweep killing a running instance msys ps
cannot see; a real cross-target linux kit baked from windows to a 24MB ELF; a zipfs-less
8.6 bake producing a bootable zip kit.
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; 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
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
Both payloads + rewrapped bin/punk-runtime.cmd (roundtrip pin green 9/0/1skip).
Embedded read WITHOUT executing the target: bash uses unzip's central-directory
read; ps1 uses .NET System.IO.Compression with a manual EOCD scan + prepend
offset fixup (.NET does not apply the self-extractor fixup - the pure-zip tail
is copied to a temp file and read there; delta 0 = plain zip also fine). The
cooperative probe (piping a reader into the EXECUTED target) is printed as the
documented fallback when no zip reader exists, execution caveat stated.
Report: field-by-field embedded/sidecar columns, !DISAGREE flags on shared-field
mismatches, file sha1 checked against the sidecar (!SHA1-MISMATCH), stray
renamed copies identified embedded-only, pre-v1 artifacts report sidecar-only
(schema-tolerant parsing; new Get-PunkRuntimeRecordFields helper). Verified on
the emitted v1 r2 artifacts: sidecar-agree case, renamed-stray case, pre-v1
case - ps1/bash output parity, wrapped cmd smoke under Windows PowerShell 5.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Field report (jcross1, Windows PowerShell 5): Get-FileHash not
recognized during list -remote while Write-Host/Invoke-WebRequest
worked. Root cause class: Get-FileHash is a SCRIPT-defined function in
PS 5.1's Microsoft.PowerShell.Utility, resolved via PSModulePath
autoload - a damaged PSModulePath (pwsh7 path pollution, overridden env,
redirected user module dirs) removes it while the module's compiled
cmdlets keep working. Effects were wrong results, not just noise:
spurious UPDATE AVAILABLE rows (null local hash) and fail-closed fetch
verification.
New Get-PunkFileSha1 computes sha1 via .NET (SHA1.Create over a stream,
lowercase hex) at all three former Get-FileHash sites; works on any
PowerShell edition/state incl FIPS, and emits a one-time informational
note when the damaged condition is detected (chosen over
detect-and-offer-install/env-repair: nothing to install once the
dependency is gone, and persistent environment mutation from a fetch
tool is disproportionate). Bash payload already probes
sha1sum/shasum/sha1/openssl - unchanged. bin/AGENTS.md records the
no-script-module-cmdlets payload rule.
Verified: hash parity with Get-FileHash under powershell 5 and pwsh 7;
list -remote via the rewrapped .cmd (correct Same-version rows);
damaged-PS simulation (probe forced unresolvable): note printed once,
zero errors, hashing correct; scriptwrap roundtrip pin
runtimecmd_roundtrip PASS (payload + regenerated bin output committed
together). CHANGELOG bullet added under the in-flight 0.19.0 entry
(rides the user's pending release-notes commit).
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
User policy 2026-07-22: doc examples for the polyglot bin utilities show
the .cmd extension (bin/punk-runtime.cmd ...) - extensionless windows
invocation resolves the .ps1 twin, which is ExecutionPolicy-gated and
runs under the invoking powershell edition, while .cmd always executes
via the wrap-pinned tested path. The same .cmd file runs on unix shells
unmodified, so one form serves all platforms with path-separator style
as the only remaining per-platform difference. Sweep confirmed no
existing user-facing guidance contradicts (none exists yet).
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
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
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 remaining pre-policy punkshell-own bin utilities take the punk- prefix
(bin/AGENTS.md policy, G-096); external-tool wrappers (dtplite/sdx/kettle)
and getpunk stay unprefixed. No behaviour changes ride along.
- runtime scriptset: sources/toml renamed (src/scriptapps/bin/punk-runtime.*),
the eight ps1 usage/guidance messages now say punk-runtime.cmd, the bash
payload's filename-derivation comment example updated; REWRAPPED ->
bin/punk-runtime.cmd (checkfile clean) with the .ps1 twin regenerated as a
byte-copy. The roundtrip + checkfile pins retarget the new names and pass.
- tclargs + bits: sources/tomls renamed; bin artifacts moved BYTE-FAITHFULLY
(git mv, no rewrap): a pre-rename drift check showed both carry
pre-template-refresh wraps (477-byte delta = the template's 2025
wmic-deprecation timestamp fix; runtime was in sync). Regenerating them is
a behaviour change and is deliberately not smuggled into the rename -
recorded in the goal. Fresh .ps1 twins cut from the current .cmds; stale
untracked bits.bat/bits.ps1/tclargs.ps1/runtime.ps1 removed.
- selfsign experiments: SELFSIGN.PS1 -> punk-selfsign.ps1 (case normalized),
wrap toml + cert-create script renamed; the four untracked bin experiment
scripts renamed on disk; the exported .cer is not a script and keeps its
name.
- runtimebash_wsl.test: functional staged-filename sites updated (bash
./punk-runtime.bash; solo-fixture cp) along with comments.
- Docs: bin/AGENTS.md (examples, policy paragraph records the sweep, runtime
contract section, pin pointer corrected to runtimecmd_roundtrip.test),
src/scriptapps/AGENTS.md, root AGENTS.md, README.md, src/README.md,
untracked bin/runtime/README.md, G-060 reference, libunknown comment (src
copy; root modules/ + bootsupport copies catch up on their re-vendor
cycles).
Suites green: scriptwrap + binscripts 26 run / 25 passed / 1 constraint-skip
/ 0 failed - the roundtrip pin passes against the renamed artifact.
Discovered and recorded for user decision (goal Progress): the project
LAYOUT stores ship stale utility copies - runtime.cmd (2025-era payload) and
getzig.cmd (the G-096 rename missed this channel) - so generated projects
still receive old-named utilities; folding the layout channel into this
goal's scope vs a layout-sync mechanism is flagged.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The zig version is now the first argument (default = the suite pin,
0.16.0) and each version installs into tools/zig-x86_64-windows-<version>
- the zip's own root folder name, so the old rename-to-tools/zig step and
its post-ExtractToDirectory lock retry/GC dance are gone. Installed-check
warns if the exe's reported version mismatches its versioned folder.
Documented limitations: dev builds (/builds/) and pre-0.14.1 releases
(old zig-<os>-<arch> naming) are not handled - the punkbin flat tools/
mirror path covers those if one must be pinned. The bash side stays an
honest stub with the same argument convention.
Rewrapped via scriptwrap::multishell (punk905_beta src script) ->
bin/punk-getzig.cmd (the untracked .ps1 twin byte-synced locally).
Verified all four paths through the polyglot: explicit present version,
no-arg default, existing-zip verify+extract (0.15.2 zip with no dir), and
the FULL network path (0.15.2 artifacts removed then re-materialized:
mirror latency selection -> download zip+minisig -> signature verified ->
versioned extract -> ZIG VERSION 0.15.2). G-096's remaining item is now
the final clean-checkout re-verification only.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The build016 experiment port lands in the tracked recipe (root_module/
createModule creation, addLibrary+linkage, .root_module.* method sweep,
linkSystemLibrary options arg, array_list.Managed, Io.Dir dir-walks with
b.graph.io, wrapfiletofile ported to the 0.16 entry/Io idiom). 0.14 support
deprecated per user direction; 0.14.1 remains archived on punkbin. Verified
on the pinned default (bin/tools/zig-x86_64-windows-0.16.0): build PASS,
shells 9.0.5, tcl-test parity 557/357/200/0 identical to the 0.14.1 build.
punk-getzig payload pins -> 0.16.0 (windows zip + linux tarball), re-wrapped
checkfile ERROR-free, ps1 twin refreshed. punkbin commit 54714d7 holds the
0.16.0 archive; push pending gitea recovery (server currently 500s).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Scriptset (src/scriptapps/bin) and the generated bin wrapper renamed; the
untracked bin/getzig.ps1 twin replaced by punk-getzig.ps1 (byte-copy of the
.cmd - launchability convenience for cmd.exe-or-powershell starts). Payload
improvements: self-references updated, and the ziglang.org release URL now
derives its version from the single $releasearchive pin (was a separately
hardcoded 0.15.1 vs the 0.15.2 archive). Re-wrapped via scriptwrap multishell;
checkfile ERROR-free (the two boundary-scan warnings are the documented-normal
polyglot ones). bin/AGENTS.md gains the punk- naming policy section
(exceptions: dtplite/sdx/kettle wrappers, getpunk; sweep of bits/runtime/
tclargs/selfsign is G-097).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
'dev doc.validate' invokes a bare dtplite command which the repl
unknown-handler resolves via auto_execok on PATH - no dtplite executable
existed (only the legacy misnamed bin/dtplite_run.bat), giving
"invalid command name dtplite".
- src/scriptapps/dtplite.tcl: LF-converted (polyglot payloads are embedded
verbatim into the LF-only multishell output); fall back to the
project-vendored tcllib (src/vendorlib_tcl9/<arch>/tcllib*) when the
invoking tclsh lacks the dtplite package
- src/scriptapps/dtplite_wrap.toml: new scriptset config (tclsh nextshell
on all platforms)
- bin/dtplite.cmd: generated polyglot via
punk::mix::commandset::scriptwrap::multishell (checkfile-clean, LF-only)
- src/tests/shell/testsuites/binscripts/dtplite.test: artifact pins
(LF-only, checkfile, byte-identical round-trip re-wrap) + execution
usecases (usage error, validate good/bad file, validate directory tree,
html generation) - 8/8 pass under runtests
- AGENTS.md (bin, src/scriptapps): record the dtplite scriptset, its test
pin and the LF-only payload requirement
- punkproject.toml: 0.12.22 -> 0.12.23
Verified: 'dev doc.validate' in punk902z src validates all 64
src/doc .man files clean. The doctools pipeline remains interim -
punk::args is the intended doc source of truth.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- list -remote against an unreachable artifact server now warns and compares using the previously fetched sha1sums.txt instead of dying on an unhandled Invoke-WebRequest error (parity with the bash payload); no cached copy -> clear error + return
- the fetch path always fell through silently to a cached sha1sums.txt on download failure - it now announces "proceeding with cached copy" (behaviour unchanged, messaging explicit)
- fixed latent undefined-variable bug: the list -remote branch created the runtime folder with $container (only defined in the fetch branch) - now $archfolder
- bin/runtime.cmd regenerated (checkfile clean, roundtrip pin green 9 pass + 1 skip); verified live: unreachable PUNKBIN_URL -> cached-fallback table renders (tclsfe-x64 "Same version" against the punkbin pin), normal fetch path unchanged
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- bash/zsh payload gains list -remote parity with the powershell payload: local-vs-server sha1 comparison table (Same version / UPDATE AVAILABLE / not listed on server, plus remote-only entries), falling back to a cached sha1sums.txt with a warning when the server is unreachable (the powershell version has no cached fallback - candidate backport)
- both payloads: artifact server base url overridable via PUNKBIN_URL (mirrors/testing - also what makes the new feature testable offline)
- first real catch for the 512-byte label guard: the payload growth pushed the template's :exit_multishell target label across a boundary from its callsite (checkfile ERROR at wrap time); fixed with a documented byte-alignment spacer comment at the end of runtime.bash, and the resize-the-spacer workflow recorded in bin/AGENTS.md
- bin/runtime.cmd regenerated via scriptwrap (roundtrip pin green; multishell suite 9 pass + 1 skip on 9.0.3 and 8.7); runtime.bash syntax-checked under bash and zsh; windows list/use/run sanity re-verified
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- run no longer launches the last runtime alphabetically: resolution is PUNK_ACTIVE_RUNTIME env override -> bin/runtime/<platform>/active.toml (constrained single-key toml, written by the new 'use <name>' subcommand, marked with * in list, covered by the existing bin/* VCS ignores) -> sole installed candidate -> error listing candidates. First fetch sets active only when none recorded; later fetches never steal it. Stale active (file removed) reported with reselect guidance.
- bash/zsh payload fetch reaches checksum parity with the powershell payload: fetches sha1sums.txt, locates the stored hash, skips when the local copy matches, downloads to .tmp and installs only on sha1 match; sha1 tool detection (sha1sum/shasum/sha1/openssl) with refusal of unverified downloads when none present; optional runtime-name argument added (fetch <name>)
- fixes: powershell "stored hash from sha1sums.txt" printed an undefined variable ($storedhash -> $stored_sha1); bash MSYS branch invalid assignment (interp = ...); candidate listings for run/list/use exclude .tmp leftovers and non-runtime files (a stray .txt could previously be selected by run)
- runtime scriptset sources relocated to src/scriptapps/bin (proper home alongside getzig.*); bin/runtime.cmd regenerated via scriptwrap from the new location - roundtrip test path updated, suite green on 9.0.3 (8 pass + unix-gated skip), runtime.bash syntax-checked under bash and zsh
- verified live on windows: multiple-runtimes-no-active errors with candidates (previously silently launched tksfe-twapi-x64), use/list/run against tclsfe-x64 and env override to tclsh902z, fetch no-steal + first-fetch auto-set, checksum-match no-download path
- docs: bin/AGENTS.md documents the fetch/use/run contract and updated generated-polyglot workflow paths; src/scriptapps/AGENTS.md scriptset-home wording updated
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- new src/tests/modules/punk/mix/testsuites/scriptwrap/multishell.test (9 tests, green on tcl 9.0.3 + 8.7, unix exec case constraint-gated): scriptset wrap via the module-provided punk.multishell.cmd template (payloads + _wrap.toml fixture) - output produced, MULTISHELL magic line, payloads embedded verbatim, configured win32 nextshell present, LF-only endings, byte-identical re-wrap determinism; checkfile 512-byte label/boundary validation reports no label location errors for a fresh wrap AND for the committed bin/runtime.cmd; the runtime scriptset ROUND-TRIP pin - re-wrapping src/scriptapps runtime.ps1+runtime.bash+runtime_wrap.toml reproduces bin/runtime.cmd byte for byte (verified identical before pinning), so hand-edits to the output or unregenerated payload changes both fail; execution smoke - cmd.exe runs the polyglot and dispatches the powershell payload (windows), sh payload execution gated to unix (on windows the shell layer deliberately relaunches via the win32 nextshell)
- guidance strengthened so "fix bin/<name>.cmd" routes to sources: root AGENTS.md bin/ index entry now states the .cmd polyglots are scriptwrap-generated from src/scriptapps; bin/AGENTS.md gains a "Generated polyglot .cmd scripts - never edit in place" section with the 4-step fix workflow (edit payloads/toml, re-wrap with multishell -askme 0, heed checkfile ERRORs, commit source + regenerated output together); src/scriptapps/AGENTS.md documents the scriptset->bin/*.cmd relationship and regeneration command; tests index updated
- context: the polyglot technique is deliberately maintained despite fragility (user direction 2026-07-10) until hiding techniques close in the underlying languages - these pins are the guardrails
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The dash-delimited launch package modes of built punk shells (dev/os/src/
internal, implemented in src/vfs/_config/punk_main.tcl) had no agent-facing
record. bin/AGENTS.md now documents the mode grammar and, in operational
terms, the src mode that matters for verifying working-tree changes:
exe-location-based project-root discovery, the source module paths it
prepends, package prefer latest (dev 999999.0a1.0 modules beating
kit-stamped snapshots), and how 'package present' distinguishes a src-mode
session from a plain kit launch. Also records the both-Tcl-generations
interactive verification convention (a Tcl 8.6-based shell plus the current
Tcl 9-based incarnation, deliberately not version-pinned) and the role of
the plain runtime kits under bin/runtime/ for punk-free probes.
Root AGENTS.md Child DOX Index gains the bin/ entry, and .gitignore gains
a !/bin/AGENTS.md negation alongside the other source-controlled bin items
(the /bin/* ignore is why no doc lived there before).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com