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
src/vendormodules_tcl8 is a tm root - a pkgIndex-style directory there is
invisible to tm handling and nothing referenced this copy (experiment
leftover; added in an early bulk commit). Its designed home is the
platform vendor-library tree: pkgIndex-based, win-x64 dll, Tcl 8 ->
src/vendorlib_tcl8/win32-x86_64/ (reachable via make.tcl's bootstrap
lib paths and the libs build; kit inclusion stays declarative via
src/runtime/vendorlib_vfs.toml - no kit content change from this move).
pages.tcl's comment drift from the old TODO-resolution sweep (283ca03b)
reverted per the vendorlib dont-edit-vendor-code contract - the moved
copy is now byte-identical to the working punk86bawt.vfs payload copy.
Smoke-verified: package require cookfs -> 1.9.0 (dll load, Mount cmd
present) from the new location under native tclsh86t.
(tdbc/sqlite3-1.1.5.tm beside it is NOT misplaced - a namespace subdir
in a tm root is correct tm layout: package tdbc::sqlite3.)
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
suite_tcl90 now assembles and verifies the G-103 family as part of the
default pipeline:
- kit-family: two staging trees (core, bi) wrap into working-name products
tclsh9.0.5.exe / tclsh9.0.5-punk.exe / tclsh9.0.5-punk-bi.exe under
out/family. Attached image mirrors the installed prefix - tcl_library/ at
the app root (stock C-boot position, no main.tcl - falls through to the
interactive shell), tm tree at tcl9/<ver>, batteries under lib/ with their
installed-shape pkgIndexes (../../bin -> /app/bin), dlls under bin/, plus a
one-line stock pkgIndex hook at lib/pkgIndex.tcl extending auto_path (the
tclPkgUnknown mid-scan growth mechanism tcllib's own index uses).
- tools/family_check.tcl: per-member self-containment verification from a
scratch dir with scrubbed env - patchlevel, zipfs tcl_library, tzdata/
encodings, attached tm modules, functional Thread (cross-thread eval), vfs
zip-mount round-trip, tcllib md5 + tcllibc accel engaged, piperepl
default-ON/opt-out per variant (::tclsh(istty) discriminator), Tk
create/destroy + tklib for bi. All three members PASS.
- kit-family-artifacts + tools/family_artifacts.tcl: punkbin-layout emission
(immutable -r<N> names via -Dfamilyrev, per-artifact toml metadata with
variant/sha1/versions/provenance/G-107 evidence, sha1sums.txt), run UNDER
the plain family kit itself. punkbin publication stays a user step.
- build_tclthread/build_tk return pkgidx+version facts; tclvfs configured
package generation shared between prefix install and family staging;
tm-module install list single-sourced; manifestUuid helper tolerates
repos without the fossil manifest setting.
- consumers: mapvfs.config entries punk9_beta (punk + punk9wintk905.vfs) and
punk9bi_beta (punk-bi + punk9win_for_tkruntime.vfs); working names copied
to bin/runtime/win32-x86_64 (untracked). src/runtime/AGENTS.md stale
runtime.cmd references updated to punk-runtime (G-097).
Full pipeline suite.tcl build PASS end-to-end; verification evidence
recorded in the goal Progress section. Remaining: punk-runtime list/use
metadata surfacing, kit-wrap trial of the new mapvfs entries.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Completes the user's conversion of punk::mix::base from manual
versioning to the magic-version mechanism: header Meta block + magic
provide block in base-999999.0a1.0.tm, version history relocated to the
new base-buildversion.txt (0.1.2 - same version, mechanism-only
change). The file RENAME itself landed one commit early (ab3e1a45)
via the staged index riding an unrelated commit - net effect is the
repo's preferred move-then-edit sequence, recorded here for clarity.
src/modules/AGENTS.md: punk::libunknown is now the only manually
versioned module; base noted as converted 2026-07-21.
Bootsupport syncs from the rebuild ride along: base-0.1.2.tm restamped
from the converted source; libunknown comment catch-up
(runtime.cmd -> punk-runtime.cmd reference).
Conversion verified: make.tcl modules builds base-0.1.2.tm from the
magic-versioned source under Tcl 9.0.3 and 8.7a6 (the original build
failure was the unrelated pre-c971e6c7c4 zipfs mkzip dotfile defect,
fixed by cli 0.5.2's fallback in ab3e1a45).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Tcl 8.7 builds predating core fix c971e6c7c4 (tkt 7d5f1c13089d463e7796
'zipfs mkzip broken on Windows dotfiles') die with 'non-unique path
name' on dot-prefixed entries - hit by the templates modpod's layout
.fossil-custom payloads (in the modpod source since G-087 stage 3)
whenever a modpod rebuild triggers under such an interp (c:/tcl87 =
8.7a6 is the PATH-default tclsh here). Diagnosed from the eager
punkcheck INPROGRESS remnants (two died-mid-transfer attempts) plus a
3-file minimal repro; the suspected punk::mix::base version-scheme
conversion was coincidental and is innocent.
The fallback reuses the invocation already established for zipfs-less
interpreters (punk::zip::mkzip -base ...), deletes the partial zip a
failed mkzip leaves behind (punk::zip::mkzip refuses to overwrite),
and notes the interpreter + upstream ticket on stderr. Healthy
interpreters keep the zipfs path.
Verified: re-triggered templates-modpod rebuild under 8.7a6 completes
exit 0 via the fallback; the built modpod mounts with identical entry
sets under 9.0.3 and 8.7a6 (incl the .fossil-custom/mainmenu payload
that broke mkzip); punkcheck/mix/lib suites 193 pass under 9.0.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The Tk opt-in census surfaced that the full suite cannot run unattended in
the batch/suite-built shell: winDialog.test (72 cases) and winMsgbox.test (19)
pop real OS dialogs whose message-injection automation does not drive them
here, so each blocks waiting on a human. The first attempt hung there and the
engine correctly reported no-totals/fail.
Adds a dedicated file-exclusion mechanism: tools/test_gate.tcl gains -notfiles
(a Tcl list of test-file globs passed to the driver as one -notfile list
value - a flat -testargs cannot carry a multi-file list through the option
chain, since -notfile takes a single list arg), and build905.zig gains a
per-library -Dtestnotfiles-<lib> knob defaulting to each LibSuite's
default_notfiles. tk defaults to excluding winDialog.test + winMsgbox.test so
its census completes hands-off; -Dtestnotfiles-tk="" re-includes them for a
manual interactive run. The exclusion is recorded in the evidence summary
(notfiles key). Empty for every other library (no behaviour change).
Verified: tk census now completes unattended (9865 run / 8127 passed / 1711
skipped / 27 failed, result pass; log shows winDialog/winMsgbox in the driver
skip list); thread gate still PASS with notfiles {} recorded.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The external libraries the suite builds and ships now run their own
testsuites under the suite-built shell as named recipe steps - evidence for
the exact zig-built combinations nobody upstream tests.
tools/test_gate.tcl generalized into the shared engine: -mode gate|record
(gate = parsed totals diffed against the tracked dispositioned baseline,
the core-gate mechanism; record = run must complete, failures recorded not
fatal), -driver selection (tcllib-family trees run via their own
support/devel/all.tcl - sak's underlying driver, standard aggregate totals,
per-file child interps), -summaryfile/-library line-record evidence
summaries for the G-103 artifact-metadata consumer (shape documented in the
goal detail file), file-error evidence capture (@+ blocks, runAllTests
error-exit sections). A run with no parseable totals FAILS the step in
every mode - infrastructure breakage must never masquerade as recorded
results. Core gate semantics unchanged; the core gate step now also writes
out/testreports/tclcore.summary.
build905.zig: steps test-thread test-tclvfs test-tcllib test-tklib test-tk
+ composite test-libraries (tk excluded - opt-in: interactive desktop, maps
windows, tens of minutes; intended before publishing bi-family artifacts).
Per-library -Dtestpolicy-<lib>=gate|record|skip and -Dtestargs-<lib>
invocation overrides - no recipe edits needed. Baselines staged in both
flows (suite.tcl item list + bootstrap recipe_items).
suite.tcl: test action takes -steps (default test-gate) and a -zigargs
passthrough (both actions); passes -j1 so combined test invocations
serialize (zig runs independent steps concurrently; thread's suite is
timing-sensitive).
Census results (suite tclsh90s.exe 9.0.5, zig 0.16.0): thread 143/0 failed,
EMPTY baseline, GATE PASS x3 identical consecutive runs; tclvfs 51/7
failed, all dispositioned (3x tcl9 glob-nomatch semantics through vfs
handlers, 4x dead-FTP network tests), GATE PASS x3 identical; tcllib WITH
tcllibc accelerators engaged (E tcllibc markers, crc32-critcl-* variants
running) RECORDED 62328/54 failed; tklib RECORDED 796/18 failed (widgetPlus
drift under Tk 9). No-totals failure path verified in both modes.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Found by G-107's first library-test census: build_tclthread.zig compiled
thread trunk 3.0.7 sources with -DPACKAGE_VERSION="3.0.1", so the dll
self-reported the wrong version, and the pkgIndex declared only capital-T
Thread 3.0.1 - the thread testsuite's 'package require -exact thread 3.0.7'
could never load the package (nothing previously load-tested thread at all).
The version now derives from the tree's AC_INIT (new build_common helpers
acInitVersion/stripChars) and flows into every version-derived name: dll
tcl9thread<nodots>.dll, install dir lib/thread<version>, PACKAGE_VERSION/
PACKAGE_STRING defines, rc resource fields, and a pkgIndex declaring BOTH
'Thread' and 'thread' (threadCmd.c provides both; the testsuite requires
lowercase, existing punkshell consumers the capitalized name). Dead
zip-related consts riding the stale version removed.
Note for the next kit/vfs refresh: the punk905 kit payload
(src/vfs/punk9wintk905.vfs/lib_tcl9/thread3.0.1/) still carries the old
self-consistent 3.0.1-stamped copy - refresh to the derived naming then.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Layout fold ("fold stale layout fixes into this"): both layout stores
(src/project_layouts/vendor/punk/project-0.1/bin and the modpod-templates
equivalent) had shipped a stale 2025-era runtime.cmd and a pre-G-096
getzig.cmd - the getzig rename had missed this channel entirely, so
generated projects still received old-named, stale utilities. Both renamed
via git mv AND refreshed to byte-copies of the current bin/punk-runtime.cmd
+ bin/punk-getzig.cmd; the layout src/runtime/Readme.md references updated
in both stores (the layout bin/runtime/ data-dir READMEs are gitignored -
updated on disk only, like the root bin/runtime/README.md); residual
old-name scan of the layout trees clean. The built modpod zips (root
modules/ + bootsupport templates-0.2.0.tm) carry old names until their
normal re-vendor cycles. Layout paths join the goal Scope per the approved
fold.
Flip mechanics: detail file to goals/archive with Status achieved
2026-07-21 (verification in its Progress section: full rename sweep, pins
retargeted and passing 26/25/1/0, drift findings recorded), GOALS.md entry
removed, GOALS-archive record appended (amended Scope + Acceptance
verbatim), reference sweep: G-103 scope parenthetical (both tiers) +
Relationships and the G-099/G-103 sequencing notes annotated with the
achievement; G-096's archive gains a note recording the layout-channel gap
and its closure. goals_lint clean (75 active-index goals, 31 archived).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Root cause of the punk86-kit runtests failure: a punk-kit interpreter's
boot pre-registers its kit-stamped package versions, and an unversioned
require satisfiable by such a registration never fires package unknown -
the freshly-added bootsupport tm path is never scanned. The old kit's
punk::args 0.1.0 won the require, then the versioned punk::path 0.4.0-
pulled a modern module whose load-time argdoc needs punk::args::define:
invalid command name.
Floors added: punk::args 0.12- (runtests.tcl toplevel), punk::lib
0.5.1- (both 8.6 lpop guards; punk::path 0.4.0- already floored in
discovery.tcl). Feature-era minimums, not latest pins - their purpose is
rejecting fossils so package unknown resolves the bootsupport copy.
Verified: the floors alone resurrect even the OLD fossilized punk86 kit
(discover-only + a 35/35 suite run); native 9 and 8.6 unaffected.
concurrency.test child preamble floors its punkcheck require (0.6-):
kit-hosted children boot with kit-stamped punkcheck PRELOADED, and a
stale kit (pre-vfscommonupdate _vfscommon) made children fail on
'invalid command name punkcheck:🔒:acquire' - the floor turns that
into a loud version-conflict in the child log.
src/tests/AGENTS.md records the floor rationale and the kit-hosted
child-suite requirement (vfscommonupdate-current kit content).
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 two child-spawning tests (two-writers, lock-holder) proceed on the
children's done-marker files, but a just-finished child can still hold
its redirected stdout log open for a beat after writing the marker - on
Windows the -cleanup tree delete then hits 'permission denied'
(observed as a ~1-in-3 flake under the slower Tcl 8.6 interp, exposed
by the new native-8.6 runtests support; same race existed under Tcl 9).
cleanup_workspace retries the delete briefly (10s deadline) instead of
flaking. 8/8 consecutive clean runs under 8.6.17 post-fix; Tcl 9.0.3
punkcheck subtree 84/84.
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
The validated compat family is brought across for the harness: guarded
'package require punk::lib' when ::lpop is absent, at both boot levels -
the toplevel two-stage boot (right after punk::args, whose parse needs
lpop at runtests.tcl's own argument parsing) and the singleproc
testinterp (before the shellrun preload, whose runx parses via
punk::args::parse). No-ops on Tcl 8.7+/9: -discover-only stays ~0.35s.
Native 8.6.17 verification: -discover-only works; punkcheck subtree
84/84, punk/lib subtree 43/43+1 gated skip, runner discovery suite
22/22, and a multiproc (-singleproc 0) probe 49/49.
Tcl 9.0.3 regression per the src/tests/AGENTS.md runner-change
contract: full suite in both modes with -report json,
runtests_parity.tcl reports PARITY: ok (files=96 total=1064
passed=1047 skipped=16 failed=1 - the sole failure is the documented
pre-existing exec-14.3 baseline).
src/tests/AGENTS.md records the supported-interpreter change and the
still-broken punk86-kit runtests route (kit/dev module skew - use a
native 8.6 tclsh for 8.6 legs).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Reviewed against the real 8.7/9 lpop via a 24-case differential (results,
final list state, error messages, errorcodes) - the compat proc was
correct on every success path; all divergences were error-path:
- out-of-range errors said 'tcl_lpop index ...' with no errorcode; now
the builtin's exact message and {TCL VALUE INDEX OUTOFRANGE}
- variable-access failures named the internal upvar link variable and
flattened detail (missing array element misreported as 'no such
variable'; unset var lost its TCL LOOKUP errorcode). Fixed by probing
with a plain read in the caller's frame BEFORE creating the upvar
link - through a link, or once a link merely exists, Tcl downgrades
the error class.
Finding: the assumed 8.6 divergence does not exist - 8.6's core index
parser already accepts TIP-176 M+N arithmetic, so compat::lpop now has
zero known divergence from the builtin (doctools note corrected).
compat.test extended (3 -> 10 tests): a differential parity matrix that
runs wherever the builtin exists (self-updating pin against future core
changes), static pins for values/errors/errorcodes that also run under
8.6 where no builtin exists, an unconditional M+N arithmetic pin, and
an 8.6-only pin that punk::lib installs lpop as the compat alias.
Green under Tcl 9.0.3 (9 pass/1 gated skip) and native 8.6.17
(9 pass/1 gated skip).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The five decorative 'echo --Installing package X--' addSystemCommand steps
(2024-era) spawned 'echo' as a program - a cmd BUILTIN that only resolved when
a coreutils echo.exe happened to be on PATH. In the PATH-scrubbed bootstrap
environment the spawns failed and took the tm installs, install-libraries and
(transitively) make-zipfs down with them - the reason the zip-wrapped shells
never landed in scrubbed composite runs while every package step was green.
zig's own step reporting makes the banners redundant.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Per the G-095 note, the advisory protocol is only effective once all
writers carry it - bootsupport re-vendored immediately after landing.
Verification under 0.6.0: 'make.tcl modules' + full 'make.tcl project'
exit 0 with zero lock timeouts, zero tripwire warnings, no spurious
recopies, all kit installs skip 'no change detected', and no
.punkcheck.lock / .punkcheck.tmp.* leftovers anywhere in the tree.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Saves are write-temp-then-atomic-rename with bounded retry for Windows
sharing violations; load_records_from_file retries transient open
denials during a writer's replace window (parse errors stay strict -
they mean real corruption). Readers gain torn-read immunity with no
reader-side protocol.
New punkcheck::lock namespace (PUNKARGS-documented): advisory sibling
lockfile <punkcheckfile>.lock via open {WRONLY CREAT EXCL}, contents
naming holder pid/host/installer/timestamp, channel held open for the
duration, in-process reference-counted re-acquisition (sequential
make.tcl installers over one root must not self-deadlock). start_event
acquires; event end / installtrack destroy releases; flushes and
chokepoint saves outside an event take a transient lock. Contention
retries with backoff to -timeout (env PUNKCHECK_LOCK_TIMEOUT, default
15s) then errors naming the holder; stale locks break on provably-dead
holder pid (twapi process_exists / kill -0, capability-gated) or age
(-staleage / PUNKCHECK_LOCK_STALEAGE, default 300s).
Deferred flushes merge own records (INSTALLER by -name, touched
FILEINFO by -targets) into freshly-loaded file state under the lock
instead of wholesale overwrite; an mtime/size tripwire warns when a
non-protocol writer (e.g. older vendored punkcheck) touched the file
between load and save.
Duplicate-INSTALLER recovery: clean actionable error when stdin is
non-interactive (punkcheck::lib::stdin_is_interactive - strict twapi
GetConsoleMode on the real stdin handle on Windows, -inputmode probe /
test -t 0 on unix); the interactive prompt gains the synced-targets
deletion-wedge caveat. default_excludefiletail_core adds .punkcheck.*
so protocol siblings are never installable content.
Consumers verified without edits: cli and five make.tcl sites end their
events (lock released at end); make.tcl's vfs/bin kit flows destroy
their installers on every path (destructor releases).
New concurrency.test (6 tests): two child installer processes with a
polling reader (no parse errors, both installers survive, no duplicate
INSTALLERs, no lock/tmp leftovers), lock timeout naming the holder then
success after release, dead-pid and age stale-breaks against planted
lockfiles, non-interactive duplicate-INSTALLER error via pipe-stdin
child, protocol-sibling exclusion pin.
Matrix: Windows Tcl 9.0.3 84/84 (runtests), Windows Tcl 8.6.17 84/84
(direct tcltest drive - the runtests harness itself needs lpop under
native 8.6), linux WSL tclsh 8.6.14 84/84 (native-FS staged run).
punk/mix subtree unaffected (150 pass / 1 known constraint-skip).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Three deltas surfaced by the PATH-scrubbed clean-checkout demonstration:
- build.zig: default-entry re-export of build905.zig's build so the documented
plain 'zig build stage|bootstrap' works from the tracked suite dir (the
recipe keeps its versioned filename; staged flows still invoke it via
--build-file).
- critcl_zig.config + recipe: settings move under an EXPLICIT target
(win32-x86_64-zig) and the tcllibc step passes -target win32-x86_64-zig.
critcl otherwise chooses its build target by probing PATH for compilers -
with a gcc visible the config defaults engaged (why G-098's flow worked),
but the scrubbed environment fell back to critcl's builtin msvc 'cl'
target and all 25 accelerator modules failed with "couldn't execute cl".
Verified green in BOTH environments (scrubbed and normal PATH).
- build905.zig comptime gate: the stale 0.13-dev minimum becomes the actual
suite pin (0.16.0) with a message pointing at punk-getzig and the README
(acceptance: the recipe records the zig version it is written against).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The whole pipeline now lives in the zig recipe; Tcl remains the tool exactly
where a tclsh is guaranteed to exist - run by the FRESHLY BUILT suite shell
as build steps:
- New steps (native-host builds): smoke (static shell patchlevel; zip shell
patchlevel + attached tzdata/autoload), tklib / tcllib (their own installers,
batch, -pkg-path as a cached output dir installed into the prefix, + package
smokes incl withdrawn-Tk tooltip), tcllibc (critcl driving zig cc via the
tracked critcl_zig.config, module list parsed from tcllib's version.tcl,
pinned-zig dir prepended to PATH, + accel smoke), test-gate (tools/
test_gate.tcl - the parsed-totals gate vs expected_test_failures.txt,
-Dtestargs passthrough).
- Package landing moves into the recipe proper: thread pkgIndex.tcl
(build_tclthread), tk pkgIndex.tcl (build_tk), and the tclvfs script package
incl .in-template substitution + dll (build_tclvfs_shared
install_tclvfs_package) - all hooked to the install step.
- Step scripts: tools/test_gate.tcl, tools/suite_smoke.tcl, tools/pkg_smoke.tcl
(run under the built shell; assertions live in Tcl).
- Two windows-childproofing findings encoded: built-shell Runs execute the
CACHED artifact (no ../lib/tcl9.0 beside it) so each such Run gets
TCL_LIBRARY pointed at the source tree's script library (the zip smoke
deliberately excluded - its attached library is the thing under test); and
cached (non-side-effect) Runs spawn with stdout IGNORED, leaving the tcl
child without a stdout channel ('can not find channel named "stdout"',
critcl's logging) - such runs capture stdout to give the child a real pipe
while keeping caching.
- suite.tcl: thinned to the fossil dev flow - fetch live checkouts (git kind
now handled in the main loop for critcl's pin), stage the recipe, delegate
to the staged steps (run_zig_steps; 'test' delegates to test-gate). Default
-steps and the bootstrap default grow to the full pipeline short of
test-gate. critcl_zig.config + expected_test_failures.txt join both staging
lists. Docs updated (README two-flow section, sources.config two-surface
header, overlay section); .gitignore learns .zig-cache/ and zig-pkg/ (zig
0.16 extracts fetched packages into zig-pkg/ beside the manifest).
Verified (fossil flow): full pipeline PASS - suite_smoke static+zip, tklib
tooltip:2.0.4 under withdrawn Tk, tcllib md5/sha1/cmdline, tcllibc:2.0 with
md5-critcl-accel:1; 'suite.tcl test -testargs {-file http.test}' delegates to
the gate step (528/519/9/0 GATE PASS).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Batched punkcheck-managed build outputs from 'make.tcl modules' +
'make.tcl bootsupport' after the G-094 landing: punkcheck 0.4.0 -> 0.5.0
and punk::mix::cli 0.5.0 -> 0.5.1 snapshots (per the G-094 prompt
re-vendor note - make.tcl now runs the unified lifecycle), plus
opportunistic catch-up of stale snapshots (libunknown 0.2.0 -> 0.2.1,
punk::config / punk::lib / punk::repl content syncs from current built
modules).
Verification under the new punkcheck: 'make.tcl modules' x2 and a full
'make.tcl project' complete exit 0 with skip/copy decisions unchanged
against pre-refactor .punkcheck state - copied: 0 on every batch phase,
kit installs skip 'no change detected' (the sole punk905 rebuild traces
to the newly promoted tclsh905 runtime, a genuinely changed source).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
suite_tcl90 gains the no-tclsh source path:
- build.zig.zon: content-hashed manifest pinning each source as a fossil
per-checkin tarball (tcl 1a9c3b9d96 / thread caa1d3aa30 / tclvfs f082c47f9b
/ tk effef6c657 / tklib 2d53beafc0 / tcllib c784f6fda4 - the exact checkouts
the promoted punk905 runtime was built from) plus critcl 3.3.1 as a github
archive. All lazy: the fossil dev flow never triggers a fetch. Refresh =
bump a pin (zig fetch --save). Verified honored under --build-file
build905.zig.
- build905.zig mode split: from the staged recipe copy the full graph
registers as before; from the TRACKED suite dir (sources.config present,
no ../tcl905) only the staging steps register. 'zig build stage'
materializes pinned sources + a recipe copy into ../_build/<suite> (the
same layout suite.tcl's fossil staging produces - both flows share the
staged invocation, and the stage dir derives from the suite folder name so
copy-and-tweak isolation holds). 'zig build bootstrap' chains the staged
build: nested zig invocation with suite.tcl-parity cwd (parts of the
recipe resolve sources cwd-relative), forward-slash prefix (the prefix
flows into -DTCL_PACKAGE_PATH as a C string literal - backslashes broke
the stubs compile), per-zig-version shared cache dir, hermetic-child env
scrub, ReleaseFast default.
- tools/stagetree.zig: host-compiled materializer. Pinned mode keys a
.stage-materialized marker on the dependency's content-addressed cache
path (pin bump = invalidation, stale trees deleted so orphans cannot
survive); always-mode for recipe items; fossil/git checkouts at the
destination are never touched (tested).
Verified: 'zig build stage' against the fossil-populated stage refreshes
only the recipe copy (checkouts untouched, fossil changes empty); a full
copy-and-tweak suite copy (suite_tcl90zt) ran 'zig build bootstrap' from
nothing but the tracked tree + pinned zig - all 7 sources fetched/staged
from the manifest, all four shells built; tcl::build-info reports the same
9.0.5+1a9c3b9d... as the fossil-flow build and the zip shell boots its
attached library (tzdata + autoload).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
installtrack/installevent is now the only implementation of the .punkcheck
record lifecycle (targetset init/add-source/started/end). Each event takes
a persistence policy at start_event (-persistence eager|deferred): eager
keeps the current per-op read-modify-write behaviour; deferred accumulates
updates in the installtrack's in-memory working recordset until an explicit
$installer flush (event-scoped save). QUERY stays never-persisted.
punkcheck::install rebuilt as a tree-walking OO consumer in deferred mode -
its records now carry the full field set (-metadata_us/-ts_start_transfer/
-transfer_us/-cksum_us and -targets_cksums incl all-targets mode), pinned
field-equivalent with OO-installed records by the new lifecycle.test.
Legacy zero-caller proc pipeline (start_installer_event, installfile_begin/
started_install/finished_install/skipped_install) retired to error-with-
pointer shims; installfile_help rewritten for the OO lifecycle; the live
shared engine installfile_add_source_and_fetch_metadata is unchanged.
punk::mix::cli's commented-out legacy call sites removed (0.5.1, no
behaviour change).
Single save chokepoint: every lifecycle write funnels through installtrack
save_working_recordset - the G-095 attachment point.
Coherence and latent fixes (each pinned in lifecycle.test):
- start_event refreshes the working recordset; sequential events on one
instance no longer clobber prior targetset writes (end/end_event now
clears the active-event slot, so a second start_event is valid)
- event reconstruction maps record -ts_begin/-ts_end to constructor opts
(flush no longer rewrites prior event history timestamps)
- installtrack as_record: stray backslash-space wrote -name with a
trailing space, breaking by-name lookup after any flush
- get_recordlist misspelled variable; targetset_dict nonexistent helper
- extract_or_create_fileset_record stdout print removed (isnew returned;
targetset_init reports via debugchannel); dead targetset class removed
Pin flip (recorded in installtrack.test): the full-lifecycle test's
end + end_event double-end now correctly errors - lifecycle uses one of
$event end / $installer end_event, matching all real consumers.
Suites: punkcheck install/installtrack/lifecycle 78/78, punk/mix subtree
incl cli prune.test 144 pass / 1 constraint-skip on native Tcl 9.0.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Generation of the configure-products a fresh checkout lacks moves from
suite.tcl tree-writes into the zig recipe as build-cache overlays:
- tclUuid.h / tkUuid.h / threadUuid.h: wrapfiletofile Run outputs consumed
via overlay include dirs added FIRST per module (stale tree copies from
pre-G-102 flows can never shadow; the LazyPath also carries the step dep).
The unused addUpdateSourceFiles tree-write variants (build905 prepare-source,
build_tclthread) are removed.
- tclsh.exe.manifest: configure-time substitution (tcl.h parsed by the new
build_common.zig helpers); tclsh.rc compiled from an overlay COPY beside the
generated manifest because rc resource references resolve rc-file-relative
before include paths. Both tclsh exes switch to .include_paths LazyPaths.
- wish.exe.manifest: overlay dir first in tk.rc include_paths (RT_MANIFEST
resolves through rc include paths - the arrangement the tk build already
relied on). tk.rc itself stays tree-compiled (lives in win/rc, no stale risk).
- thread.rc: compiled from an overlay copy with the tcl.h include inserted
(the historical checkout edit is normalized if a mutated tree is staged);
the staged tclthread checkout's thread.rc edit has been fossil-reverted.
- build905.zig: redundant configure-time top-level library install loop
removed (install_library_tree already covers it); dead zlib stage copy and
the suite.tcl generation blocks removed (read-only version parsing kept for
smokes/logging).
Verified: full staged-mode rebuild PASS (all smokes incl tklib/tcllib/tcllibc);
built binaries carry the overlay products (tcl::build-info reports
9.0.5+1a9c3b9d..., tclsh manifest version 9.0.2.905, tk dll manifest + tk
checkout uuid, thread dll uuid; thread dll's empty FileVersion matches the
pre-change binary - upstream quirk). Source checkouts stay pristine (fossil
changes empty). Core test gate: 69783 run, 12 failed - 11 baselined plus
http-4.14.2, a network-timing flake that passes on isolated rerun (528/519/9/0).
tclsh90sprzip.exe install into out/bin is currently blocked by an open user
application holding the file; the product builds identically into the zig
cache and installs on next run once released.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User direction 2026-07-21 recorded in G-103: piperepl-patched runtime
executables must carry 'punk' in the name (e.g tclsh905punk.exe) so
patched and unpatched are never confusable - now an Acceptance item, with
the open design questions captured (how to encode tcl patchlevel + punk
version, separator choice; existing sub-namespaces punkNNN kits /
tclsh-runtimes / punk- utilities; metadata carries authoritative versions
so filenames stay human-distinguishing). The suite's tclsh90spr/sprzip
are flagged as internal working names in patches/README.md pending the
scheme.
Also noted: punkbin pushes of suite runtimes are deferred until family
members carry Thread etc in the attached zip and the punk-named pr
variants exist - publication follows G-103's artifacts, not the interim
tclsh905/punk905 shapes. goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Per the *_beta convention (trial before punk tests, drop the suffix on
acceptance): punk9wintk905_beta.vfs renamed to punk9wintk905.vfs, the
runtime redeployed as bin/runtime/win32-x86_64/tclsh905.exe (fresh copy
of the suite's tclsh90szip.exe, self-containment smoked), and the
mapvfs.config entry becomes 'tclsh905.exe {punk9wintk905.vfs punk905
zip}' with the promotion recorded in the comment block. tcludp joins the
promoted vfs via vendorlib_vfs.toml (daily-driver expectation - teelog
workflows), installed by make.tcl vfslibs.
Built punk905.exe verified: kitcheck full pass (Thread/vfs/vfs::zip/
sqlite3/twapi/tcllibc/md5-accelerated/tk 9.0.2) plus udp 1.0.13; 'shell'
round-trips (repl 0.5.2, libunknown 0.2.1); kit-hosted console suites
71/71 via the src-mode child launch. Beta artifacts (bin/punk905_beta.exe,
runtime tclsh905_beta.exe) removed. A piperepl-runtime punk kit
(tclsh90sprzip base) remains G-103 kit-family territory.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Fresh clone (shallow path + core.longpaths - the deep-path first attempt
hit windows MAX_PATH on the modpod template trees, caveat recorded) ->
the clone's own punk-getzig fetched 0.16.0 (mirror chain, minisign,
versioned dir) -> cold-cache suite build PASS: 9.0.5 static/zip/pr/przip
shells with recipe-generated configure-products, zip shell smoked, all
tk/tklib/tcllib/tcllibc legs green.
Cold-log 'failed command:' blocks diagnosed as BENIGN zig 0.16 behaviour
(build_runner prints that block for any step with nonempty result_stderr
even on success) triggered by our own tools' informational stderr prints
- zipfs_mkzip/mkimg call echoes now go to stdout and wrapfiletofile's
octet count is removed; rebuild shows zero occurrences, PASS.
All G-096 acceptance items are now met - achieved flip pending user
confirmation.
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 recovered 2024 TCLSH_PIPEREPL patch applies cleanly to current
core-9-0-branch tclMain.c (8 hunks, offset 4). Tracked as
patches/tclMain_piperepl_905.c = stock 9.0.5 + patch + gate-default flip:
ENABLED unless TCLSH_PIPEREPL=0 (2024 was opt-in set-and-not-"0") per the
G-103 punk-kit policy - the goal's Goal/Acceptance were aligned to that
policy first at user request. Era files kept unmodified as recovered
artifacts; patches/README updated (status, gate semantics, known
tcl_interactive early-link divergence when the gate is open).
build905.zig gains tclsh90spr (per-source construction mirroring tclsh90s
with both tclMain compiles - unicode + TCL_ASCII_MAIN ansi - swapped to
the patched file; stock products stay byte-for-byte unpatched) and
tclsh90sprzip (zipfs_mkimg wrap of the pr exe, -infile form). patches/
added to suite.tcl's staged recipe items. Full suite build PASS.
Behaviour matrix recorded in the goal: 9/9 stock-equivalence rows
IDENTICAL (script-arg / script-consuming-stdin / piped-commands x
unset/0/1 - open-gate plain scripts behave stock; unread piped payload
never eval'd); feature row proves buffering verbatim into
::tclsh(inputbuffer) (write-trace capture), console reopen success and
repl landing; =0 feature row identical to stock; przip variant identical
to pr - the G-103 punk-kit precursor works.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
All tcl9 zip kits failed the 'shell' subcommand with "could not find
interpreter code": the repl codethread could not resolve root-level tm
packages (commandstack, via punk::packagepreference) after any subdir tm
(punk::args) had resolved on the same path. zipfs_tm_UnknownHandler's
static-path can_skip_update state was WRITTEN keyed by the tm-list root
(currentsearchpath) but READ keyed by the namespace-subdir searchpath
actually scanned (specificsearchpath) - so a punk/ scan poisoned the
ROOT's skip map and later root-level requires were skipped as
known-absent. Only zipfs tm paths take the skip branch, which is why
src/dev filesystem launches never showed it; kits have exactly one
(zipfs) tm path so every shell boot hit it. Independent of the epoch-copy
unsoundness fixed earlier today (reproduced with a fresh libunknown init).
Fix: both added-map writes now key by specificsearchpath, matching the
reader and libunknown::init's indexbase keying. Version bumped to 0.2.1
with history note (the file rename itself rode the previous commit via a
staged git mv; this commit carries the 0.2.1 content).
_vfscommon refreshed via make.tcl modules + vfscommonupdate + vfs (also
picks up today's punk::lib epoch-export, punk::repl collect-guard and
punk::config PUNK_FOSSIL_STORE changes); 5 kits rebuilt. Verified:
ordered probe (subdir-then-root require in a fresh thread) fails on
kit-bundled 0.2.0, passes with 0.2.1; 'shell' now reaches the repl and
evaluates on punk905_beta, punk902z and punk91; full native runtests
sweep twice at machine baseline (1037/1021/15/1 exec-14.3 only).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User requirements batch 2026-07-20 integrated:
- G-103 runtime kit family: buildsuites produce self-contained kits whose
info library and batteries live in the initially attached zip - PLAIN
tclsh kit (Thread + tclvfs/vfs::* + tcllib/tcllibc), PUNK kit (piperepl
applied, ENABLED BY DEFAULT with env opt-out - gating review agreed; the
plain kit serves stock semantics), BI kits adding libraries we build (Tk
now; sqlite3/tdom easy/moderate futures; twapi flagged needs-investigation
under the zig-only policy). tcllib+tcllibc in all members (user lean,
agreed). Artifact metadata in punkbin (+compatible repos) surfaced by the
runtime scriptset list/use. G-018 flagged as substantially subsumed. 8.6
variant deferred through G-101 (static-vfs/metakit questions noted there).
- G-104 make.tcl buildsuite surface: list / info <suite> / build <suite>
with suites SELF-describing (info contract survives the G-102 driver
migration; copied trees appear automatically). mapvfs single-kit/list
wishes noted as sibling ergonomics.
- G-105 cross-target builds: -target as an invocation dimension (suite
folders stay version-named), linux x86_64 first verified via local WSL
with its own test baseline; zig tier findings VERIFIED and recorded -
the freebsd asymmetry suspicion is inverted (freebsd AS TARGET was the
gap, closed in zig 0.16 for FreeBSD 14+ with CI-tested x86_64/aarch64;
building FROM freebsd was already fine); macOS-as-target (SDK/frameworks)
recorded as the hard case; fully-static-musl dlopen limitation drives a
dynamic first linux target.
Cross-edits: G-096 piperepl matrix gains the kit-default policy update
(punk kits opt-out not opt-in); G-101 records the 8.6 kit-family
dependency; G-102 notes the family/target/surface as build-graph products.
goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
A developer (no llm assistance, no punkshell modules - the driver stays
dependency-free plain tclsh) can now copy the suite tree and retarget
sources declaratively: urls/refs/pins live in sources.config (plain line
records 'source <name> <kind> <url> <ref> <dir>', parsed never executed;
fossil sources + the critcl git pin), and the build stage derives from the
suite FOLDER name so a copied tree stages into its own _build/<name>
isolated from the original. -tclbranch becomes a per-run override of the
declared tcl ref. Depth limit documented where the tweaker will read it:
same-major url/ref changes are config-only; version-class changes ripple
into build905.zig (checkout dir names, version-derived tm/dll/manifest
names).
README gains a Retargeting/copying section; its Sources section corrected
(stale per-stage fossil-store location from before the ~/.punkshell/fossils
move, and the G-098 sources were missing from the table).
Direction recorded in G-096 notes (2026-07-20): toml requirement DROPPED
for binary-build buildsuites; long-term intent is bootstrapping without a
pre-existing tclsh (zig acquisition = accepted root dependency; the
freshly built tclsh is the legitimate intermediate for tcllib/tklib
installers and critcl); zig-driver-vs-polyglot question recorded with the
current recommendation (zig hybrid; polyglot counselled against).
Verified: suite.tcl test -testargs '-file assocd.test' passes through
config load + fetch skip-logic + gate on the existing stage; stage
derivation for a copied name resolves to _build/<copyname>.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Under punk91/punk902z/punk905_beta, '-include-paths modules/punk/console/***
-jobs 16' failed all 7 files with zero tests run: child processes boot via
plain kit script dispatch, preloading kit-stamped punk packages
(punk::console 0.7.2) before the payload's src paths apply - the suites'
pinned 'require punk::console 999999.0a1.0-' then version-conflicts and
the child exits 1 (the known shadowing runtests already warned about).
Fix: when the host is a PUNK kit (kit container heuristics AND the
::punkboot namespace marker from punk_main.tcl boot) children launch as
'kitexe src child_test_runner.tcl ...' so they boot the project's src dev
modules - matching what the payload selects. Non-punk kit containers (e.g
tclsh90szip.exe: zipfs app mount, no punk boot) keep the old warning and
get no extra arg. runtests_run_child_process gains a required exemodeargs
param (tpool info args/body replication unaffected).
Tally: file-level failures are not test results, so a FAIL run could sit
beside 'Failed 0' unexplained (user report). The tally line now appends a
fail-coloured 'Testfiles-failed N' whenever testfiles failed.
Verification: console suites 71/71 under punk905_beta, punk91, punk902z
(previously 0 run / 7 files failed); native Tcl903 + suite tclsh90s
unchanged 71/71 with no modeargs; tclsh90szip warning path passes; tally
demo shows 'Total 0 ... Failed 0 Testfiles-failed 1'.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Copying ::punk::libunknown::epoch verbatim into a fresh interp/thread
carries per-epoch 'added' maps that drive zipfs_tclPkgUnknown's
can_skip_sourcing short-circuit - sound only in the interp that performed
the scans. Packages the donor obtained at an earlier epoch (or with no
unknown call: Thread is baked into thread::create'd threads) are absent
from the donor's current-epoch map, so recipients skip their pkgIndex
sourcing and requires fail where stock tclPkgUnknown would succeed.
Bit deterministically as repl_console_backend_tkconsole under the suite
9.0.5 runtime: 'package require Tk' bumps the epoch pre-init, the
codethread inherits the post-bump sparse map, the code interp then can't
find vfs/Thread/registry, its init aborts before the G-001 conredirect
junction vars exist, and the first pending-collect error left the repl
reader inactive until the driver failsafe. Tcl903 escaped only by an
accidental extra epoch bump in its code interp (fresh map, full rescan).
Fix: punk::lib::libunknown_epoch_export (PUNKARGS-documented) - epoch
record with every 'added' map emptied; counters/untracked/scripts/index
globs preserved. Used at all four propagation sites (interp_sync,
snapshot, repl %lib_epoch%, repl safe-arm). Hardening: the repl
pending-collect now tolerates missing junction vars so a code-interp init
failure can't wedge the reader.
Also: test socketpairs pinned to -myaddr 127.0.0.1 (all-interfaces
listens raised windows firewall consent popups for each newly built test
exe - user datapoint).
Verification: consolebackends 3/3 both runtimes (suite 42s->14s); full
runtests sweeps identical on suite runtime and Tcl903: 1037/1021/15/1
with the sole failure exec-14.3 (documented machine baseline). G-098
acceptance sweep met. Pre-existing PUNK_TEST_TK opt-in quirk noted in the
goal (silent early end, both runtimes, out of scope).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com