Browse Source

punk-runtime: no-name fetch defaults come from the server's curated defaults.txt

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
master
Julian Noble 1 week ago
parent
commit
0ac4058bcd
  1. 4
      CHANGELOG.md
  2. 11
      bin/AGENTS.md
  3. 126
      bin/punk-runtime.cmd
  4. 8
      goals/G-103-runtime-kit-family.md
  5. 2
      punkproject.toml
  6. 126
      src/project_layouts/vendor/punk/project-0.1/bin/punk-runtime.cmd
  7. 75
      src/scriptapps/bin/punk-runtime.bash
  8. 51
      src/scriptapps/bin/punk-runtime.ps1

4
CHANGELOG.md

@ -5,6 +5,10 @@ The latest `## [X.Y.Z]` header must match the `version` field in `punkproject.to
Entries are newest-first; one bullet per notable change. See the root `AGENTS.md`
"Project Versioning" section for the bump policy.
## [0.18.5] - 2026-07-22
- `bin/punk-runtime.cmd`: the default runtime a no-name `fetch` retrieves now comes from the artifact server's curated root-level `defaults.txt` (`<platform> <runtimename>` per line - a punkbin release decision, updated there in the same change-set that publishes the artifact it points at; validated by punkbin's maintenance script) instead of values baked into the payloads. Works for any `-platform` (the recommendation is per-platform server data); platforms without a recorded default, and servers without the file, get an actionable message; cached-copy fallback on network failure. The baked per-platform defaults were removed from both payloads - one of them (linux-arm) had already drifted from the server's actual artifact name, which is precisely the failure mode the server-side file eliminates.
## [0.18.4] - 2026-07-22
- Platform matrix: `win32-ix86` (32-bit x86 windows) added to `punk::platform` / `help platforms` - status supported, runtime+lib tiers, buildsuite `candidate` (zig can target it; a buildsuite is undetermined - hosting for available third-party runtimes/libs is supported regardless). `vendorlib_tcl8`/`_tcl9` gained the platform dirs; `punk-runtime` detects genuine 32-bit windows hosts (32-bit shells on 64-bit OS keep the x86_64 default); `punk::platform::normalize` folds hand-typed `i386`/`i486`/`i586`/`i686` to `ix86`.

11
bin/AGENTS.md

@ -120,7 +120,16 @@ root-level `platforms.txt` discovery manifest (part of the punkbin layout contra
generated by punkbin's `src/build_sha1sums.tcl`; third-party mirrors using the layout
carry the same file - raw-file servers have no directory listing, so the manifest IS
the discovery mechanism), with local presence marked and cached-copy fallback;
servers without the manifest get an actionable message. Platform names follow the CANONICAL
servers without the manifest get an actionable message.
The default runtime a no-name `fetch` retrieves is NOT baked into the payloads: it
comes from the server's root-level curated `defaults.txt` (`<platform> <runtimename>`
per line - a punkbin RELEASE DECISION, hand-edited there as part of each publication
change-set and validated by punkbin's `src/build_sha1sums.tcl`; mirrors may curate
their own). The lookup keys on the resolved platform, so a no-name
`fetch -platform <p>` works too; platforms without a recorded default, and servers
without the file, produce an actionable name-it-explicitly message (cached-copy
fallback on network failure). Platform names follow the CANONICAL
punkshell platform-dir names defined by the `punk::platform` module and surfaced as
`help platforms` in the punk shell (cpu tokens normalized: amd64->x86_64,
aarch64->arm64; the bash payload's local-platform prongs emit canonical names - the

126
bin/punk-runtime.cmd

@ -1292,7 +1292,6 @@ scriptroot="${basename%.*}" #e.g "punk-runtime"
#artifact server base url - overridable for mirrors/testing
url_kitbase="${PUNKBIN_URL:-https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master}"
runtime_available=0
#$OSTYPE varies in capitalization across for example zsh and bash
#uname probably a more consistent bet
arch=$(uname -m) #machine/architecture
@ -1301,8 +1300,8 @@ plat=$(uname -s) #platform/system
#we keep the code separate so it can be tweaked easily for unexpected differences
#each prong sets local_platform (the CANONICAL punkshell platform-DIR name - see
#punk::platform / 'help platforms': cpu tokens normalized amd64->x86_64,
#aarch64->arm64) and, where a runtime is published for the platform, rt_default
#(default runtime name).
#aarch64->arm64). Per-platform default fetch runtimes are NOT baked here - they
#are the server's curated defaults.txt (a punkbin release decision).
narch="$arch"
case "$narch" in
amd64) narch="x86_64";;
@ -1311,18 +1310,14 @@ esac
if [[ "$plat" = "Linux"* ]]; then
if [[ "$arch" = "x86_64"* ]]; then
local_platform="linux-x86_64"
rt_default="tclkit-902-Linux64-intel-dyn"
runtime_available=1
elif [[ "$narch" = "arm64" ]]; then
#canonical arm64 (aarch64). punkbin's existing arm kit predates the
#arm64 name and sits in linux-arm - no fetch default here until a
#linux-arm64 punkbin folder exists; name runtimes explicitly.
#arm64 name and sits in linux-arm (the server's defaults.txt records
#per-platform recommendations).
local_platform="linux-arm64"
elif [[ "$arch" = "arm"* ]]; then
#32-bit arm
local_platform="linux-arm"
rt_default="tclkit-902-Linux64-arm-dyn"
runtime_available=1
else
local_platform="linux-$narch"
fi
@ -1332,8 +1327,6 @@ elif [[ "$plat" = "Darwin"* ]]; then
#universal (multi-arch) binaries - the runtime tier keeps ONE macosx folder
#(per-arch macosx-x86_64/macosx-arm64 names serve the lib tree tier)
local_platform="macosx"
rt_default="tclkit-902-Darwin64-dyn"
runtime_available=1
elif [[ "$plat" = "FreeBSD"* ]]; then
#canonical names (2026-07-22): freebsd-x86_64 (punkbin's actual folder; this
#payload previously said freebsd-amd64) / freebsd-arm64
@ -1356,22 +1349,16 @@ elif [[ "$plat" == "MINGW32"* ]]; then
i*86) local_platform="win32-ix86";;
*) local_platform="win32-x86_64";;
esac
rt_default="tclsh902z.exe"
runtime_available=1
elif [[ "$plat" == "MINGW64"* ]]; then
#REVIEW
os="win32"
local_platform="win32-x86_64"
rt_default="tclsh902z.exe"
runtime_available=1
elif [[ "$plat" == "CYGWIN_NT"* ]]; then
os="win32"
case "$arch" in
i*86) local_platform="win32-ix86";;
*) local_platform="win32-x86_64";;
esac
rt_default="tclsh902z.exe"
runtime_available=1
elif [[ "$plat" == "MSYS_NT"* ]]; then
echo MSYS
os="win32"
@ -1383,8 +1370,6 @@ elif [[ "$plat" == "MSYS_NT"* ]]; then
#This breaks calls to various unix utils such as sed etc (wsl related?)
export PATH="$shellfolder${PATH:+:${PATH}}"
local_platform="win32-x86_64"
rt_default="tclsh902z.exe"
runtime_available=1
else
local_platform="other"
os="other"
@ -1538,8 +1523,10 @@ show_help() {
echo " bin/runtime/<p>/ with sha1 verification against the server's"
echo " sha1sums.txt. -r<N>-named family artifacts also fetch their"
echo " <rootname>.toml metadata record. Omitting <name> fetches the"
echo " local platform's default runtime; a FOREIGN platform fetch"
echo " requires an explicit <name>."
echo " platform's recommended default per the server's curated"
echo " defaults.txt (a punkbin release decision; works with -platform"
echo " too) - platforms without a recorded default need an explicit"
echo " <name>."
echo " list ?-remote? ?-platform <p>?"
echo " List installed runtimes with artifact-metadata summaries"
echo " (variant, tcl patchlevel, revision, piperepl policy, source"
@ -1594,18 +1581,41 @@ working_name_of() {
case "$action" in
"fetch")
runtime="$rt_default"
if [[ -n "${1:-}" ]]; then
runtime="$1"
elif [[ "$is_local" -ne 1 ]]; then
#fetch-name defaults only make sense for the platform we are standing
#on - a foreign-platform fetch (cross-build staging) names its runtime
echo "No default runtime for foreign platform '$platform' - name it explicitly:"
echo " $0 fetch <runtimename> -platform $platform"
echo " (see available names: $0 list -remote -platform $platform)"
if [[ "$archtail" == "other" ]]; then
echo "Unrecognised local platform - name one explicitly with -platform"
echo "(canonical names: 'help platforms' in the punk shell)"
exit 1
fi
if [[ ( "$runtime_available" -eq 1 || -n "${1:-}" ) && "$archtail" != "other" && -n "$runtime" ]]; then
runtime="${1:-}"
if [[ -z "$runtime" ]]; then
#no name given: consult the server's curated defaults.txt - the punkbin
#release recommendation (updated there as part of each publication
#change-set; see punkbin AGENTS.md). Per-platform server data, so it
#works for any -platform, not just local.
defaultsurl="${url_kitbase}/defaults.txt"
defaultslocal="${scriptdir}/runtime/defaults.txt"
mkdir -p "${scriptdir}/runtime"
if ! curl -fsSL --output "$defaultslocal" "$defaultsurl"; then
if [[ -f "$defaultslocal" ]]; then
echo "WARNING: could not fetch $defaultsurl - using cached copy at $defaultslocal"
else
echo "Could not fetch $defaultsurl"
echo "No server default available - name a runtime explicitly:"
echo " $0 fetch <runtimename> ?-platform $archtail?"
echo " (see available names: $0 list -remote -platform $archtail)"
exit 1
fi
fi
runtime=$(awk -v p="$archtail" '$1==p {print $2; exit}' "$defaultslocal")
if [[ -z "$runtime" ]]; then
echo "No default recorded for platform '$archtail' in the server's defaults.txt - name a runtime explicitly:"
echo " $0 fetch <runtimename> ?-platform $archtail?"
echo " (see available names: $0 list -remote -platform $archtail)"
exit 1
fi
echo "using server default for $archtail: $runtime"
fi
if [[ -n "$runtime" ]]; then
url="${url_kitbase}/${archtail}/${runtime}"
output="${archdir}/${runtime}"
sha1url="${url_kitbase}/${archtail}/sha1sums.txt"
@ -1689,9 +1699,6 @@ case "$action" in
if [[ -z "$(get_active)" ]]; then
set_active "$runtime"
fi
else
echo "No default runtime currently published for $os ($archtail)"
echo "If one exists on the server, name it explicitly: $0 fetch <runtimename>"
fi
;;
"list")
@ -2347,8 +2354,10 @@ function Show-PunkRuntimeHelp {
write-host " bin/runtime/<p>/ with sha1 verification against the server's"
write-host " sha1sums.txt. -r<N>-named family artifacts also fetch their"
write-host " <rootname>.toml metadata record. Omitting <name> fetches the"
write-host " local platform's default runtime; a FOREIGN platform fetch"
write-host " requires an explicit <name>."
write-host " platform's recommended default per the server's curated"
write-host " defaults.txt (a punkbin release decision; works with -platform"
write-host " too) - platforms without a recorded default need an explicit"
write-host " <name>."
write-host " list ?-remote? ?-platform <p>?"
write-host " List installed runtimes with artifact-metadata summaries"
write-host " (variant, tcl patchlevel, revision, piperepl policy, source"
@ -2623,16 +2632,47 @@ function psmain {
$runtime = ""
if ( $PSBoundParameters["runtime"].Length ) {
$runtime = $PSBoundParameters["runtime"]
} elseif ($arch -eq $script:PunkLocalPlatform) {
$runtime = "tclsh902z.exe"
} else {
#fetch-name defaults only make sense for the platform we are standing
#on - a foreign-platform fetch (cross-build staging) names its runtime
write-host "No default runtime for foreign platform '$arch' - name it explicitly:"
write-host " punk-runtime.cmd fetch <runtimename> -platform $arch"
write-host " (see available names: punk-runtime.cmd list -remote -platform $arch)"
#no name given: consult the server's curated defaults.txt - the
#punkbin release recommendation (updated there as part of each
#publication change-set; see punkbin AGENTS.md). Per-platform
#server data, so it works for any -platform, not just local.
$defaultsurl = "$artifacturl/defaults.txt"
$defaultslocal = Join-Path -Path $rtfolder -ChildPath "defaults.txt"
if (-not (Test-Path -Path $rtfolder -PathType Container)) {
new-item -Path $rtfolder -ItemType Directory -force | out-null
}
try {
Invoke-WebRequest -Uri $defaultsurl -OutFile $defaultslocal -ErrorAction Stop
} catch {
if (Test-Path -Path $defaultslocal -PathType Leaf) {
Write-Host "WARNING: could not fetch ${defaultsurl}: $($_.Exception.Message)"
Write-Host "WARNING: using cached copy at $defaultslocal"
} else {
Write-Host "Could not fetch ${defaultsurl}: $($_.Exception.Message)"
Write-Host "No server default available - name a runtime explicitly:"
Write-Host " punk-runtime.cmd fetch <runtimename> ?-platform ${arch}?"
Write-Host " (see available names: punk-runtime.cmd list -remote -platform $arch)"
exit 1
}
}
foreach ($line in (Get-Content -Path $defaultslocal)) {
$line = $line.Trim()
if ($line -eq "" -or $line.StartsWith("#")) { continue }
$parts = -split $line
if ($parts.Count -ge 2 -and $parts[0] -eq $arch) {
$runtime = $parts[1]
break
}
}
if ($runtime -eq "") {
Write-Host "No default recorded for platform '$arch' in the server's defaults.txt - name a runtime explicitly:"
Write-Host " punk-runtime.cmd fetch <runtimename> ?-platform ${arch}?"
Write-Host " (see available names: punk-runtime.cmd list -remote -platform $arch)"
exit 1
}
Write-Host "using server default for ${arch}: $runtime"
}
$fileurl = "$archurl/$runtime"
$output = join-path -Path $archfolder -ChildPath $runtime

8
goals/G-103-runtime-kit-family.md

@ -409,3 +409,11 @@ Remaining for acceptance:
new 'platforms -remote' action (and third-party mirrors per the Context
"compatible repos" note) enumerate served platforms. Verified end-to-end
against a file:// mirror simulation of the local punkbin checkout.
- 2026-07-22: punkbin layout also gained a curated root-level defaults.txt
(punkbin c4d948f) - the per-platform recommended default a no-name
'punk-runtime fetch' retrieves. A RELEASE DECISION as server data: updated in
the same punkbin change-set that publishes the artifact it points at
(validated by punkbin's build_sha1sums.tcl), so flipping the recommendation
to a family artifact at publication time is a one-line edit with no punkshell
release. The payloads' baked defaults were removed (one had already drifted
from the server's actual linux-arm artifact name).

2
punkproject.toml

@ -1,4 +1,4 @@
[project]
name = "punkshell"
version = "0.18.4"
version = "0.18.5"
license = "BSD-2-Clause"

126
src/project_layouts/vendor/punk/project-0.1/bin/punk-runtime.cmd vendored

@ -1292,7 +1292,6 @@ scriptroot="${basename%.*}" #e.g "punk-runtime"
#artifact server base url - overridable for mirrors/testing
url_kitbase="${PUNKBIN_URL:-https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master}"
runtime_available=0
#$OSTYPE varies in capitalization across for example zsh and bash
#uname probably a more consistent bet
arch=$(uname -m) #machine/architecture
@ -1301,8 +1300,8 @@ plat=$(uname -s) #platform/system
#we keep the code separate so it can be tweaked easily for unexpected differences
#each prong sets local_platform (the CANONICAL punkshell platform-DIR name - see
#punk::platform / 'help platforms': cpu tokens normalized amd64->x86_64,
#aarch64->arm64) and, where a runtime is published for the platform, rt_default
#(default runtime name).
#aarch64->arm64). Per-platform default fetch runtimes are NOT baked here - they
#are the server's curated defaults.txt (a punkbin release decision).
narch="$arch"
case "$narch" in
amd64) narch="x86_64";;
@ -1311,18 +1310,14 @@ esac
if [[ "$plat" = "Linux"* ]]; then
if [[ "$arch" = "x86_64"* ]]; then
local_platform="linux-x86_64"
rt_default="tclkit-902-Linux64-intel-dyn"
runtime_available=1
elif [[ "$narch" = "arm64" ]]; then
#canonical arm64 (aarch64). punkbin's existing arm kit predates the
#arm64 name and sits in linux-arm - no fetch default here until a
#linux-arm64 punkbin folder exists; name runtimes explicitly.
#arm64 name and sits in linux-arm (the server's defaults.txt records
#per-platform recommendations).
local_platform="linux-arm64"
elif [[ "$arch" = "arm"* ]]; then
#32-bit arm
local_platform="linux-arm"
rt_default="tclkit-902-Linux64-arm-dyn"
runtime_available=1
else
local_platform="linux-$narch"
fi
@ -1332,8 +1327,6 @@ elif [[ "$plat" = "Darwin"* ]]; then
#universal (multi-arch) binaries - the runtime tier keeps ONE macosx folder
#(per-arch macosx-x86_64/macosx-arm64 names serve the lib tree tier)
local_platform="macosx"
rt_default="tclkit-902-Darwin64-dyn"
runtime_available=1
elif [[ "$plat" = "FreeBSD"* ]]; then
#canonical names (2026-07-22): freebsd-x86_64 (punkbin's actual folder; this
#payload previously said freebsd-amd64) / freebsd-arm64
@ -1356,22 +1349,16 @@ elif [[ "$plat" == "MINGW32"* ]]; then
i*86) local_platform="win32-ix86";;
*) local_platform="win32-x86_64";;
esac
rt_default="tclsh902z.exe"
runtime_available=1
elif [[ "$plat" == "MINGW64"* ]]; then
#REVIEW
os="win32"
local_platform="win32-x86_64"
rt_default="tclsh902z.exe"
runtime_available=1
elif [[ "$plat" == "CYGWIN_NT"* ]]; then
os="win32"
case "$arch" in
i*86) local_platform="win32-ix86";;
*) local_platform="win32-x86_64";;
esac
rt_default="tclsh902z.exe"
runtime_available=1
elif [[ "$plat" == "MSYS_NT"* ]]; then
echo MSYS
os="win32"
@ -1383,8 +1370,6 @@ elif [[ "$plat" == "MSYS_NT"* ]]; then
#This breaks calls to various unix utils such as sed etc (wsl related?)
export PATH="$shellfolder${PATH:+:${PATH}}"
local_platform="win32-x86_64"
rt_default="tclsh902z.exe"
runtime_available=1
else
local_platform="other"
os="other"
@ -1538,8 +1523,10 @@ show_help() {
echo " bin/runtime/<p>/ with sha1 verification against the server's"
echo " sha1sums.txt. -r<N>-named family artifacts also fetch their"
echo " <rootname>.toml metadata record. Omitting <name> fetches the"
echo " local platform's default runtime; a FOREIGN platform fetch"
echo " requires an explicit <name>."
echo " platform's recommended default per the server's curated"
echo " defaults.txt (a punkbin release decision; works with -platform"
echo " too) - platforms without a recorded default need an explicit"
echo " <name>."
echo " list ?-remote? ?-platform <p>?"
echo " List installed runtimes with artifact-metadata summaries"
echo " (variant, tcl patchlevel, revision, piperepl policy, source"
@ -1594,18 +1581,41 @@ working_name_of() {
case "$action" in
"fetch")
runtime="$rt_default"
if [[ -n "${1:-}" ]]; then
runtime="$1"
elif [[ "$is_local" -ne 1 ]]; then
#fetch-name defaults only make sense for the platform we are standing
#on - a foreign-platform fetch (cross-build staging) names its runtime
echo "No default runtime for foreign platform '$platform' - name it explicitly:"
echo " $0 fetch <runtimename> -platform $platform"
echo " (see available names: $0 list -remote -platform $platform)"
if [[ "$archtail" == "other" ]]; then
echo "Unrecognised local platform - name one explicitly with -platform"
echo "(canonical names: 'help platforms' in the punk shell)"
exit 1
fi
if [[ ( "$runtime_available" -eq 1 || -n "${1:-}" ) && "$archtail" != "other" && -n "$runtime" ]]; then
runtime="${1:-}"
if [[ -z "$runtime" ]]; then
#no name given: consult the server's curated defaults.txt - the punkbin
#release recommendation (updated there as part of each publication
#change-set; see punkbin AGENTS.md). Per-platform server data, so it
#works for any -platform, not just local.
defaultsurl="${url_kitbase}/defaults.txt"
defaultslocal="${scriptdir}/runtime/defaults.txt"
mkdir -p "${scriptdir}/runtime"
if ! curl -fsSL --output "$defaultslocal" "$defaultsurl"; then
if [[ -f "$defaultslocal" ]]; then
echo "WARNING: could not fetch $defaultsurl - using cached copy at $defaultslocal"
else
echo "Could not fetch $defaultsurl"
echo "No server default available - name a runtime explicitly:"
echo " $0 fetch <runtimename> ?-platform $archtail?"
echo " (see available names: $0 list -remote -platform $archtail)"
exit 1
fi
fi
runtime=$(awk -v p="$archtail" '$1==p {print $2; exit}' "$defaultslocal")
if [[ -z "$runtime" ]]; then
echo "No default recorded for platform '$archtail' in the server's defaults.txt - name a runtime explicitly:"
echo " $0 fetch <runtimename> ?-platform $archtail?"
echo " (see available names: $0 list -remote -platform $archtail)"
exit 1
fi
echo "using server default for $archtail: $runtime"
fi
if [[ -n "$runtime" ]]; then
url="${url_kitbase}/${archtail}/${runtime}"
output="${archdir}/${runtime}"
sha1url="${url_kitbase}/${archtail}/sha1sums.txt"
@ -1689,9 +1699,6 @@ case "$action" in
if [[ -z "$(get_active)" ]]; then
set_active "$runtime"
fi
else
echo "No default runtime currently published for $os ($archtail)"
echo "If one exists on the server, name it explicitly: $0 fetch <runtimename>"
fi
;;
"list")
@ -2347,8 +2354,10 @@ function Show-PunkRuntimeHelp {
write-host " bin/runtime/<p>/ with sha1 verification against the server's"
write-host " sha1sums.txt. -r<N>-named family artifacts also fetch their"
write-host " <rootname>.toml metadata record. Omitting <name> fetches the"
write-host " local platform's default runtime; a FOREIGN platform fetch"
write-host " requires an explicit <name>."
write-host " platform's recommended default per the server's curated"
write-host " defaults.txt (a punkbin release decision; works with -platform"
write-host " too) - platforms without a recorded default need an explicit"
write-host " <name>."
write-host " list ?-remote? ?-platform <p>?"
write-host " List installed runtimes with artifact-metadata summaries"
write-host " (variant, tcl patchlevel, revision, piperepl policy, source"
@ -2623,16 +2632,47 @@ function psmain {
$runtime = ""
if ( $PSBoundParameters["runtime"].Length ) {
$runtime = $PSBoundParameters["runtime"]
} elseif ($arch -eq $script:PunkLocalPlatform) {
$runtime = "tclsh902z.exe"
} else {
#fetch-name defaults only make sense for the platform we are standing
#on - a foreign-platform fetch (cross-build staging) names its runtime
write-host "No default runtime for foreign platform '$arch' - name it explicitly:"
write-host " punk-runtime.cmd fetch <runtimename> -platform $arch"
write-host " (see available names: punk-runtime.cmd list -remote -platform $arch)"
#no name given: consult the server's curated defaults.txt - the
#punkbin release recommendation (updated there as part of each
#publication change-set; see punkbin AGENTS.md). Per-platform
#server data, so it works for any -platform, not just local.
$defaultsurl = "$artifacturl/defaults.txt"
$defaultslocal = Join-Path -Path $rtfolder -ChildPath "defaults.txt"
if (-not (Test-Path -Path $rtfolder -PathType Container)) {
new-item -Path $rtfolder -ItemType Directory -force | out-null
}
try {
Invoke-WebRequest -Uri $defaultsurl -OutFile $defaultslocal -ErrorAction Stop
} catch {
if (Test-Path -Path $defaultslocal -PathType Leaf) {
Write-Host "WARNING: could not fetch ${defaultsurl}: $($_.Exception.Message)"
Write-Host "WARNING: using cached copy at $defaultslocal"
} else {
Write-Host "Could not fetch ${defaultsurl}: $($_.Exception.Message)"
Write-Host "No server default available - name a runtime explicitly:"
Write-Host " punk-runtime.cmd fetch <runtimename> ?-platform ${arch}?"
Write-Host " (see available names: punk-runtime.cmd list -remote -platform $arch)"
exit 1
}
}
foreach ($line in (Get-Content -Path $defaultslocal)) {
$line = $line.Trim()
if ($line -eq "" -or $line.StartsWith("#")) { continue }
$parts = -split $line
if ($parts.Count -ge 2 -and $parts[0] -eq $arch) {
$runtime = $parts[1]
break
}
}
if ($runtime -eq "") {
Write-Host "No default recorded for platform '$arch' in the server's defaults.txt - name a runtime explicitly:"
Write-Host " punk-runtime.cmd fetch <runtimename> ?-platform ${arch}?"
Write-Host " (see available names: punk-runtime.cmd list -remote -platform $arch)"
exit 1
}
Write-Host "using server default for ${arch}: $runtime"
}
$fileurl = "$archurl/$runtime"
$output = join-path -Path $archfolder -ChildPath $runtime

75
src/scriptapps/bin/punk-runtime.bash

@ -12,7 +12,6 @@ scriptroot="${basename%.*}" #e.g "punk-runtime"
#artifact server base url - overridable for mirrors/testing
url_kitbase="${PUNKBIN_URL:-https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master}"
runtime_available=0
#$OSTYPE varies in capitalization across for example zsh and bash
#uname probably a more consistent bet
arch=$(uname -m) #machine/architecture
@ -21,8 +20,8 @@ plat=$(uname -s) #platform/system
#we keep the code separate so it can be tweaked easily for unexpected differences
#each prong sets local_platform (the CANONICAL punkshell platform-DIR name - see
#punk::platform / 'help platforms': cpu tokens normalized amd64->x86_64,
#aarch64->arm64) and, where a runtime is published for the platform, rt_default
#(default runtime name).
#aarch64->arm64). Per-platform default fetch runtimes are NOT baked here - they
#are the server's curated defaults.txt (a punkbin release decision).
narch="$arch"
case "$narch" in
amd64) narch="x86_64";;
@ -31,18 +30,14 @@ esac
if [[ "$plat" = "Linux"* ]]; then
if [[ "$arch" = "x86_64"* ]]; then
local_platform="linux-x86_64"
rt_default="tclkit-902-Linux64-intel-dyn"
runtime_available=1
elif [[ "$narch" = "arm64" ]]; then
#canonical arm64 (aarch64). punkbin's existing arm kit predates the
#arm64 name and sits in linux-arm - no fetch default here until a
#linux-arm64 punkbin folder exists; name runtimes explicitly.
#arm64 name and sits in linux-arm (the server's defaults.txt records
#per-platform recommendations).
local_platform="linux-arm64"
elif [[ "$arch" = "arm"* ]]; then
#32-bit arm
local_platform="linux-arm"
rt_default="tclkit-902-Linux64-arm-dyn"
runtime_available=1
else
local_platform="linux-$narch"
fi
@ -52,8 +47,6 @@ elif [[ "$plat" = "Darwin"* ]]; then
#universal (multi-arch) binaries - the runtime tier keeps ONE macosx folder
#(per-arch macosx-x86_64/macosx-arm64 names serve the lib tree tier)
local_platform="macosx"
rt_default="tclkit-902-Darwin64-dyn"
runtime_available=1
elif [[ "$plat" = "FreeBSD"* ]]; then
#canonical names (2026-07-22): freebsd-x86_64 (punkbin's actual folder; this
#payload previously said freebsd-amd64) / freebsd-arm64
@ -76,22 +69,16 @@ elif [[ "$plat" == "MINGW32"* ]]; then
i*86) local_platform="win32-ix86";;
*) local_platform="win32-x86_64";;
esac
rt_default="tclsh902z.exe"
runtime_available=1
elif [[ "$plat" == "MINGW64"* ]]; then
#REVIEW
os="win32"
local_platform="win32-x86_64"
rt_default="tclsh902z.exe"
runtime_available=1
elif [[ "$plat" == "CYGWIN_NT"* ]]; then
os="win32"
case "$arch" in
i*86) local_platform="win32-ix86";;
*) local_platform="win32-x86_64";;
esac
rt_default="tclsh902z.exe"
runtime_available=1
elif [[ "$plat" == "MSYS_NT"* ]]; then
echo MSYS
os="win32"
@ -103,8 +90,6 @@ elif [[ "$plat" == "MSYS_NT"* ]]; then
#This breaks calls to various unix utils such as sed etc (wsl related?)
export PATH="$shellfolder${PATH:+:${PATH}}"
local_platform="win32-x86_64"
rt_default="tclsh902z.exe"
runtime_available=1
else
local_platform="other"
os="other"
@ -258,8 +243,10 @@ show_help() {
echo " bin/runtime/<p>/ with sha1 verification against the server's"
echo " sha1sums.txt. -r<N>-named family artifacts also fetch their"
echo " <rootname>.toml metadata record. Omitting <name> fetches the"
echo " local platform's default runtime; a FOREIGN platform fetch"
echo " requires an explicit <name>."
echo " platform's recommended default per the server's curated"
echo " defaults.txt (a punkbin release decision; works with -platform"
echo " too) - platforms without a recorded default need an explicit"
echo " <name>."
echo " list ?-remote? ?-platform <p>?"
echo " List installed runtimes with artifact-metadata summaries"
echo " (variant, tcl patchlevel, revision, piperepl policy, source"
@ -314,18 +301,41 @@ working_name_of() {
case "$action" in
"fetch")
runtime="$rt_default"
if [[ -n "${1:-}" ]]; then
runtime="$1"
elif [[ "$is_local" -ne 1 ]]; then
#fetch-name defaults only make sense for the platform we are standing
#on - a foreign-platform fetch (cross-build staging) names its runtime
echo "No default runtime for foreign platform '$platform' - name it explicitly:"
echo " $0 fetch <runtimename> -platform $platform"
echo " (see available names: $0 list -remote -platform $platform)"
if [[ "$archtail" == "other" ]]; then
echo "Unrecognised local platform - name one explicitly with -platform"
echo "(canonical names: 'help platforms' in the punk shell)"
exit 1
fi
if [[ ( "$runtime_available" -eq 1 || -n "${1:-}" ) && "$archtail" != "other" && -n "$runtime" ]]; then
runtime="${1:-}"
if [[ -z "$runtime" ]]; then
#no name given: consult the server's curated defaults.txt - the punkbin
#release recommendation (updated there as part of each publication
#change-set; see punkbin AGENTS.md). Per-platform server data, so it
#works for any -platform, not just local.
defaultsurl="${url_kitbase}/defaults.txt"
defaultslocal="${scriptdir}/runtime/defaults.txt"
mkdir -p "${scriptdir}/runtime"
if ! curl -fsSL --output "$defaultslocal" "$defaultsurl"; then
if [[ -f "$defaultslocal" ]]; then
echo "WARNING: could not fetch $defaultsurl - using cached copy at $defaultslocal"
else
echo "Could not fetch $defaultsurl"
echo "No server default available - name a runtime explicitly:"
echo " $0 fetch <runtimename> ?-platform $archtail?"
echo " (see available names: $0 list -remote -platform $archtail)"
exit 1
fi
fi
runtime=$(awk -v p="$archtail" '$1==p {print $2; exit}' "$defaultslocal")
if [[ -z "$runtime" ]]; then
echo "No default recorded for platform '$archtail' in the server's defaults.txt - name a runtime explicitly:"
echo " $0 fetch <runtimename> ?-platform $archtail?"
echo " (see available names: $0 list -remote -platform $archtail)"
exit 1
fi
echo "using server default for $archtail: $runtime"
fi
if [[ -n "$runtime" ]]; then
url="${url_kitbase}/${archtail}/${runtime}"
output="${archdir}/${runtime}"
sha1url="${url_kitbase}/${archtail}/sha1sums.txt"
@ -409,9 +419,6 @@ case "$action" in
if [[ -z "$(get_active)" ]]; then
set_active "$runtime"
fi
else
echo "No default runtime currently published for $os ($archtail)"
echo "If one exists on the server, name it explicitly: $0 fetch <runtimename>"
fi
;;
"list")

51
src/scriptapps/bin/punk-runtime.ps1

@ -92,8 +92,10 @@ function Show-PunkRuntimeHelp {
write-host " bin/runtime/<p>/ with sha1 verification against the server's"
write-host " sha1sums.txt. -r<N>-named family artifacts also fetch their"
write-host " <rootname>.toml metadata record. Omitting <name> fetches the"
write-host " local platform's default runtime; a FOREIGN platform fetch"
write-host " requires an explicit <name>."
write-host " platform's recommended default per the server's curated"
write-host " defaults.txt (a punkbin release decision; works with -platform"
write-host " too) - platforms without a recorded default need an explicit"
write-host " <name>."
write-host " list ?-remote? ?-platform <p>?"
write-host " List installed runtimes with artifact-metadata summaries"
write-host " (variant, tcl patchlevel, revision, piperepl policy, source"
@ -368,16 +370,47 @@ function psmain {
$runtime = ""
if ( $PSBoundParameters["runtime"].Length ) {
$runtime = $PSBoundParameters["runtime"]
} elseif ($arch -eq $script:PunkLocalPlatform) {
$runtime = "tclsh902z.exe"
} else {
#fetch-name defaults only make sense for the platform we are standing
#on - a foreign-platform fetch (cross-build staging) names its runtime
write-host "No default runtime for foreign platform '$arch' - name it explicitly:"
write-host " punk-runtime.cmd fetch <runtimename> -platform $arch"
write-host " (see available names: punk-runtime.cmd list -remote -platform $arch)"
#no name given: consult the server's curated defaults.txt - the
#punkbin release recommendation (updated there as part of each
#publication change-set; see punkbin AGENTS.md). Per-platform
#server data, so it works for any -platform, not just local.
$defaultsurl = "$artifacturl/defaults.txt"
$defaultslocal = Join-Path -Path $rtfolder -ChildPath "defaults.txt"
if (-not (Test-Path -Path $rtfolder -PathType Container)) {
new-item -Path $rtfolder -ItemType Directory -force | out-null
}
try {
Invoke-WebRequest -Uri $defaultsurl -OutFile $defaultslocal -ErrorAction Stop
} catch {
if (Test-Path -Path $defaultslocal -PathType Leaf) {
Write-Host "WARNING: could not fetch ${defaultsurl}: $($_.Exception.Message)"
Write-Host "WARNING: using cached copy at $defaultslocal"
} else {
Write-Host "Could not fetch ${defaultsurl}: $($_.Exception.Message)"
Write-Host "No server default available - name a runtime explicitly:"
Write-Host " punk-runtime.cmd fetch <runtimename> ?-platform ${arch}?"
Write-Host " (see available names: punk-runtime.cmd list -remote -platform $arch)"
exit 1
}
}
foreach ($line in (Get-Content -Path $defaultslocal)) {
$line = $line.Trim()
if ($line -eq "" -or $line.StartsWith("#")) { continue }
$parts = -split $line
if ($parts.Count -ge 2 -and $parts[0] -eq $arch) {
$runtime = $parts[1]
break
}
}
if ($runtime -eq "") {
Write-Host "No default recorded for platform '$arch' in the server's defaults.txt - name a runtime explicitly:"
Write-Host " punk-runtime.cmd fetch <runtimename> ?-platform ${arch}?"
Write-Host " (see available names: punk-runtime.cmd list -remote -platform $arch)"
exit 1
}
Write-Host "using server default for ${arch}: $runtime"
}
$fileurl = "$archurl/$runtime"
$output = join-path -Path $archfolder -ChildPath $runtime

Loading…
Cancel
Save