From e6be5329383827c848cfe727213ce67474414b84 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Sat, 11 Jul 2026 01:01:30 +1000 Subject: [PATCH] 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 --- CHANGELOG.md | 6 ++++ bin/AGENTS.md | 10 +++++- bin/runtime.cmd | 59 ++++++++++++++++++++++++++++++++- punkproject.toml | 2 +- src/scriptapps/bin/runtime.bash | 55 +++++++++++++++++++++++++++++- src/scriptapps/bin/runtime.ps1 | 4 +++ 6 files changed, 132 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e3e0622..3336dc67 100644 --- a/CHANGELOG.md +++ b/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//active.toml` (`active = ""`, 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. diff --git a/bin/AGENTS.md b/bin/AGENTS.md index 1656658f..3914359e 100644 --- a/bin/AGENTS.md +++ b/bin/AGENTS.md @@ -22,7 +22,11 @@ When asked to "fix bin/.cmd": (output defaults to `/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//` (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//active.toml` (constrained single-key toml `active = ""`, written by `runtime.cmd use `, marked in `list`, VCS-ignored via the existing diff --git a/bin/runtime.cmd b/bin/runtime.cmd index 486277d2..25232842 100755 --- a/bin/runtime.cmd +++ b/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 ' 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) # @@ -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" diff --git a/punkproject.toml b/punkproject.toml index 59c2d9fc..89c8a0ec 100644 --- a/punkproject.toml +++ b/punkproject.toml @@ -1,3 +1,3 @@ [project] name = "punkshell" -version = "0.7.0" +version = "0.8.0" diff --git a/src/scriptapps/bin/runtime.bash b/src/scriptapps/bin/runtime.bash index b59e3601..5c3b2f6a 100644 --- a/src/scriptapps/bin/runtime.bash +++ b/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 ' 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) diff --git a/src/scriptapps/bin/runtime.ps1 b/src/scriptapps/bin/runtime.ps1 index 9a5a2221..bd0ae85f 100644 --- a/src/scriptapps/bin/runtime.ps1 +++ b/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"