Browse Source

G-128: seam names the kit group icon PUNKSHELL (icon-derived, both arms); punkshell 0.30.2

RT_GROUP_ICON name policy (user decision 2026-07-29): kit_icon_process derives
icon_group from the icon FILE's uppercased rootname (RC convention) -
punkshell.ico -> PUNKSHELL for the default icon and per-kit overrides alike -
and passes it to whichever mechanism embeds. punkres arm uses set-icon -group
(punkres 0.2.0); kit_icon_embed_twapi gains the matching optional
group_override (name only - language adoption unchanged) so the arms stay in
parity. Replaces the retained stub-lineage names (punk91 "SFE", suite kits
"TCLSH"); already-deployed kits keep theirs until their next natural rebuild
(the policy is not in the punkcheck source set).

Sidecar gains icon_group (recorded whenever the icon file exists);
bin/AGENTS.md format doc + ARCHITECTURE.md updated, architecture_lint clean.

Live-verified on punkluck86 rebakes: punkres arm and twapi arm (TCLLIBPATH
route) both emit RT_GROUP_ICON "PUNKSHELL" lang 1033, extracted icons
byte-identical between arms; sidecar icon_group=PUNKSHELL; final deployed
state punkres-stamped and booting. Full punkexe suite 83 tests 0 failed.

Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
Julian Noble 2 days ago
parent
commit
bd65183061
  1. 2
      ARCHITECTURE.md
  2. 11
      CHANGELOG.md
  3. 12
      bin/AGENTS.md
  4. 35
      goals/G-128-portable-pe-resource-stamping.md
  5. 2
      punkproject.toml
  6. 57
      src/make.tcl

2
ARCHITECTURE.md

@ -87,7 +87,7 @@ Two layers with a deliberate dependency direction (the class never depends on th
- **Provenance gates.** Build/promotion commands warn on uncommitted `src/` changes (column-0 `PROVENANCE-WARNING:` token, `-dirty-abort` for strict mode); `vendorupdate` warns for dirty source-project checkouts. - **Provenance gates.** Build/promotion commands warn on uncommitted `src/` changes (column-0 `PROVENANCE-WARNING:` token, `-dirty-abort` for strict mode); `vendorupdate` warns for dirty source-project checkouts.
- **Boot-precondition gate (G-125).** A bake refuses a kit whose merged `.vfs` supplies no tcl library rather than deploying an artifact that cannot initialise: the kit lands in `FAILED KITS` and nothing is written, so the previously deployed `bin/<kit>` survives. Structural and non-executing (so cross-target kits are covered), reading the merged tree rather than the extraction outcome. The predicate is `punkboot::utils::vfs_boot_library_report`, called through the same guarded require as the provenance check so a stale bootsupport snapshot degrades it to a notice; `make.tcl check` reports ACTIVE/UNAVAILABLE. Sources: `src/AGENTS.md`, `src/modules/punkboot/utils-999999.0a1.0.tm`. - **Boot-precondition gate (G-125).** A bake refuses a kit whose merged `.vfs` supplies no tcl library rather than deploying an artifact that cannot initialise: the kit lands in `FAILED KITS` and nothing is written, so the previously deployed `bin/<kit>` survives. Structural and non-executing (so cross-target kits are covered), reading the merged tree rather than the extraction outcome. The predicate is `punkboot::utils::vfs_boot_library_report`, called through the same guarded require as the provenance check so a stale bootsupport snapshot degrades it to a notice; `make.tcl check` reports ACTIVE/UNAVAILABLE. Sources: `src/AGENTS.md`, `src/modules/punkboot/utils-999999.0a1.0.tm`.
- **Payload/target consistency checks (G-133), both advisory.** At the same post-merge seam, a bake classifies each binary library in the merged tree by header (`punkboot::utils::binary_arch_classify` - PE/ELF/Mach-O, honest unknowns) against the kit's target platform; wrong-arch libraries outside platform-discriminated subdirs (canonical `<os>-<cpu>` names, vendor spellings like `win-x64`) earn recapped `BUILD-WARNING`s. After assembly, a kit declaring smoke-require packages (`mapvfs.config` 5th entry element) has each one plain-`package require`d inside the freshly built artifact via its tclsh subcommand - the only check that sees resolution-order defects (wrong-arch version shadowing); cross-target kits skip with a stated reason. Same guarded-require degradation; `make.tcl check` reports both. Neither guarantees statics, pure-tcl packages with binary deps, or version preference beyond the declared smoke set. Sources: `src/AGENTS.md`, `src/runtime/AGENTS.md`, `src/modules/punkboot/utils-999999.0a1.0.tm`. - **Payload/target consistency checks (G-133), both advisory.** At the same post-merge seam, a bake classifies each binary library in the merged tree by header (`punkboot::utils::binary_arch_classify` - PE/ELF/Mach-O, honest unknowns) against the kit's target platform; wrong-arch libraries outside platform-discriminated subdirs (canonical `<os>-<cpu>` names, vendor spellings like `win-x64`) earn recapped `BUILD-WARNING`s. After assembly, a kit declaring smoke-require packages (`mapvfs.config` 5th entry element) has each one plain-`package require`d inside the freshly built artifact via its tclsh subcommand - the only check that sees resolution-order defects (wrong-arch version shadowing); cross-target kits skip with a stated reason. Same guarded-require degradation; `make.tcl check` reports both. Neither guarantees statics, pure-tcl packages with binary deps, or version preference beyond the declared smoke set. Sources: `src/AGENTS.md`, `src/runtime/AGENTS.md`, `src/modules/punkboot/utils-999999.0a1.0.tm`.
- **Kit icon step (G-057 + G-128).** Every kit a bake builds gets a `<kitname>.resources.toml` sidecar (deployed beside `bin/<kit>`) recording the build-time icon choice - default `src/runtime/punkshell.ico`, overridable by a root `punkshell.ico` in the kit's own custom `.vfs` folder (pre-merge) - with sha256 identity and provenance lifted from the icon's G-135 assetorigin record. win32-target kits get the icon embedded as PE `RT_ICON`/`RT_GROUP_ICON` behind a single seam (`::punkboot::kit_icon_process`): the vendored punkres portable stamper (`src/tools/punkres`, built to `bin/punkres(.exe)` by the make.tcl tool step) is selected when present and works from any build host; otherwise the twapi arm (tcl-sfe mechanism) serves windows hosts with nothing built. Both arms share one semantic (delete all icon/group entries, write ids 1..N under the first pre-existing group's name+lang) and stamp a per-kit copy of the payload-free raw runtime prefix BEFORE payload attach; punkres can also stamp a FINISHED kit post-hoc, preserving an appended zip payload (archive-relative moved verbatim; file-relative refused by default, shifted with a consent flag). Non-PE targets skip as not applicable; a host where neither mechanism serves skips with a combined notice naming the punkres build remedy; the sidecar is written in every case. Sources: `src/AGENTS.md`, `bin/AGENTS.md`, `src/vfs/AGENTS.md`, `src/tools/AGENTS.md`. - **Kit icon step (G-057 + G-128).** Every kit a bake builds gets a `<kitname>.resources.toml` sidecar (deployed beside `bin/<kit>`) recording the build-time icon choice - default `src/runtime/punkshell.ico`, overridable by a root `punkshell.ico` in the kit's own custom `.vfs` folder (pre-merge) - with sha256 identity and provenance lifted from the icon's G-135 assetorigin record. win32-target kits get the icon embedded as PE `RT_ICON`/`RT_GROUP_ICON` behind a single seam (`::punkboot::kit_icon_process`): the vendored punkres portable stamper (`src/tools/punkres`, built to `bin/punkres(.exe)` by the make.tcl tool step) is selected when present and works from any build host; otherwise the twapi arm (tcl-sfe mechanism) serves windows hosts with nothing built. Both arms share one semantic (delete all icon/group entries, write ids 1..N; the group is NAMED from the icon file's uppercased rootname - `PUNKSHELL` - with language adopted from the replaced group) and stamp a per-kit copy of the payload-free raw runtime prefix BEFORE payload attach; punkres can also stamp a FINISHED kit post-hoc, preserving an appended zip payload (archive-relative moved verbatim; file-relative refused by default, shifted with a consent flag). Non-PE targets skip as not applicable; a host where neither mechanism serves skips with a combined notice naming the punkres build remedy; the sidecar is written in every case. Sources: `src/AGENTS.md`, `bin/AGENTS.md`, `src/vfs/AGENTS.md`, `src/tools/AGENTS.md`.
- **Buildsuites and the kit family.** `src/buildsuites/suite_tcl90/` builds Tcl/Tk/tcllib from source with a pinned zig toolchain and produces the runtime kit family (plain / punk / bi) plus artifact metadata (G-096-G-117 era: see archived goals G-096, G-098, G-102, G-103, G-107); artifacts publish to the punkbin repo that `bin/punk-runtime.cmd` fetches from. `src/buildsuites/suite_tcl86/` is the 8.6 sibling (G-099 + G-100, both achieved): a Tcl 8.6 windows runtime (static + dynamic shells, `tcl86t.dll`, on-disk lib tree - no zipfs, so no self-contained kit) with thread 2.8 + tclvfs + Tk 8.6 + tklib + tcllib(+tcllibc critcl accelerators) companions, gated against the 8.6 core/thread/tclvfs testsuites with tcllib/tklib on a record tier and an opt-in `test-tk`; punkshell's own runtests is censused on that runtime at parity with a same-day native-8.6 baseline. Suite child shells scrub `TCL<major>_<minor>_TM_PATH` as well as TCLLIBPATH/TCL_LIBRARY/TK_LIBRARY - without it a census measures the machine's module trees. The 8.6 kit container strategy remains in-flux - see "In-flux areas". - **Buildsuites and the kit family.** `src/buildsuites/suite_tcl90/` builds Tcl/Tk/tcllib from source with a pinned zig toolchain and produces the runtime kit family (plain / punk / bi) plus artifact metadata (G-096-G-117 era: see archived goals G-096, G-098, G-102, G-103, G-107); artifacts publish to the punkbin repo that `bin/punk-runtime.cmd` fetches from. `src/buildsuites/suite_tcl86/` is the 8.6 sibling (G-099 + G-100, both achieved): a Tcl 8.6 windows runtime (static + dynamic shells, `tcl86t.dll`, on-disk lib tree - no zipfs, so no self-contained kit) with thread 2.8 + tclvfs + Tk 8.6 + tklib + tcllib(+tcllibc critcl accelerators) companions, gated against the 8.6 core/thread/tclvfs testsuites with tcllib/tklib on a record tier and an opt-in `test-tk`; punkshell's own runtests is censused on that runtime at parity with a same-day native-8.6 baseline. Suite child shells scrub `TCL<major>_<minor>_TM_PATH` as well as TCLLIBPATH/TCL_LIBRARY/TK_LIBRARY - without it a census measures the machine's module trees. The 8.6 kit container strategy remains in-flux - see "In-flux areas".
- **Project generation.** `dev project.new` composes thin layouts from `src/project_layouts/` (overlay chain with `.anti` deletion markers and `name@base` derivation - G-087, achieved) and injects bootsupport modules from the generating shell at generation time. - **Project generation.** `dev project.new` composes thin layouts from `src/project_layouts/` (overlay chain with `.anti` deletion markers and `name@base` derivation - G-087, achieved) and injects bootsupport modules from the generating shell at generation time.
- **Workflow overview.** `tclsh src/make.tcl workflow` prints the embedded ASCII data-flow overview of the build/release pipeline, with its own update contract in `src/AGENTS.md`. This section deliberately summarises rather than copies it. - **Workflow overview.** `tclsh src/make.tcl workflow` prints the embedded ASCII data-flow overview of the build/release pipeline, with its own update contract in `src/AGENTS.md`. This section deliberately summarises rather than copies it.

11
CHANGELOG.md

@ -5,6 +5,17 @@ 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` Entries are newest-first; one bullet per notable change. See the root `AGENTS.md`
"Project Versioning" section for the bump policy. "Project Versioning" section for the bump policy.
## [0.30.2] - 2026-07-29
- Baked kits' embedded RT_GROUP_ICON is now NAMED from the icon file's
uppercased rootname - `PUNKSHELL` for `punkshell.ico` (default and per-kit
overrides alike) - instead of retaining the stub lineage's name ("SFE",
"TCLSH"). Applied identically by both icon mechanisms (punkres 0.2.0
`set-icon -group`; the twapi arm gained the matching override), language
still adopted from the replaced group. The `<kit>.resources.toml` sidecar
records the name as `icon_group`. Already-deployed kits keep their old
group name until their next rebuild.
## [0.30.1] - 2026-07-29 ## [0.30.1] - 2026-07-29
- Portable PE resource stamping (G-128, first increment): new vendored zig tool - Portable PE resource stamping (G-128, first increment): new vendored zig tool

12
bin/AGENTS.md

@ -168,8 +168,12 @@ never modified). Two mechanisms share one semantic and yield equivalent
resource content (G-128 parity evidence): `bin/punkres(.exe)` - the vendored resource content (G-128 parity evidence): `bin/punkres(.exe)` - the vendored
portable stamper, built via `make.tcl tool build punkres`, host-independent - portable stamper, built via `make.tcl tool build punkres`, host-independent -
is selected when present; otherwise the twapi arm serves windows hosts with is selected when present; otherwise the twapi arm serves windows hosts with
nothing built. Named "resources", not "icon", so the parked RT_VERSION nothing built. The embedded RT_GROUP_ICON is NAMED from the icon file's
stamping extends the same file. uppercased rootname (`punkshell.ico` -> `PUNKSHELL`, RC convention; applies
to per-kit overrides identically since they are also named `punkshell.ico`),
with the resource language adopted from the group being replaced. Named
"resources", not "icon", so the parked RT_VERSION stamping extends the same
file.
- Icon choice: a root-level `punkshell.ico` in the kit's own custom `.vfs` - Icon choice: a root-level `punkshell.ico` in the kit's own custom `.vfs`
folder (consulted pre-merge, so the `_vfscommon.vfs` copy never reads as an folder (consulted pre-merge, so the `_vfscommon.vfs` copy never reads as an
@ -183,7 +187,9 @@ stamping extends the same file.
path of the chosen icon); `icon_hash` (`sha256:`-prefixed); path of the chosen icon); `icon_hash` (`sha256:`-prefixed);
`icon_provenance_source` / `icon_provenance_source_hash` (lifted from the `icon_provenance_source` / `icon_provenance_source_hash` (lifted from the
chosen icon's `.assetorigin.toml` when one exists - the record then reaches chosen icon's `.assetorigin.toml` when one exists - the record then reaches
back to the SVG-derived master); `embedding` = `punkres` | `twapi` | `none`; back to the SVG-derived master); `icon_group` (the derived RT_GROUP_ICON
resource name, present whenever the icon file exists - recorded even when
embedding did not run); `embedding` = `punkres` | `twapi` | `none`;
`embedding_status` = `embedded` | `not-applicable` | `unavailable` | `embedding_status` = `embedded` | `not-applicable` | `unavailable` |
`failed`; `embedding_reason` (empty when embedded). `failed`; `embedding_reason` (empty when embedded).
- Skip semantics: a target with no PE resources (linux, freebsd, macosx - Skip semantics: a target with no PE resources (linux, freebsd, macosx

35
goals/G-128-portable-pe-resource-stamping.md

@ -173,17 +173,20 @@ the parked RT_VERSION stamping wants, since the project version is known late.
stamping-support review). No acceptance wording change; revisit if other stamping-support review). No acceptance wording change; revisit if other
payload shapes (cookit/cookfs, or a G-101-chosen container) become stamping payload shapes (cookit/cookfs, or a G-101-chosen container) become stamping
targets - a dedicated goal is warranted only then. targets - a dedicated goal is warranted only then.
- Group naming (2026-07-29, user-directed): punkres 0.2.0 adds - Group naming (2026-07-29, user-directed; DEFAULT DECIDED same day): punkres
`set-icon -group <id|name>` overriding the adopted RT_GROUP_ICON name 0.2.0 adds `set-icon -group <id|name>` overriding the adopted RT_GROUP_ICON
(stored as given, case-insensitive lookups; language + codepage adoption name (stored as given, case-insensitive lookups; language + codepage
unchanged; re-stamps without the flag adopt the renamed group, so renaming adoption unchanged; re-stamps without the flag adopt the renamed group, so
is convergent). Motivation: stamped kits carry their stub lineage's group renaming is convergent). Motivation: stamped kits carried their stub
name (punk91 "SFE", suite-runtime kits "TCLSH") where a punkshell-derived lineage's group name (punk91 "SFE", suite-runtime kits "TCLSH"). The SEAM
name reads better. SEAM DEFAULT NOT CHANGED yet - flipping the bake to pass now derives the name from the icon FILE's uppercased rootname (user
a derived name (e.g. the icon file's root name, giving "punkshell" for both decision: uppercase per the RC convention) - punkshell.ico -> PUNKSHELL for
the default icon and per-kit overrides) needs the twapi arm to gain the the default icon and per-kit overrides alike - and passes it to whichever
same override for parity, and changes every baked kit's resource listing - arm embeds: kit_icon_embed_twapi gained the same optional group_override
proposal outstanding with the user. for parity. The sidecar records it as icon_group (present whenever the icon
file exists). Kits already deployed keep their old group name until their
next natural rebuild (the naming policy is not in the punkcheck source set,
so it does not itself dirty kits).
- Related: G-105 - recorded at activation (2026-07-29 overlap survey): the end-to-end - Related: G-105 - recorded at activation (2026-07-29 overlap survey): the end-to-end
non-windows-host acceptance clause needs a host-native punkres build; cross-target non-windows-host acceptance clause needs a host-native punkres build; cross-target
zig builds and target naming live in G-105 rather than here (the same division zig builds and target naming live in G-105 rather than here (the same division
@ -288,3 +291,13 @@ the parked RT_VERSION stamping wants, since the project version is known late.
(user decision - see Notes); G-101 carries the container-review rider. (user decision - see Notes); G-101 carries the container-review rider.
BSD-2-Clause licence confirmed by user. Seam group-name default: proposal BSD-2-Clause licence confirmed by user. Seam group-name default: proposal
outstanding (Notes). outstanding (Notes).
- 2026-07-29 increment 1b (user-directed): seam group-name default LANDED -
kit_icon_process derives icon_group = uppercased icon-file rootname
(PUNKSHELL) and passes it to both arms; kit_icon_embed_twapi gained the
matching group_override parameter (parity); sidecar gains icon_group
(bin/AGENTS.md + ARCHITECTURE.md updated). Live-verified on punkluck86
rebakes: punkres arm and twapi arm (TCLLIBPATH route) both produce
RT_GROUP_ICON "PUNKSHELL" lang 1033 with byte-identical extracted icons
(codepage divergence as per the Notes finding); sidecar icon_group +
embedding recorded; final deployed state punkres-stamped and booting.
punkshell 0.30.2.

2
punkproject.toml

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

57
src/make.tcl

@ -6312,13 +6312,15 @@ proc ::punkboot::assemble_zipcat_image {raw_runtime wrapvfs outfile zipfile} {
#consulted PRE-merge so the _vfscommon copy never reads as an override), and #consulted PRE-merge so the _vfscommon copy never reads as an override), and
#win32-target kits get that icon embedded as PE RT_ICON/RT_GROUP_ICON resources #win32-target kits get that icon embedded as PE RT_ICON/RT_GROUP_ICON resources
#when this host can write them. Two mechanisms share one semantic (delete ALL #when this host can write them. Two mechanisms share one semantic (delete ALL
#icon/group entries, write the .ico images as ids 1..N under the first #icon/group entries, write the .ico images as ids 1..N; the RT_GROUP_ICON is
#pre-existing group's name+lang - idempotent by construction, parity recorded #NAMED from the icon file - uppercased rootname, so punkshell.ico gives
#in the G-128 detail file): the vendored punkres portable stamper (G-128, #PUNKSHELL (user decision 2026-07-29, RC uppercase convention) - with language
#src/tools/punkres, built by 'make.tcl tool build punkres') is selected when #adopted from the first replaced group; idempotent by construction, parity
#bin/punkres(.exe) exists and works from ANY build host; otherwise the twapi #recorded in the G-128 detail file): the vendored punkres portable stamper
#arm (tcl-sfe sfe-0.2.tm ReplaceIconInStub lineage; Ashok P. Nadkarni) serves #(G-128, src/tools/punkres, built by 'make.tcl tool build punkres') is
#windows hosts with nothing built. Ordering is stub-first either way: a per-kit #selected when bin/punkres(.exe) exists and works from ANY build host;
#otherwise the twapi arm (tcl-sfe sfe-0.2.tm ReplaceIconInStub lineage; Ashok
#P. Nadkarni) serves windows hosts with nothing built. Ordering is stub-first either way: a per-kit
#copy of the payload-free raw runtime prefix is stamped BEFORE any payload is #copy of the payload-free raw runtime prefix is stamped BEFORE any payload is
#appended (punkres could also stamp post-hoc - the bake keeps stub-first so #appended (punkres could also stamp post-hoc - the bake keeps stub-first so
#both arms stay interchangeable). kit_icon_process is the single internal #both arms stay interchangeable). kit_icon_process is the single internal
@ -6538,12 +6540,14 @@ proc ::punkboot::kiticon::punkres_available {repo_root} {
} }
#G-128 punkres arm: exec the vendored portable stamper on the payload-free stub #G-128 punkres arm: exec the vendored portable stamper on the payload-free stub
#copy. punkres itself deletes all icon/group entries, writes the images as ids #copy. punkres itself deletes all icon/group entries, writes the images as ids
#1..N under the first pre-existing group's name+lang, and re-reads its own #1..N under the first pre-existing group's name+lang (a non-empty
#group_override renames the group via 'set-icon -group' - the seam's naming
#policy; language and codepage adoption unchanged), and re-reads its own
#output (resources AND any overlay) before reporting success - equivalent #output (resources AND any overlay) before reporting success - equivalent
#resource content to the twapi arm from the same input (parity evidence in the #resource content to the twapi arm from the same input (parity evidence in the
#G-128 detail file). Returns the number of images embedded; raises an error #G-128 detail file). Returns the number of images embedded; raises an error
#carrying punkres's output on any nonzero exit. #carrying punkres's output on any nonzero exit.
proc ::punkboot::kit_icon_embed_punkres {punkres_exe exepath icopath} { proc ::punkboot::kit_icon_embed_punkres {punkres_exe exepath icopath {group_override {}}} {
set f [open $icopath rb] set f [open $icopath rb]
set icondata [read $f] set icondata [read $f]
close $f close $f
@ -6554,7 +6558,12 @@ proc ::punkboot::kit_icon_embed_punkres {punkres_exe exepath icopath} {
if {$ico_count == 0} { if {$ico_count == 0} {
error "no images in $icopath" error "no images in $icopath"
} }
if {[catch {exec [file nativename $punkres_exe] set-icon [file nativename $exepath] [file nativename $icopath] 2>@1} output]} { set cmd [list exec [file nativename $punkres_exe] set-icon]
if {$group_override ne ""} {
lappend cmd -group $group_override
}
lappend cmd [file nativename $exepath] [file nativename $icopath] 2>@1
if {[catch $cmd output]} {
error "punkres set-icon failed: $output" error "punkres set-icon failed: $output"
} }
return $ico_count return $ico_count
@ -6563,10 +6572,13 @@ proc ::punkboot::kit_icon_embed_punkres {punkres_exe exepath icopath} {
#the images of icopath. Follows sfe-0.2.tm ReplaceIconInStub generalized: all #the images of icopath. Follows sfe-0.2.tm ReplaceIconInStub generalized: all
#existing icon/group entries (any name, any lang) are deleted and the new set #existing icon/group entries (any name, any lang) are deleted and the new set
#written as ids 1..N under the first pre-existing group's name+lang (fallback #written as ids 1..N under the first pre-existing group's name+lang (fallback
#name 1, lang 1033), in one resource-update transaction. Raises an error on #name 1, lang 1033), in one resource-update transaction. A non-empty
#failure (after -discard); returns the number of images embedded. The file at #group_override replaces the group NAME only (language adoption unchanged) -
#exepath must carry NO appended payload - a resource update rewrites the image. #the same override punkres's 'set-icon -group' applies, so the seam's naming
proc ::punkboot::kit_icon_embed_twapi {exepath icopath} { #policy keeps the two arms in parity (G-128). Raises an error on failure
#(after -discard); returns the number of images embedded. The file at exepath
#must carry NO appended payload - a resource update rewrites the image.
proc ::punkboot::kit_icon_embed_twapi {exepath icopath {group_override {}}} {
set f [open $icopath rb] set f [open $icopath rb]
set icondata [read $f] set icondata [read $f]
close $f close $f
@ -6601,6 +6613,9 @@ proc ::punkboot::kit_icon_embed_twapi {exepath icopath} {
if {[llength $old_groups]} { if {[llength $old_groups]} {
lassign [lindex $old_groups 0] group_name group_lang lassign [lindex $old_groups 0] group_name group_lang
} }
if {$group_override ne ""} {
set group_name $group_override
}
set update_h [twapi::begin_resource_update $exepath] set update_h [twapi::begin_resource_update $exepath]
try { try {
foreach entry $old_icons { foreach entry $old_icons {
@ -6649,6 +6664,15 @@ proc ::punkboot::kit_icon_process {targetkit rt_target rtname kit_type sourcefol
set icon_path $sourcefolder/runtime/punkshell.ico set icon_path $sourcefolder/runtime/punkshell.ico
} }
set have_icon [file isfile $icon_path] set have_icon [file isfile $icon_path]
#RT_GROUP_ICON name policy (G-128, user decision 2026-07-29): derived from
#the icon FILE's rootname, uppercased per the RC convention - punkshell.ico
#gives PUNKSHELL for the default icon and for per-kit overrides alike
#(overrides are by convention also named punkshell.ico). Applied by
#whichever mechanism embeds; language stays adopted from the replaced group.
set icon_group ""
if {$have_icon} {
set icon_group [string toupper [file rootname [file tail $icon_path]]]
}
set embedding none set embedding none
set status "" set status ""
set reason "" set reason ""
@ -6687,10 +6711,10 @@ proc ::punkboot::kit_icon_process {targetkit rt_target rtname kit_type sourcefol
catch {exec chmod +w $stamped} catch {exec chmod +w $stamped}
if {$punkres_ok} { if {$punkres_ok} {
set embedding punkres set embedding punkres
set embed_cmd [list ::punkboot::kit_icon_embed_punkres $punkres_info $stamped $icon_path] set embed_cmd [list ::punkboot::kit_icon_embed_punkres $punkres_info $stamped $icon_path $icon_group]
} else { } else {
set embedding twapi set embedding twapi
set embed_cmd [list ::punkboot::kit_icon_embed_twapi $stamped $icon_path] set embed_cmd [list ::punkboot::kit_icon_embed_twapi $stamped $icon_path $icon_group]
} }
if {[catch $embed_cmd embed_result]} { if {[catch $embed_cmd embed_result]} {
::punkboot::print_build_warnings [list "kit icon embedding FAILED for $targetkit ($icon_origin icon $icon_path via $embedding): $embed_result - kit keeps its runtime's own icon"] ::punkboot::print_build_warnings [list "kit icon embedding FAILED for $targetkit ($icon_origin icon $icon_path via $embedding): $embed_result - kit keeps its runtime's own icon"]
@ -6727,6 +6751,7 @@ proc ::punkboot::kit_icon_process {targetkit rt_target rtname kit_type sourcefol
if {[dict exists $ao source_hash]} { if {[dict exists $ao source_hash]} {
lappend lines "icon_provenance_source_hash = \"[$esc [dict get $ao source_hash]]\"" lappend lines "icon_provenance_source_hash = \"[$esc [dict get $ao source_hash]]\""
} }
lappend lines "icon_group = \"[$esc $icon_group]\""
} }
lappend lines "embedding = \"$embedding\"" lappend lines "embedding = \"$embedding\""
lappend lines "embedding_status = \"$status\"" lappend lines "embedding_status = \"$status\""

Loading…
Cancel
Save