Browse Source
New surface for the vendored first-party build tools under src/tools:
make.tcl tool list|info|build|test ?<toolname> ...? ?-test 0|1?
- discovery is convention-based (a src/tools directory carrying
build.zig is a tool), so the G-128 tool will appear with zero
make.tcl edits; per-tool records are read tolerantly from
build.zig.zon (version, minimum_zig_version floor) and PROVENANCE.md
(upstream, vendored commit)
- list/info report installed-binary state (current|stale|absent vs
bin/<name><exe-suffix>) and the resolved toolchain
- toolchain resolution: PUNK_ZIG=<path> overrides; otherwise
bin/tools/zig* is scanned and the LOWEST release satisfying the floor
wins - deterministic as newer toolchains get unpacked beside the
pinned one; dev builds count only when their base version exceeds
the floor
- build runs the tree's own 'zig build test' as an EXIT-CODE gate
(expected stderr warnings do not fail it), then builds ReleaseSafe
and installs to bin/; nothing installs when the gate or build fails;
-test 0 skips the gate; build caches are deliberately left in place
between runs for rebuild speed (git- and fossil-ignored)
- zig stays OPTIONAL: packages/bake never require the step; without a
suitable toolchain, list reports the state and build/test exit
nonzero with bin/punk-getzig.cmd guidance
- full subcommand accompaniments per src/AGENTS.md: punk::args argdoc
(SUMMARIES/HELPTEXTS/bespoke passthrough definition), SUBGROUPS
("vendored tools"), known_commands, degraded-mode dispatch, plain
help text, bootsupport-staleness exemption, workflow text (new
OUT-OF-BAND SUBSYSTEMS section also covering buildsuite), project
version 0.28.3 + CHANGELOG entry
- piped characterization (zig-independent):
src/tests/shell/testsuites/punkexe/maketcltool.test - 4/4 green
- verified live: 'tool build punkzip' gated on the vendored tree's
130/130 suite and installed bin/punkzip.exe (ReleaseSafe, v2.3.1,
1.1MB) over the stale Nov-2024 v2.1.0 binary; list state flipped
stale -> current; PUNKBOOT_PLAIN degraded dispatch and tabled help
verified
G-126 Progress updated: the acceptance's build-step clause is
satisfied. Remaining: punk::zip fast path, parity suite, benchmark.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
5 changed files with 603 additions and 10 deletions
@ -1,4 +1,4 @@
|
||||
[project] |
||||
name = "punkshell" |
||||
version = "0.28.2" |
||||
version = "0.28.3" |
||||
license = "BSD-2-Clause" |
||||
|
||||
@ -0,0 +1,154 @@
|
||||
package require tcltest |
||||
|
||||
#Piped characterization of the make.tcl tool subcommand (goal G-126): the surface |
||||
#for the vendored first-party zig build tools under src/tools. Runs the WORKING |
||||
#TREE's src/make.tcl under the built punk executable's 'script' subcommand with |
||||
#output captured through a pipe, and pins: |
||||
# - 'tool' (bare = list) exits 0, output is ESC-free (G-113 piped policy), the |
||||
# stable header row is present, the punkzip row carries the declared zig floor |
||||
# (>=0.16.0), an installed-binary state from the documented vocabulary and a |
||||
# 12-hex vendored-commit column, and the toolchain line reports either a |
||||
# resolved zig or the documented no-suitable-toolchain guidance (the test must |
||||
# pass on machines without a 0.16 toolchain) |
||||
# - 'tool info punkzip' exits 0 and reports the PROVENANCE.md-sourced records |
||||
# (upstream, full 40-hex vendored commit) and the provenance file path |
||||
# - 'tool <unknown-action>' exits 2 naming the action and the expected set |
||||
# - 'tool info <unknown-name>' exits 2 naming the tool and the configured names |
||||
#The build/test actions are deliberately NOT exercised here (they need a zig |
||||
#toolchain and minutes of compile time); the tree's own 'zig build test' is the |
||||
#gate for those, driven by 'make.tcl tool build/test'. |
||||
#The punkzip row pins are characterization of the current vendored tree - a |
||||
#re-vendor with a raised floor legitimately updates them. |
||||
# |
||||
#Target executable resolved from env(PUNK_SHELL_TEST_EXE), else <projectroot>/bin/punk902z.exe |
||||
#then <projectroot>/bin/punkshell902. Skipped (constraint punkexeavailable) if none found. |
||||
|
||||
namespace eval ::testspace { |
||||
namespace import ::tcltest::* |
||||
|
||||
variable testdir [file dirname [file normalize [info script]]] |
||||
#<projectroot>/src/tests/shell/testsuites/punkexe -> 5 levels up to <projectroot> |
||||
variable projectroot [file normalize [file join $testdir .. .. .. .. ..]] |
||||
variable maketcl [file join $projectroot src make.tcl] |
||||
|
||||
variable punkexe "" |
||||
if {[info exists ::env(PUNK_SHELL_TEST_EXE)] && $::env(PUNK_SHELL_TEST_EXE) ne ""} { |
||||
set punkexe [file normalize $::env(PUNK_SHELL_TEST_EXE)] |
||||
} else { |
||||
foreach candidate [list [file join $projectroot bin punk902z.exe] [file join $projectroot bin punkshell902]] { |
||||
if {[file exists $candidate]} { |
||||
set punkexe $candidate |
||||
break |
||||
} |
||||
} |
||||
} |
||||
testConstraint punkexeavailable [expr {$punkexe ne "" && [file exists $punkexe]}] |
||||
|
||||
variable maketcl_run_timeout_ms 60000 |
||||
|
||||
variable runstate |
||||
array set runstate {} |
||||
|
||||
proc maketcl_run_read {chan} { |
||||
variable runstate |
||||
append runstate(output) [read $chan] |
||||
if {[chan eof $chan]} { |
||||
chan event $chan readable {} |
||||
set runstate(done) eof |
||||
} |
||||
} |
||||
|
||||
#Run <punkexe> script src/make.tcl <subcommand...> with output captured through a |
||||
#pipe (stdin half-closed for immediate EOF - make.tcl must never wait on stdin for |
||||
#these subcommands). Returns dict: timedout 0|1, exitcode <int|"">, output |
||||
#<combined stdout+stderr>. |
||||
proc maketcl_run {cmdargs} { |
||||
variable runstate |
||||
variable maketcl_run_timeout_ms |
||||
variable punkexe |
||||
variable maketcl |
||||
array unset runstate |
||||
set runstate(output) "" |
||||
set runstate(done) "" |
||||
|
||||
set chan [open |[list $punkexe script $maketcl {*}$cmdargs 2>@1] r+] |
||||
chan configure $chan -blocking 0 -translation binary |
||||
catch {chan close $chan write} ;#no stdin for the child - immediate EOF |
||||
set timerid [after $maketcl_run_timeout_ms [list set [namespace current]::runstate(done) timeout]] |
||||
chan event $chan readable [list [namespace current]::maketcl_run_read $chan] |
||||
while {$runstate(done) eq ""} { |
||||
vwait [namespace current]::runstate(done) |
||||
} |
||||
after cancel $timerid |
||||
set timedout [expr {$runstate(done) eq "timeout"}] |
||||
set exitcode "" |
||||
if {$timedout} { |
||||
catch {exec {*}[auto_execok taskkill] /F /T /PID [lindex [pid $chan] 0]} |
||||
catch {chan close $chan} |
||||
} else { |
||||
chan configure $chan -blocking 1 |
||||
if {[catch {chan close $chan} errdata errdict]} { |
||||
set exitcode [lindex [dict get $errdict -errorcode] end] |
||||
} else { |
||||
set exitcode 0 |
||||
} |
||||
} |
||||
return [dict create timedout $timedout exitcode $exitcode output $runstate(output)] |
||||
} |
||||
|
||||
proc esc_count {text} { |
||||
return [regexp -all {\x1b} $text] |
||||
} |
||||
|
||||
#added 2026-07-27 (agent, G-126) |
||||
test maketcl_tool_list {piped make.tcl tool (bare = list): exit 0, ESC-free, header + punkzip row + toolchain line} -constraints {punkexeavailable} -body { |
||||
set r [maketcl_run {tool}] |
||||
set out [dict get $r output] |
||||
set result [list] |
||||
lappend result timedout [dict get $r timedout] exitcode [dict get $r exitcode] |
||||
lappend result esc [esc_count $out] |
||||
lappend result header [regexp {(?n)^ name\s+version\s+zig-floor\s+bin\s+vendored-commit\s*$} $out] |
||||
lappend result punkziprow [regexp {(?n)^ punkzip\s+\S+\s+>=0\.16\.0\s+(current|stale|absent)\s+[0-9a-f]{12}\s*$} $out] |
||||
lappend result toolchain [regexp {(?n)^toolchain: (zig \S+ via |no suitable zig toolchain)} $out] |
||||
lappend result optionalnote [regexp {zig is OPTIONAL for punkshell builds} $out] |
||||
set result |
||||
} -result {timedout 0 exitcode 0 esc 0 header 1 punkziprow 1 toolchain 1 optionalnote 1} |
||||
|
||||
#added 2026-07-27 (agent, G-126) |
||||
test maketcl_tool_info_punkzip {tool info punkzip reports the PROVENANCE.md records and paths} -constraints {punkexeavailable} -body { |
||||
set r [maketcl_run {tool info punkzip}] |
||||
set out [dict get $r output] |
||||
set result [list] |
||||
lappend result timedout [dict get $r timedout] exitcode [dict get $r exitcode] |
||||
lappend result toolline [regexp {(?n)^tool: punkzip\s*$} $out] |
||||
lappend result upstream [regexp {(?n)^ upstream:\s+\S+} $out] |
||||
lappend result commit [regexp {(?n)^ vendored commit: [0-9a-f]{40}\s*$} $out] |
||||
lappend result provfile [regexp {(?n)^ provenance:\s+\S+PROVENANCE\.md\s*$} $out] |
||||
lappend result floor [regexp {(?n)^ zig floor:\s+>= 0\.16\.0\s*$} $out] |
||||
set result |
||||
} -result {timedout 0 exitcode 0 toolline 1 upstream 1 commit 1 provfile 1 floor 1} |
||||
|
||||
#added 2026-07-27 (agent, G-126) |
||||
test maketcl_tool_unknown_action {tool with an unknown action exits 2 naming it and the expected actions} -constraints {punkexeavailable} -body { |
||||
set r [maketcl_run {tool frobnicate}] |
||||
set out [dict get $r output] |
||||
set result [list] |
||||
lappend result timedout [dict get $r timedout] exitcode [dict get $r exitcode] |
||||
lappend result named [regexp {unknown tool action 'frobnicate' - expected list\|info\|build\|test} $out] |
||||
set result |
||||
} -result {timedout 0 exitcode 2 named 1} |
||||
|
||||
#added 2026-07-27 (agent, G-126) |
||||
test maketcl_tool_unknown_name {tool info with an unknown tool name exits 2 listing the configured tools} -constraints {punkexeavailable} -body { |
||||
set r [maketcl_run {tool info nosuchtoolxyz}] |
||||
set out [dict get $r output] |
||||
set result [list] |
||||
lappend result timedout [dict get $r timedout] exitcode [dict get $r exitcode] |
||||
lappend result named [regexp {tool 'nosuchtoolxyz' not found under } $out] |
||||
lappend result confignames [regexp {configured tools: .*punkzip} $out] |
||||
set result |
||||
} -result {timedout 0 exitcode 2 named 1 confignames 1} |
||||
|
||||
cleanupTests |
||||
} |
||||
namespace delete ::testspace |
||||
Loading…
Reference in new issue