Browse Source
One parsed-mapping model (::punkboot::lib::mapvfs_parse / mapvfs_kit_outputs / mapvfs_match_outputs) now backs the kit surfaces - the bake machinery, the new bakelist report and the bake/bakelist argdoc kit-name choices all consume the model, never the file format, so the G-024 toml conversion can swap the reader underneath. - bakelist ?kitname ...? (informational SUBGROUP): kit name, type, runtime with presence, vfs folder, deployed state of bin/<kit> vs src/_build/<kit> (current|stale|absent|nobuild; size/mtime fast path, byte-compare when in doubt), anomalies as trailing key=value notes (runtime=missing, vfs=missing, rtrev=r<cur><r<max> via the shared runtime_materialization_check core). Name filtering doubles as per-kit detail (resolved paths/sizes/mtimes). - bake ?kitname ...?: selective kit assembly - unknown names error before any build listing the configured names (flag-order hint included); selected-but- unbuildable kits (missing runtime/vfs) fail fast; runtime BUILDCOPY/caps probe/vfs cksums/vfslibs phase all narrow to the selected kits so other kits' _build/bin artifacts and punkcheck records stay untouched. Bare bake unchanged (verified full-set run). Deprecated alias vfs mirrors the values. - argdocs: SUBVALUES/VALUES_SYNOPSES mechanism, kitname choices enumerated from the mapping at define time (-choicerestricted 0, degrade-safe), block-form help values; SUMMARIES/HELPTEXTS/SUBOPTS/SUBGROUPS/known_commands/plain gethelp/workflow text updated per the update contract; degraded-mode (PUNKBOOT_PLAIN) dispatch collects trailing kit names. - mapvfs.config todo comment retired to point at G-121. - piped characterization: src/tests/shell/testsuites/punkexe/maketclbakelist.test (full-report row/vocabulary + ESC-free, filtered detail, unknown-name errors on both surfaces with the no-build guarantee) - 4 PASS; maketclcolour.test still 3 PASS. - selective-refresh verification (recorded in the goal file): forced punk91 rebuild + deploy via 'bake -confirm 0 punk91'; stat diffs over src/_build and bin show only punk91.exe, punk91.exe.vfs, raw_tclsfe-x64.exe and bin/punk91.exe changed; .punkcheck diffs mention only punk91's records (negative grep for all other kit/vfs names clean). - docs: src/AGENTS.md work-guidance bullet; ARCHITECTURE.md build-entry subcommand list refreshed (bake/bakehouse naming + bakelist, stale in-flux G-112 mention dropped); CHANGELOG 0.24.0 + punkproject.toml minor bump. Claude-Session: https://claude.ai/code/session_01Jz7wkUsknJzyuJ3tgMaL2t Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.commaster
7 changed files with 905 additions and 112 deletions
@ -1,4 +1,4 @@ |
|||||||
[project] |
[project] |
||||||
name = "punkshell" |
name = "punkshell" |
||||||
version = "0.23.3" |
version = "0.24.0" |
||||||
license = "BSD-2-Clause" |
license = "BSD-2-Clause" |
||||||
|
|||||||
@ -0,0 +1,150 @@ |
|||||||
|
package require tcltest |
||||||
|
|
||||||
|
#Piped characterization of the make.tcl bakelist report and the bake-side selective |
||||||
|
#kit-name validation (goal G-121). Runs the WORKING TREE's src/make.tcl under the |
||||||
|
#built punk executable's 'script' subcommand with output captured through a pipe, |
||||||
|
#and pins: |
||||||
|
# - 'bakelist' exits 0, output is ESC-free (G-113 piped policy), the stable header |
||||||
|
# row is present and the punk91 row carries the expected type/runtime/vfs columns |
||||||
|
# with a deployed state from the documented vocabulary |
||||||
|
# - 'bakelist <kitname>' filters to the named entry and appends the per-kit detail |
||||||
|
# block; unfiltered rows do not appear |
||||||
|
# - 'bakelist <unknown>' exits 1 naming the unknown and listing the configured names |
||||||
|
# - 'bake <unknown>' exits 1 BEFORE any build ("nothing built"), listing the |
||||||
|
# configured names - the no-build guarantee of selective bake |
||||||
|
#The row pins are characterization of the current src/runtime/mapvfs.config kit |
||||||
|
#matrix (punk91 = tclsfe-x64 + punk9wintk903.vfs, zip) - a deliberate config change |
||||||
|
#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-26 (agent, G-121) |
||||||
|
test maketcl_bakelist_full_report {piped make.tcl bakelist: exit 0, ESC-free, header row + punk91 row with documented deployed vocabulary} -constraints {punkexeavailable} -body { |
||||||
|
set r [maketcl_run {bakelist}] |
||||||
|
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)^kit\s+type\s+runtime\s+vfs\s+deployed\s*$} $out] |
||||||
|
lappend result punk91row [regexp {(?n)^punk91\s+zip\s+tclsfe-x64\s+punk9wintk903\.vfs\s+(current|stale|absent|nobuild)\y} $out] |
||||||
|
set result |
||||||
|
} -result {timedout 0 exitcode 0 esc 0 header 1 punk91row 1} |
||||||
|
|
||||||
|
#added 2026-07-26 (agent, G-121) |
||||||
|
test maketcl_bakelist_filtered_detail {bakelist punk91 filters to the named entry and appends the per-kit detail block} -constraints {punkexeavailable} -body { |
||||||
|
set r [maketcl_run {bakelist punk91}] |
||||||
|
set out [dict get $r output] |
||||||
|
set result [list] |
||||||
|
lappend result timedout [dict get $r timedout] exitcode [dict get $r exitcode] |
||||||
|
lappend result punk91row [regexp {(?n)^punk91\s+zip\s+} $out] |
||||||
|
lappend result otherrows [regexp {(?n)^(punk905|punkbi|punksys|punk86)\s} $out] |
||||||
|
lappend result detailblock [regexp {(?n)^detail: punk91\s*$} $out] |
||||||
|
lappend result detailpaths [regexp {(?n)^\s+build product: src/_build/punk91} $out] |
||||||
|
set result |
||||||
|
} -result {timedout 0 exitcode 0 punk91row 1 otherrows 0 detailblock 1 detailpaths 1} |
||||||
|
|
||||||
|
#added 2026-07-26 (agent, G-121) |
||||||
|
test maketcl_bakelist_unknown_name {bakelist with an unknown kit name exits 1 naming it and listing the configured names} -constraints {punkexeavailable} -body { |
||||||
|
set r [maketcl_run {bakelist nosuchkitxyz}] |
||||||
|
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 {bakelist: unknown kit name\(s\): nosuchkitxyz} $out] |
||||||
|
lappend result confignames [regexp {configured kit outputs: .*punk91} $out] |
||||||
|
set result |
||||||
|
} -result {timedout 0 exitcode 1 named 1 confignames 1} |
||||||
|
|
||||||
|
#added 2026-07-26 (agent, G-121) |
||||||
|
test maketcl_bake_unknown_name_no_build {bake with an unknown kit name exits 1 before any build, listing the configured names} -constraints {punkexeavailable} -body { |
||||||
|
set r [maketcl_run {bake nosuchkitxyz}] |
||||||
|
set out [dict get $r output] |
||||||
|
set result [list] |
||||||
|
lappend result timedout [dict get $r timedout] exitcode [dict get $r exitcode] |
||||||
|
lappend result nothingbuilt [regexp {make\.tcl bake: unknown kit name\(s\): nosuchkitxyz - nothing built} $out] |
||||||
|
lappend result confignames [regexp {configured kit outputs: .*punk91} $out] |
||||||
|
#the run must never reach the kit machinery (no vfs scan / kit processing output) |
||||||
|
lappend result nomachinery [expr {![regexp {processing targetkit:} $out]}] |
||||||
|
set result |
||||||
|
} -result {timedout 0 exitcode 1 nothingbuilt 1 confignames 1 nomachinery 1} |
||||||
|
|
||||||
|
cleanupTests |
||||||
|
} |
||||||
|
namespace delete ::testspace |
||||||
Loading…
Reference in new issue