Browse Source

runtime.cmd: list -remote for the unix payload + PUNKBIN_URL override (punkshell 0.8.0)

- bash/zsh payload gains list -remote parity with the powershell payload: local-vs-server sha1 comparison table (Same version / UPDATE AVAILABLE / not listed on server, plus remote-only entries), falling back to a cached sha1sums.txt with a warning when the server is unreachable (the powershell version has no cached fallback - candidate backport)
- both payloads: artifact server base url overridable via PUNKBIN_URL (mirrors/testing - also what makes the new feature testable offline)
- first real catch for the 512-byte label guard: the payload growth pushed the template's :exit_multishell target label across a boundary from its callsite (checkfile ERROR at wrap time); fixed with a documented byte-alignment spacer comment at the end of runtime.bash, and the resize-the-spacer workflow recorded in bin/AGENTS.md
- bin/runtime.cmd regenerated via scriptwrap (roundtrip pin green; multishell suite 9 pass + 1 skip on 9.0.3 and 8.7); runtime.bash syntax-checked under bash and zsh; windows list/use/run sanity re-verified

Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
Julian Noble 4 days ago
parent
commit
e6be532938
  1. 6
      CHANGELOG.md
  2. 10
      bin/AGENTS.md
  3. 59
      bin/runtime.cmd
  4. 2
      punkproject.toml
  5. 55
      src/scriptapps/bin/runtime.bash
  6. 4
      src/scriptapps/bin/runtime.ps1

6
CHANGELOG.md

@ -5,6 +5,12 @@ 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.8.0] - 2026-07-11
- `runtime.cmd list -remote` parity for the unix (bash/zsh) payload: local-vs-server comparison table (Same version / UPDATE AVAILABLE / not-listed, plus remote-only entries), falling back to a cached `sha1sums.txt` with a warning when the server is unreachable. Both payloads gain a `PUNKBIN_URL` env override of the artifact server base url (mirrors/testing).
- The polyglot's 512-byte label guard caught its first real regression during this change: the payload growth pushed the template's `:exit_multishell` label across a boundary; fixed with a documented byte-alignment spacer comment in `runtime.bash` (workflow recorded in bin/AGENTS.md).
- G-059 achieved: WSL capability probing + native-filesystem staging for driving unix-side tests from Windows (`src/tests/testsupport/wslprobe.tcl`, `wsllinux` constraint). The MULTISHELL sh payload and the runtime.cmd unix payload (`runtime.bash` — never previously executed on real unix) now run green under WSL: active/use/run resolution, env override, stale-active guidance, single-candidate fallback and offline `list -remote` — all staged to the distro's native filesystem, with a guard test asserting the Windows checkout's git state is untouched.
## [0.7.0] - 2026-07-11
- `bin/runtime.cmd` gains a `use` subcommand and an active-runtime selection: which runtime `run` launches is now the per-machine `bin/runtime/<platform>/active.toml` (`active = "<name>"`, shown with a `*` in `list`), resolved as `PUNK_ACTIVE_RUNTIME` env override → `active.toml` → sole installed candidate — with multiple runtimes and no selection, `run` errors listing candidates instead of silently launching the last name alphabetically. The first `fetch` sets the active runtime only when none is recorded; later fetches never steal it.

10
bin/AGENTS.md

@ -22,7 +22,11 @@ When asked to "fix bin/<name>.cmd":
(output defaults to `<projectroot>/bin`; requires Thread + the punk::mix modules, e.g
a punk shell or a tclsh with project module paths).
3. The wrapper runs `checkfile` (the 512-byte label/boundary validator) automatically -
heed ERROR output; "possibly bogus target" warnings are normal for polyglots.
heed ERROR output; "possibly bogus target" warnings are normal for polyglots. Payload
growth can push a TEMPLATE label beyond the payloads (e.g `:exit_multishell`) across a
512-byte boundary: fix by resizing the byte-alignment spacer comment at the end of the
affected payload (see the `(512B spacer)` comment in `runtime.bash`) and re-wrapping
until checkfile is ERROR-free.
4. Commit source AND regenerated output together: the scriptwrap test suite pins that a
re-wrap of the runtime scriptset reproduces `bin/runtime.cmd` byte for byte
(`src/tests/modules/punk/mix/testsuites/scriptwrap/multishell.test`
@ -46,6 +50,10 @@ The first argument to a built punk shell may be a dash-delimited package mode co
`bin/runtime/<platform>/` (retrieved from the punkbin artifact repo with sha1
verification against its `sha1sums.txt` - both the powershell payload on windows and the
bash payload on unix verify; a fetch whose checksum fails leaves only a `.tmp`).
`list -remote` compares local runtimes against the server's sha1sums (Same version /
UPDATE AVAILABLE / not-listed, plus remote-only entries; the bash payload falls back to
a cached sha1sums.txt with a warning when the server is unreachable). The artifact
server base url is overridable via `PUNKBIN_URL` (mirrors/testing) in both payloads.
Which runtime `run` launches is the per-machine "active" selection in
`bin/runtime/<platform>/active.toml` (constrained single-key toml `active = "<name>"`,
written by `runtime.cmd use <name>`, marked in `list`, VCS-ignored via the existing

59
bin/runtime.cmd

@ -1290,7 +1290,8 @@ scriptpath=$(realpath $scriptpath)
basename=$(basename "$scriptpath") #e.g fetchruntime.bash
scriptroot="${basename%.*}" #e.g "fetchruntime"
url_kitbase="https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master"
#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
@ -1489,6 +1490,53 @@ case "$1" in
fi
;;
"list")
if [[ "$2" == "-remote" ]]; then
#compare local runtimes with those listed on the artifact server
#(functional parity with the powershell payload's 'list -remote')
sha1url="${url_kitbase}/${archtail}/sha1sums.txt"
sha1local="${archdir}/sha1sums.txt"
mkdir -p "$archdir"
if curl -fsSL --output "$sha1local" "$sha1url"; then
echo "Fetched $sha1url"
elif [[ -f "$sha1local" ]]; then
echo "WARNING: could not fetch $sha1url - using cached copy at $sha1local"
else
echo "Unable to fetch $sha1url and no cached copy available"
exit 1
fi
probe=$(sha1_of "$sha1local")
if [[ -z "$probe" ]]; then
echo "No sha1 tool found (tried sha1sum, shasum, sha1, openssl) - cannot compare local runtimes."
exit 1
fi
echo "-----------------------------------------------------------------------"
echo "Runtimes for $archtail"
echo "Local $archdir"
echo "Remote ${url_kitbase}/${archtail}"
echo "-----------------------------------------------------------------------"
echo "Local Remote"
echo "-----------------------------------------------------------------------"
for f in $(list_candidates); do
local_sha1=$(lcase "$(sha1_of "$archdir/$f")")
stored_sha1=$(grep -E "^[0-9a-fA-F]{40} \*${f}\$" "$sha1local" | head -n 1 | cut -d' ' -f1)
if [[ -z "$stored_sha1" ]]; then
rhs="(not listed on server)"
elif [[ "$local_sha1" == "$(lcase "$stored_sha1")" ]]; then
rhs="Same version"
else
rhs="UPDATE AVAILABLE"
fi
printf '%-35s %s\n' "$f" "$rhs"
done
#remote-only entries
while IFS= read -r line; do
rname=$(printf '%s' "$line" | sed -n 's/^[0-9a-fA-F]\{40\} \*\(.*\)$/\1/p')
if [[ -n "$rname" && ! -f "$archdir/$rname" ]]; then
printf '%-35s %s\n' "-" "$rname"
fi
done < "$sha1local"
echo "-----------------------------------------------------------------------"
else
if [[ -d "$archdir" ]]; then
candidates=$(list_candidates)
active=$(get_active)
@ -1504,10 +1552,12 @@ case "$1" in
if [[ -n "$active" && ! -f "$archdir/$active" ]]; then
echo "WARNING: active runtime '$active' (from $active_file) is not present - use '$0 use <name>' to reselect"
fi
echo "Use: '$0 list -remote' to compare local runtimes with those available on the artifact server"
else
echo "No runtimes available in $archdir"
echo " Use '$0 fetch' to install."
fi
fi
;;
"use")
if [[ -z "$2" ]]; then
@ -1587,6 +1637,9 @@ case "$1" in
exit 1
;;
esac
#(512B spacer) byte-alignment padding so template labels beyond the payloads clear cmd's
#512-byte label-scan boundaries - resize this comment if scriptwrap checkfile reports a
#boundary-spanning label after a payload edit (see bin/AGENTS.md polyglot workflow)
#</shell-payload>
@ -2059,7 +2112,11 @@ function psmain {
#expected script location is the bin folder of a punk project
$rtfolder = Join-Path -Path $outbase -ChildPath "runtime"
#Binary artifact server url. (git is not ideal for this - but will do for now - todo - use artifact system within gitea?)
#overridable for mirrors/testing - keep in sync with the bash payload
$artifacturl = "https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master"
if ($env:PUNKBIN_URL) {
$artifacturl = $env:PUNKBIN_URL
}
switch ($action) {
'fetch' {
$arch = "win32-x86_64"

2
punkproject.toml

@ -1,3 +1,3 @@
[project]
name = "punkshell"
version = "0.7.0"
version = "0.8.0"

55
src/scriptapps/bin/runtime.bash

@ -10,7 +10,8 @@ scriptpath=$(realpath $scriptpath)
basename=$(basename "$scriptpath") #e.g fetchruntime.bash
scriptroot="${basename%.*}" #e.g "fetchruntime"
url_kitbase="https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master"
#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
@ -209,6 +210,53 @@ case "$1" in
fi
;;
"list")
if [[ "$2" == "-remote" ]]; then
#compare local runtimes with those listed on the artifact server
#(functional parity with the powershell payload's 'list -remote')
sha1url="${url_kitbase}/${archtail}/sha1sums.txt"
sha1local="${archdir}/sha1sums.txt"
mkdir -p "$archdir"
if curl -fsSL --output "$sha1local" "$sha1url"; then
echo "Fetched $sha1url"
elif [[ -f "$sha1local" ]]; then
echo "WARNING: could not fetch $sha1url - using cached copy at $sha1local"
else
echo "Unable to fetch $sha1url and no cached copy available"
exit 1
fi
probe=$(sha1_of "$sha1local")
if [[ -z "$probe" ]]; then
echo "No sha1 tool found (tried sha1sum, shasum, sha1, openssl) - cannot compare local runtimes."
exit 1
fi
echo "-----------------------------------------------------------------------"
echo "Runtimes for $archtail"
echo "Local $archdir"
echo "Remote ${url_kitbase}/${archtail}"
echo "-----------------------------------------------------------------------"
echo "Local Remote"
echo "-----------------------------------------------------------------------"
for f in $(list_candidates); do
local_sha1=$(lcase "$(sha1_of "$archdir/$f")")
stored_sha1=$(grep -E "^[0-9a-fA-F]{40} \*${f}\$" "$sha1local" | head -n 1 | cut -d' ' -f1)
if [[ -z "$stored_sha1" ]]; then
rhs="(not listed on server)"
elif [[ "$local_sha1" == "$(lcase "$stored_sha1")" ]]; then
rhs="Same version"
else
rhs="UPDATE AVAILABLE"
fi
printf '%-35s %s\n' "$f" "$rhs"
done
#remote-only entries
while IFS= read -r line; do
rname=$(printf '%s' "$line" | sed -n 's/^[0-9a-fA-F]\{40\} \*\(.*\)$/\1/p')
if [[ -n "$rname" && ! -f "$archdir/$rname" ]]; then
printf '%-35s %s\n' "-" "$rname"
fi
done < "$sha1local"
echo "-----------------------------------------------------------------------"
else
if [[ -d "$archdir" ]]; then
candidates=$(list_candidates)
active=$(get_active)
@ -224,10 +272,12 @@ case "$1" in
if [[ -n "$active" && ! -f "$archdir/$active" ]]; then
echo "WARNING: active runtime '$active' (from $active_file) is not present - use '$0 use <name>' to reselect"
fi
echo "Use: '$0 list -remote' to compare local runtimes with those available on the artifact server"
else
echo "No runtimes available in $archdir"
echo " Use '$0 fetch' to install."
fi
fi
;;
"use")
if [[ -z "$2" ]]; then
@ -307,3 +357,6 @@ case "$1" in
exit 1
;;
esac
#(512B spacer) byte-alignment padding so template labels beyond the payloads clear cmd's
#512-byte label-scan boundaries - resize this comment if scriptwrap checkfile reports a
#boundary-spanning label after a payload edit (see bin/AGENTS.md polyglot workflow)

4
src/scriptapps/bin/runtime.ps1

@ -176,7 +176,11 @@ function psmain {
#expected script location is the bin folder of a punk project
$rtfolder = Join-Path -Path $outbase -ChildPath "runtime"
#Binary artifact server url. (git is not ideal for this - but will do for now - todo - use artifact system within gitea?)
#overridable for mirrors/testing - keep in sync with the bash payload
$artifacturl = "https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master"
if ($env:PUNKBIN_URL) {
$artifacturl = $env:PUNKBIN_URL
}
switch ($action) {
'fetch' {
$arch = "win32-x86_64"

Loading…
Cancel
Save