Browse Source

G-057 achieved: flip, archive record, reference sweep, owning-doc pointers

Acceptance verified in full on 2026-07-29 (evidence in the detail file's
Progress section): windows-host bakes embed the default punkshell.ico
into all 10 buildable win32 kits across zip (x64 + ix86), sdx-metakit
and stamped-concat assembly, verified by twapi resource inspection
byte-matching the source ico; override round-trip proven and reverted;
boots for zip, metakit and concat images from scratch copies; linux
cross-target kit gets its sidecar with NOT APPLICABLE; the two
incapable-host conditions produce their distinct notices in REAL bakes
(mingw tclsh86: twapi not loadable; WSL linux cross-bake: cross-host
with the G-128 remedy named - and the cross-baked kit boots on windows,
the recorded known shortcoming live); idempotence converges; runtime
store originals untouched; vendored-twapi no-toolchain arm proven under
tclsh9.0.5-punk.

Index entry moves to GOALS-archive.md (ID position); the detail-file
move to goals/archive/ follows as its own pure-rename commit. Reference
sweep: G-023, G-028, G-127 and G-128 notes gain achieved/archive markers
plus what each consumes from the delivered mechanism (G-128: the seam
now exists - kit_icon_process entry point, sidecar record, cross-host
notice naming it as remedy; G-028: the stub-first ordering concentrates
the locked-target exposure at deploy, punk9_beta observed). AGENTS.md
owning-doc pointers land alongside: src/vfs (override convention),
src/runtime (default-icon role + derivation sidecar), src/assets/logo
(propagation honesty: G-057 consumes the src/runtime copy - syncing the
four build-consumed copies after artwork changes stays deliberate, with
assetorigin stale-detection as the drift signal), and an ARCHITECTURE.md
build-section bullet (architecture_lint clean).

Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
Julian Noble 2 days ago
parent
commit
47c9f99eff
  1. 1
      ARCHITECTURE.md
  2. 4
      GOALS-archive.md
  3. 4
      GOALS.md
  4. 12
      goals/G-023-version-named-binaries.md
  5. 13
      goals/G-028-file-locker-identification.md
  6. 19
      goals/G-057-kit-icon-embedding.md
  7. 17
      goals/G-127-crosstarget-vfs-bake.md
  8. 17
      goals/G-128-portable-pe-resource-stamping.md
  9. 14
      src/assets/logo/AGENTS.md
  10. 1
      src/runtime/AGENTS.md
  11. 5
      src/vfs/AGENTS.md

1
ARCHITECTURE.md

@ -87,6 +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).** 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 on a twapi-capable host get the icon embedded as PE `RT_ICON`/`RT_GROUP_ICON`: a per-kit copy of the payload-free raw runtime prefix is stamped BEFORE payload attach (the tcl-sfe mechanism behind a single seam, `::punkboot::kit_icon_process`, so a portable stamper - G-128 - substitutes without caller changes). Non-PE targets skip as not applicable; incapable hosts (no twapi / non-windows build host) skip with distinct notices; the sidecar is written in every case. Sources: `src/AGENTS.md`, `bin/AGENTS.md`, `src/vfs/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.

4
GOALS-archive.md

@ -75,6 +75,10 @@ Acceptance: the pinned GAP tests flip: cmdhelp_GAP_pseudo_command_cmdtype_notfou
Scope: src/modules/punk/args/moduledoc/tclcore-999999.0a1.0.tm (+ tclcore-buildversion.txt); src/tests/modules/punk/args/testsuites/args/ (new parity test); TEMP_REFERENCE/tcl9 (read-only reference) Scope: src/modules/punk/args/moduledoc/tclcore-999999.0a1.0.tm (+ tclcore-buildversion.txt); src/tests/modules/punk/args/testsuites/args/ (new parity test); TEMP_REFERENCE/tcl9 (read-only reference)
Acceptance: parse/parse_status against ::tcl::string::is and its per-class virtual ids agrees with the real interpreter's error-vs-ok outcome for a pinned probe matrix (missing args, trailing flag-like str word, option/class unique-prefix acceptance and ambiguity rejection, unknown option/class, -failindex var consumption leaving no str, per-version class presence: dict, unicode) on Tcl 9.0.x and 8.6; the rendered choices show only classes the running interp accepts; the parity test derives expectations from the live interpreter (not version arithmetic) and passes under both; existing args/tclcore suites pass; tclcore buildversion bumped with changelog. Acceptance: parse/parse_status against ::tcl::string::is and its per-class virtual ids agrees with the real interpreter's error-vs-ok outcome for a pinned probe matrix (missing args, trailing flag-like str word, option/class unique-prefix acceptance and ambiguity rejection, unknown option/class, -failindex var consumption leaving no str, per-version class presence: dict, unicode) on Tcl 9.0.x and 8.6; the rendered choices show only classes the running interp accepts; the parity test derives expectations from the live interpreter (not version arithmetic) and passes under both; existing args/tclcore suites pass; tclcore buildversion bumped with changelog.
### G-057 [achieved 2026-07-29] Kit builds carry a configurable icon: text sidecar for every target, embedded PE resources for windows targets → detail: goals/archive/G-057-kit-icon-embedding.md
Scope: src/make.tcl (kit/zipkit wrap steps); src/runtime/punkshell.ico (project default, existing); src/vfs/*.vfs (override placement convention); src/runtime/mapvfs.config (only if an explicit config element is the chosen override mechanism); TEMP_REFERENCE/tcl-sfe (read-only reference); helper proc location decided in the work (make.tcl inline vs punk::mix lib); kit icon sidecar record (emission points recorded in the work)
Acceptance: a `make.tcl bake` on a windows host producing a win32-target kit produces kit executables whose embedded icon resources are the project default punkshell.ico, and a kit whose .vfs supplies an override icon gets that icon instead (verified by resource inspection, e.g twapi::extract_resources, not just Explorer eyeballing); the icon-replaced executables still boot to a working punk shell reading their vfs payload for the kit types we build (kit, zip, zipcat per mapvfs.config); runtimes under src/runtime are never modified - replacement applies to the built copies only; a target with no PE resources (linux, freebsd, macosx) skips embedding as NOT APPLICABLE rather than as degradation and still gets its sidecar, while a win32 target on a host that cannot perform the update (twapi unavailable, or a non-windows host cross-baking a windows kit) skips embedding with a DISTINCT notice naming which condition applied, still writes the sidecar, and the build otherwise completes unchanged - the cross-host case is recorded here as a known shortcoming with its remedy; the sidecar is produced for every kit on every target, carries the same icon data the PE embedding uses (source .ico identity and provenance) in a documented plain-text form, is byte-stable across rebuilds at unchanged input, and is defined so the parked RT_VERSION follow-on extends the same file rather than adding a second one; the embedding implementation sits behind a single internal entry point with the mechanism selected inside it, so a later portable replacement is a substitution rather than a rewrite; the twapi mechanism remains available INDEFINITELY as the no-toolchain windows path - the seam SELECTS between mechanisms rather than replacing one with the other - and a fresh checkout that fetches a runtime and bakes produces iconed kits with no build toolchain installed; rebuilds are idempotent (re-wrapping an already-iconed build copy converges, no resource accumulation); the override convention (filename/location in the kit's custom .vfs folder vs a mapvfs.config element) and the stub-vs-split ordering decision are recorded in the detail file with the tcl-sfe attribution - the override is SHARED across a kit definition's targets and carries no target dimension (decided 2026-07-26): it is used where embedding applies and ignored elsewhere.
### G-058 [achieved 2026-07-10] Boot honours statically-linked runtime packages (static baseline seeding + packagepreference static-awareness) → detail: goals/archive/G-058-static-runtime-packages.md ### G-058 [achieved 2026-07-10] Boot honours statically-linked runtime packages (static baseline seeding + packagepreference static-awareness) → detail: goals/archive/G-058-static-runtime-packages.md
Scope: src/vfs/_config/punk_main.tcl (boot auto_path/tm path filtering); src/modules/punk/packagepreference-999999.0a1.0.tm; src/modules/punk/repl-999999.0a1.0.tm + src/modules/punk/repl/codethread-999999.0a1.0.tm (code interp / codethread bootstrap); src/modules/shellthread-999999.0a1.0.tm (punkshell-created worker threads) as applicable; src/tests/ (un-gated unit tests + constraint-gated shell/kit integration tests); punkbin artifact repo (separate git repo, local checkout c:/repo/jn/punkbin - pinned runtime additions) Scope: src/vfs/_config/punk_main.tcl (boot auto_path/tm path filtering); src/modules/punk/packagepreference-999999.0a1.0.tm; src/modules/punk/repl-999999.0a1.0.tm + src/modules/punk/repl/codethread-999999.0a1.0.tm (code interp / codethread bootstrap); src/modules/shellthread-999999.0a1.0.tm (punkshell-created worker threads) as applicable; src/tests/ (un-gated unit tests + constraint-gated shell/kit integration tests); punkbin artifact repo (separate git repo, local checkout c:/repo/jn/punkbin - pinned runtime additions)
Acceptance: a punk91-style kit (tclsfe-x64 + punk9win.vfs, no thread dll in the vfs) boots to a working repl with no "can't find package Thread" - punk::console loads in the code interp, and package require Thread succeeds there and in a punkshell-created worker thread, resolving to the static version; in the same kit, twapi resolves per the documented policy (no repeat of the observed static-Twapi-masked-by-older-vfs-twapi-5.0.2 double load; a genuinely newer bundled copy remains reachable by that policy); dll-based kits (punk902z) boot and pass their existing shell test baseline unchanged, as does a plain tclsh dev launch; the seeding mechanism is generic - driven by the captured baseline, no runtime-specific package naming - and the boot-time static baseline is introspectable at the repl; the seeding/preference logic is covered by un-gated unit tests against simulated baselines (runnable under plain tclsh), while kit-boot integration tests are gated behind a capability-probed tcltest constraint (a built kit whose baseline shows static entries including Thread) that skips cleanly when no such kit is present; the runtimes used for verification (tclsfe-x64.exe at minimum) are added to the punkbin artifact repository under win32-x86_64 with sha1sums.txt updated, so the constraint is satisfiable on other machines via the existing runtime-retrieval path; the punk91 code-interp vfs/vfs::zip load failure is re-diagnosed after the fix and either resolved or recorded as a distinct issue/candidate goal. Acceptance: a punk91-style kit (tclsfe-x64 + punk9win.vfs, no thread dll in the vfs) boots to a working repl with no "can't find package Thread" - punk::console loads in the code interp, and package require Thread succeeds there and in a punkshell-created worker thread, resolving to the static version; in the same kit, twapi resolves per the documented policy (no repeat of the observed static-Twapi-masked-by-older-vfs-twapi-5.0.2 double load; a genuinely newer bundled copy remains reachable by that policy); dll-based kits (punk902z) boot and pass their existing shell test baseline unchanged, as does a plain tclsh dev launch; the seeding mechanism is generic - driven by the captured baseline, no runtime-specific package naming - and the boot-time static baseline is introspectable at the repl; the seeding/preference logic is covered by un-gated unit tests against simulated baselines (runnable under plain tclsh), while kit-boot integration tests are gated behind a capability-probed tcltest constraint (a built kit whose baseline shows static entries including Thread) that skips cleanly when no such kit is present; the runtimes used for verification (tclsfe-x64.exe at minimum) are added to the punkbin artifact repository under win32-x86_64 with sha1sums.txt updated, so the constraint is satisfiable on other machines via the existing runtime-retrieval path; the punk91 code-interp vfs/vfs::zip load failure is re-diagnosed after the fix and either resolved or recorded as a distinct issue/candidate goal.

4
GOALS.md

@ -241,10 +241,6 @@ Detail: goals/G-055-tclcore-regen-workflow.md
Scope: src/modules/punk/args-999999.0a1.0.tm (arg_error table and string renderers, helpers); src/modules/textblock-999999.0a1.0.tm (only if cell/column-level wrap is the chosen mechanism); src/tests/modules/punk/args/testsuites/args/ (new wrapping characterization + existing rendering suites) Scope: src/modules/punk/args-999999.0a1.0.tm (arg_error table and string renderers, helpers); src/modules/textblock-999999.0a1.0.tm (only if cell/column-level wrap is the chosen mechanism); src/tests/modules/punk/args/testsuites/args/ (new wrapping characterization + existing rendering suites)
Detail: goals/G-056-punkargs-word-wrapping.md Detail: goals/G-056-punkargs-word-wrapping.md
### G-057 [active] Kit builds carry a configurable icon: text sidecar for every target, embedded PE resources for windows targets
Scope: src/make.tcl (kit/zipkit wrap steps); src/runtime/punkshell.ico (project default, existing); src/vfs/*.vfs (override placement convention); src/runtime/mapvfs.config (only if an explicit config element is the chosen override mechanism); TEMP_REFERENCE/tcl-sfe (read-only reference); helper proc location decided in the work (make.tcl inline vs punk::mix lib); kit icon sidecar record (emission points recorded in the work)
Detail: goals/G-057-kit-icon-embedding.md
### G-060 [proposed] QEMU-based cross-platform test matrix (arm's-length integration, GPL-safe posture) ### G-060 [proposed] QEMU-based cross-platform test matrix (arm's-length integration, GPL-safe posture)
Scope: build/test orchestration config and scripts (location to be settled with the buildsuites toml work - see G-005/buildsuites direction); goals/G-060-qemu-test-matrix.md (workflow + license posture); src/tests/ (any guest-driving hooks) Scope: build/test orchestration config and scripts (location to be settled with the buildsuites toml work - see G-005/buildsuites direction); goals/G-060-qemu-test-matrix.md (workflow + license posture); src/tests/ (any guest-driving hooks)
Detail: goals/G-060-qemu-test-matrix.md Detail: goals/G-060-qemu-test-matrix.md

12
goals/G-023-version-named-binaries.md

@ -86,8 +86,12 @@ binary-artifacts repository). Revisit when the accumulation actually bites.
DECISION section (achieved 2026-07-22 - goals/archive/G-103-runtime-kit-family.md; the DECISION section (achieved 2026-07-22 - goals/archive/G-103-runtime-kit-family.md; the
decision text is stable there decision text is stable there
flipped). flipped).
- G-057 relationship (recorded 2026-07-24 after overlap review): the - G-057 relationship (recorded 2026-07-24; achieved 2026-07-29, archived -
icon-embedding step hooks the same kit wrap steps; its ordering constraint see goals/archive/G-057-kit-icon-embedding.md): the icon-embedding step now
(icon the stub before payload append) interacts with this goal's every-build LIVES in the kit wrap steps this goal hooks - stub-first (a per-kit stamped
rewrite cadence. copy of the raw runtime prefix feeds the assemblers), re-run from a pristine
re-split prefix every build, so this goal's every-build rewrite cadence and
the stamping converge by construction. Scheme-expanded output names would
each get their own <name>.resources.toml sidecar via the same per-targetkit
emission.
- G-121 (archived) recorded that scheme-expanded output names should enter the parsed mapping model as expansions (::punkboot::lib::mapvfs_kit_outputs) so generated names join the bakelist / bake-by-name surface automatically when this goal lands - see goals/archive/G-121-bakelist-selective-bake.md - G-121 (archived) recorded that scheme-expanded output names should enter the parsed mapping model as expansions (::punkboot::lib::mapvfs_kit_outputs) so generated names join the bakelist / bake-by-name surface automatically when this goal lands - see goals/archive/G-121-bakelist-selective-bake.md

13
goals/G-028-file-locker-identification.md

@ -84,8 +84,13 @@ the kind of file this fails on.
or the same Restart-Manager-adjacent infrastructure this goal introduces) or the same Restart-Manager-adjacent infrastructure this goal introduces)
is the fix, and a locker-report helper that returns paths would serve both. is the fix, and a locker-report helper that returns paths would serve both.
(G-030 achieved 2026-07-14 - goals/archive/G-030-maketcl-punkargs.md) (G-030 achieved 2026-07-14 - goals/archive/G-030-maketcl-punkargs.md)
- G-057 relationship (recorded 2026-07-24 after overlap review): its PE - G-057 relationship (recorded 2026-07-24; achieved 2026-07-29, archived -
resource update hits the same locked-target failure class when an inspected see goals/archive/G-057-kit-icon-embedding.md): as implemented the icon step
or running kit is being re-wrapped - the locker-report helper covers the icon stamps a fresh per-kit COPY of the raw runtime prefix in src/_build before
step's failures as well as deploy's. payload attach, so the resource update itself never touches a runnable
deployed file - the locked-target exposure stays concentrated at the deploy
step (observed again 2026-07-29: punk9_beta embedded + built, deploy blocked
by the bin file lock). The locker-report helper this goal wants would name
the holder for that deploy failure; a locked stamped-copy in _build is
possible but requires something unusual holding _build files open.
- G-121 (archived) shipped bakelist's deployed-state column (bin/<kit> vs src/_build: current|stale|absent|nobuild) - the reporting sibling of this goal's acting-path deploy-failure naming; a locked-exe deploy failure shows afterwards as deployed=stale - see goals/archive/G-121-bakelist-selective-bake.md - G-121 (archived) shipped bakelist's deployed-state column (bin/<kit> vs src/_build: current|stale|absent|nobuild) - the reporting sibling of this goal's acting-path deploy-failure naming; a locked-exe deploy failure shows afterwards as deployed=stale - see goals/archive/G-121-bakelist-selective-bake.md

19
goals/G-057-kit-icon-embedding.md

@ -1,6 +1,6 @@
# G-057 Kit builds carry a configurable icon: text sidecar for every target, embedded PE resources for windows targets # G-057 Kit builds carry a configurable icon: text sidecar for every target, embedded PE resources for windows targets
Status: active Status: achieved 2026-07-29
Scope: src/make.tcl (kit/zipkit wrap steps); src/runtime/punkshell.ico (project default, existing); src/vfs/*.vfs (override placement convention); src/runtime/mapvfs.config (only if an explicit config element is the chosen override mechanism); TEMP_REFERENCE/tcl-sfe (read-only reference); helper proc location decided in the work (make.tcl inline vs punk::mix lib); kit icon sidecar record (emission points recorded in the work) Scope: src/make.tcl (kit/zipkit wrap steps); src/runtime/punkshell.ico (project default, existing); src/vfs/*.vfs (override placement convention); src/runtime/mapvfs.config (only if an explicit config element is the chosen override mechanism); TEMP_REFERENCE/tcl-sfe (read-only reference); helper proc location decided in the work (make.tcl inline vs punk::mix lib); kit icon sidecar record (emission points recorded in the work)
Goal: kit/zipkit builds record a build-time icon choice for every target - defaulting to the project icon src/runtime/punkshell.ico and overridable per kit by its .vfs folder - in a text sidecar that ships with the kit whatever its target, and embed it as PE icon resources when the target has them and the build host can write them - by replacing the icon resources in the built executable using the twapi-based mechanism demonstrated in tcl-sfe (TEMP_REFERENCE/tcl-sfe, by twapi author and Tcl core member Ashok P. Nadkarni): RT_ICON/RT_GROUP_ICON replacement via twapi resource-update APIs, applied so the appended vfs payload stays intact (icon the stub before appending, or sfe-style split/update/reattach), behind a single mechanism seam so the embedding implementation can be replaced without touching its callers. Goal: kit/zipkit builds record a build-time icon choice for every target - defaulting to the project icon src/runtime/punkshell.ico and overridable per kit by its .vfs folder - in a text sidecar that ships with the kit whatever its target, and embed it as PE icon resources when the target has them and the build host can write them - by replacing the icon resources in the built executable using the twapi-based mechanism demonstrated in tcl-sfe (TEMP_REFERENCE/tcl-sfe, by twapi author and Tcl core member Ashok P. Nadkarni): RT_ICON/RT_GROUP_ICON replacement via twapi resource-update APIs, applied so the appended vfs payload stays intact (icon the stub before appending, or sfe-style split/update/reattach), behind a single mechanism seam so the embedding implementation can be replaced without touching its callers.
Acceptance: a `make.tcl bake` on a windows host producing a win32-target kit produces kit executables whose embedded icon resources are the project default punkshell.ico, and a kit whose .vfs supplies an override icon gets that icon instead (verified by resource inspection, e.g twapi::extract_resources, not just Explorer eyeballing); the icon-replaced executables still boot to a working punk shell reading their vfs payload for the kit types we build (kit, zip, zipcat per mapvfs.config); runtimes under src/runtime are never modified - replacement applies to the built copies only; a target with no PE resources (linux, freebsd, macosx) skips embedding as NOT APPLICABLE rather than as degradation and still gets its sidecar, while a win32 target on a host that cannot perform the update (twapi unavailable, or a non-windows host cross-baking a windows kit) skips embedding with a DISTINCT notice naming which condition applied, still writes the sidecar, and the build otherwise completes unchanged - the cross-host case is recorded here as a known shortcoming with its remedy; the sidecar is produced for every kit on every target, carries the same icon data the PE embedding uses (source .ico identity and provenance) in a documented plain-text form, is byte-stable across rebuilds at unchanged input, and is defined so the parked RT_VERSION follow-on extends the same file rather than adding a second one; the embedding implementation sits behind a single internal entry point with the mechanism selected inside it, so a later portable replacement is a substitution rather than a rewrite; the twapi mechanism remains available INDEFINITELY as the no-toolchain windows path - the seam SELECTS between mechanisms rather than replacing one with the other - and a fresh checkout that fetches a runtime and bakes produces iconed kits with no build toolchain installed; rebuilds are idempotent (re-wrapping an already-iconed build copy converges, no resource accumulation); the override convention (filename/location in the kit's custom .vfs folder vs a mapvfs.config element) and the stub-vs-split ordering decision are recorded in the detail file with the tcl-sfe attribution - the override is SHARED across a kit definition's targets and carries no target dimension (decided 2026-07-26): it is used where embedding applies and ignored elsewhere. Acceptance: a `make.tcl bake` on a windows host producing a win32-target kit produces kit executables whose embedded icon resources are the project default punkshell.ico, and a kit whose .vfs supplies an override icon gets that icon instead (verified by resource inspection, e.g twapi::extract_resources, not just Explorer eyeballing); the icon-replaced executables still boot to a working punk shell reading their vfs payload for the kit types we build (kit, zip, zipcat per mapvfs.config); runtimes under src/runtime are never modified - replacement applies to the built copies only; a target with no PE resources (linux, freebsd, macosx) skips embedding as NOT APPLICABLE rather than as degradation and still gets its sidecar, while a win32 target on a host that cannot perform the update (twapi unavailable, or a non-windows host cross-baking a windows kit) skips embedding with a DISTINCT notice naming which condition applied, still writes the sidecar, and the build otherwise completes unchanged - the cross-host case is recorded here as a known shortcoming with its remedy; the sidecar is produced for every kit on every target, carries the same icon data the PE embedding uses (source .ico identity and provenance) in a documented plain-text form, is byte-stable across rebuilds at unchanged input, and is defined so the parked RT_VERSION follow-on extends the same file rather than adding a second one; the embedding implementation sits behind a single internal entry point with the mechanism selected inside it, so a later portable replacement is a substitution rather than a rewrite; the twapi mechanism remains available INDEFINITELY as the no-toolchain windows path - the seam SELECTS between mechanisms rather than replacing one with the other - and a fresh checkout that fetches a runtime and bakes produces iconed kits with no build toolchain installed; rebuilds are idempotent (re-wrapping an already-iconed build copy converges, no resource accumulation); the override convention (filename/location in the kit's custom .vfs folder vs a mapvfs.config element) and the stub-vs-split ordering decision are recorded in the detail file with the tcl-sfe attribution - the override is SHARED across a kit definition's targets and carries no target dimension (decided 2026-07-26): it is used where embedding applies and ignored elsewhere.
@ -299,4 +299,19 @@ recorded as gathered:
loadable", sidecar written, kit assembled via the zipfs-less concat path loadable", sidecar written, kit assembled via the zipfs-less concat path
and deployed unstamped (graceful completion). and deployed unstamped (graceful completion).
- Runtime store originals untouched throughout: stamping operates on - Runtime store originals untouched throughout: stamping operates on
per-kit copies (src/_build/iconed_<kit>) of the extraction-phase raw prefix. per-kit copies (src/_build/iconed_<kit>) of the extraction-phase raw prefix;
store file mtimes verified unchanged after all bakes.
- Host-capability skip, cross-host condition (the real thing, not a code
read): punkluck86 baked from WSL linux (tclsh 8.6.14, /mnt/c) - distinct
notice "embedding UNAVAILABLE ... cross-host: win32 target baked on a
linux-x86_64 host cannot run the twapi resource APIs (portable post-hoc
stamping is the G-128 remedy)", kit INSTALLED, sidecar deployed with
embedding_status unavailable + that reason. The cross-baked win32 kit BOOTS
on windows reading its payload (scratch copy) - a working, merely icon-less
artifact: the recorded known shortcoming, live. A subsequent windows-host
rebake re-embedded and the deployed sidecar flipped unavailable ->
embedded, demonstrating the record's host-capability dimension end-to-end.
Acceptance evaluated 2026-07-29 against every clause: met. The flip archives
this file; the cross-host shortcoming + G-128 remedy note above and the
Decisions section carry the durable design record.

17
goals/G-127-crosstarget-vfs-bake.md

@ -111,11 +111,18 @@ exists locally (empty but for sha1sums.txt) and punkbin upstream carries
platform axis and the payload axis have never been connected, and this goal is that platform axis and the payload axis have never been connected, and this goal is that
connection. connection.
- Related: G-024 - format home for expressing one vfs definition against several targets. - Related: G-024 - format home for expressing one vfs definition against several targets.
- Related: G-057 - icon embedding is a windows-target-only wrap step keyed off a per-vfs - Related: G-057 (achieved 2026-07-29, archived - see
override, so "which kits get an icon" becomes a target question once one vfs definition goals/archive/G-057-kit-icon-embedding.md) - icon embedding is a
serves several targets. Settled there 2026-07-26: the override is shared across a kit windows-target-only wrap step keyed off a per-vfs override, so "which kits
definition's targets and carries no target dimension - used where embedding applies, get an icon" becomes a target question once one vfs definition serves
ignored elsewhere. several targets. Settled there 2026-07-26 and implemented so: the override
is shared across a kit definition's targets and carries no target dimension
- used where embedding applies, ignored elsewhere. Every target's kit gets a
<kitname>.resources.toml sidecar either way (a linux-target kit records
not-applicable; a win32 kit cross-baked from a non-windows host records
unavailable with the G-128 remedy named - both proven live 2026-07-29, WSL
cross-bake included), so this goal's per-target outputs inherit working
record semantics.
- Related: G-105 - produces the cross-target RUNTIMES this consumes for custom kits. - Related: G-105 - produces the cross-target RUNTIMES this consumes for custom kits.
- Related: G-005 / G-006 - where a target's binary payload comes from: built from source - Related: G-005 / G-006 - where a target's binary payload comes from: built from source
or downloaded with consent. or downloaded with consent.

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

@ -75,8 +75,21 @@ the parked RT_VERSION stamping wants, since the project version is known late.
## Notes ## Notes
- Depends on: G-057 - supplies the mechanism seam this plugs into, and stays the - Depends on: G-057 (achieved 2026-07-29, archived - see
no-toolchain windows path. This goal adds a mechanism; it does not remove one. goals/archive/G-057-kit-icon-embedding.md) - supplies the mechanism seam
this plugs into, and stays the no-toolchain windows path. This goal adds a
mechanism; it does not remove one. The seam now EXISTS:
`::punkboot::kit_icon_process` in src/make.tcl is the single entry point
with mechanism selection inside it (`::punkboot::kit_icon_embed_twapi` is
the twapi arm), the per-kit `<kitname>.resources.toml` sidecar records
embedding/status/reason (bin/AGENTS.md documents the format), and the
cross-host skip notice names this goal as the remedy - the WSL linux
cross-bake of a win32 kit (2026-07-29) is the live demonstration of the gap
this goal closes. Note the bake seam stamps stub-first (pre-payload); this
goal's post-hoc split/update/reattach operates on FINISHED kits, so its
integration point can be either the same seam (replacing the twapi call for
cross-host bakes) or a standalone post-hoc invocation - both stay
substitutions behind kit_icon_process.
- Depends on: G-126 (achieved 2026-07-27 - see goals/archive/G-126-punkzip-accelerator.md) - - Depends on: G-126 (achieved 2026-07-27 - see goals/archive/G-126-punkzip-accelerator.md) -
the vendored-zig-tool build step, optional-zig posture and provenance pattern are the vendored-zig-tool build step, optional-zig posture and provenance pattern are
shared rather than duplicated. Everything this goal needs from it now EXISTS: shared rather than duplicated. Everything this goal needs from it now EXISTS:

14
src/assets/logo/AGENTS.md

@ -13,12 +13,16 @@ elsewhere in the tree is a derived copy or a build input, never an original.
- Files under `legacy/` are retired artwork kept for provenance. Do not edit, - Files under `legacy/` are retired artwork kept for provenance. Do not edit,
regenerate, or "modernise" them; they record what shipped before. regenerate, or "modernise" them; they record what shipped before.
- Do not repoint build consumers at this directory on your own initiative. The - Do not repoint build consumers at this directory on your own initiative. The
icon consumed by builds lives at `src/runtime/punkshell.ico` (the G-057 icon consumed by builds lives at `src/runtime/punkshell.ico` (the kit-bake
default) and `src/vfs/_vfscommon.vfs/punkshell.ico`, plus per-kit copies under default - G-057, achieved 2026-07-29) and
`src/vfs/_vfscommon.vfs/punkshell.ico`, plus per-kit copies under
`src/vfs/mkzipfix.vfs/` and `src/vfs/punk8_statictwapi.vfs/`. Those four were `src/vfs/mkzipfix.vfs/` and `src/vfs/punk8_statictwapi.vfs/`. Those four were
set from `punk-mark.ico` on 2026-07-28 at the user's direction. Propagating a set from `punk-mark.ico` on 2026-07-28 at the user's direction. The G-057
later change to them is build machinery owned by G-057 — not a manual step to icon step consumes the `src/runtime/` copy at bake time; SYNCING these four
repeat from here. The `src/runtime/` and `_vfscommon.vfs` copies carry copies from a changed assets master is NOT automated by it - after artwork
changes, refresh them deliberately (their assetorigin sidecars make drift
visible: `assetorigin_check` reports the `src/runtime/` and `_vfscommon`
copies `stale` when `punk-mark.ico` has moved on). The `src/runtime/` and `_vfscommon.vfs` copies carry
assetorigin sidecars recording the derivation (hash equals source_hash: a assetorigin sidecars recording the derivation (hash equals source_hash: a
byte-identical copy); the `_vfscommon.vfs` sidecar ships inside every baked byte-identical copy); the `_vfscommon.vfs` sidecar ships inside every baked
kit that merges the common payload (user-approved 2026-07-28 - inside a kit kit that merges the common payload (user-approved 2026-07-28 - inside a kit

1
src/runtime/AGENTS.md

@ -16,6 +16,7 @@ Houses the `mapvfs.config` that maps VFS payloads to platform runtimes, plus the
- **Smoke-require packages (5th element, G-133).** A kit entry may name packages the freshly built artifact must be able to plain-`package require`; the bake executes host-runnable kits via their tclsh subcommand and requires each one inside the real artifact (the only check that sees package resolution order - e.g a higher-versioned wrong-arch copy shadowing a working one). Advisory: failures are recapped `BUILD-WARNING`s; cross-target kits skip with a stated reason; undeclared kits run nothing new. Interim line format - the schema's eventual home is the G-024 toml conversion. Element positions are fixed, so declaring smoke-requires means also spelling out the target platform. - **Smoke-require packages (5th element, G-133).** A kit entry may name packages the freshly built artifact must be able to plain-`package require`; the bake executes host-runnable kits via their tclsh subcommand and requires each one inside the real artifact (the only check that sees package resolution order - e.g a higher-versioned wrong-arch copy shadowing a working one). Advisory: failures are recapped `BUILD-WARNING`s; cross-target kits skip with a stated reason; undeclared kits run nothing new. Interim line format - the schema's eventual home is the G-024 toml conversion. Element positions are fixed, so declaring smoke-requires means also spelling out the target platform.
- **Target platform (4th element, G-122).** A kit config entry may name the canonical punkshell platform its runtime is for (`help platforms` lists the names). It decides which `bin/runtime/<platform>/` tier the runtime is read from (macosx-* collapsing to the universal `macosx` folder), whether the runtime file and the built kit carry `.exe`, and whether the pre-deploy process sweep applies. It is a property of the RUNTIME: entries on one runtime line may repeat it but must not disagree (a conflict, or a name that is not an `<os>-<cpu>` platform-dir name, is a fatal config error). Omitted means the build host's default target - which for an msys2/cygwin-runtime tclsh is `win32-x86_64`, not that host's own canon. The live example is the `tclkit-902-Linux64-intel-dyn` entry (target `linux-x86_64`, suffixless `punkshell902` artifact). The schema's eventual home is the G-024 toml conversion; consumers read the parsed model (`::punkboot::lib::mapvfs_*`), never the file format. - **Target platform (4th element, G-122).** A kit config entry may name the canonical punkshell platform its runtime is for (`help platforms` lists the names). It decides which `bin/runtime/<platform>/` tier the runtime is read from (macosx-* collapsing to the universal `macosx` folder), whether the runtime file and the built kit carry `.exe`, and whether the pre-deploy process sweep applies. It is a property of the RUNTIME: entries on one runtime line may repeat it but must not disagree (a conflict, or a name that is not an `<os>-<cpu>` platform-dir name, is a fatal config error). Omitted means the build host's default target - which for an msys2/cygwin-runtime tclsh is `win32-x86_64`, not that host's own canon. The live example is the `tclkit-902-Linux64-intel-dyn` entry (target `linux-x86_64`, suffixless `punkshell902` artifact). The schema's eventual home is the G-024 toml conversion; consumers read the parsed model (`::punkboot::lib::mapvfs_*`), never the file format.
- Runtime executables are placed in `bin/runtime/<platform>/` by the `bin/punk-runtime.cmd` helper, manually, or (G-103 family runtimes) copied from the suite_tcl90 `kit-family` build products under `src/buildsuites/_build/suite_tcl90/out/family/`. - Runtime executables are placed in `bin/runtime/<platform>/` by the `bin/punk-runtime.cmd` helper, manually, or (G-103 family runtimes) copied from the suite_tcl90 `kit-family` build products under `src/buildsuites/_build/suite_tcl90/out/family/`.
- `punkshell.ico` here is the project-DEFAULT kit icon: the bake icon step (G-057) records it in every kit's `<kitname>.resources.toml` sidecar and embeds it into win32-target kits (per-kit override + format + skip semantics: bin/AGENTS.md). It is a derived copy of `src/assets/logo/punk-mark.ico` - its `.assetorigin.toml` sidecar records the derivation; regenerate via the logo pipeline, never edit the `.ico` here.
- The `_build/` subdirectory holds build intermediates; it can be safely deleted. - The `_build/` subdirectory holds build intermediates; it can be safely deleted.
## Work Guidance ## Work Guidance

5
src/vfs/AGENTS.md

@ -15,6 +15,11 @@ VFS (Virtual File System) folders define the runtime payloads that get wrapped i
- `*.vfs` folders are build artifacts consumed by the kit-assembly stage `tclsh src/make.tcl bake` (and its consumer umbrella `bakehouse`). - `*.vfs` folders are build artifacts consumed by the kit-assembly stage `tclsh src/make.tcl bake` (and its consumer umbrella `bakehouse`).
- A `*.vfs` folder built against a runtime is expected to carry a root-level startup script: an actual `main.tcl`, or a root fauxlink resolving to the name `main.tcl` whose target exists and is a `.tcl` file. `make.tcl` warns when neither is present (column-0 `BUILD-WARNING:` token, ANSI-highlighted, recapped at end of run like provenance warnings) but still builds - a kit without a startup script is legal. Overlay-only folders with no runtime mapping (e.g `_vfscommon.vfs`) are not checked. - A `*.vfs` folder built against a runtime is expected to carry a root-level startup script: an actual `main.tcl`, or a root fauxlink resolving to the name `main.tcl` whose target exists and is a `.tcl` file. `make.tcl` warns when neither is present (column-0 `BUILD-WARNING:` token, ANSI-highlighted, recapped at end of run like provenance warnings) but still builds - a kit without a startup script is legal. Overlay-only folders with no runtime mapping (e.g `_vfscommon.vfs`) are not checked.
- VFS content must be compatible with the target platform runtime. - VFS content must be compatible with the target platform runtime.
- A root-level `punkshell.ico` in a kit's own custom `.vfs` folder overrides
the embedded kit icon and the sidecar-recorded icon choice for that kit
(G-057; consulted pre-merge, so the `_vfscommon.vfs` copy never reads as an
override; shared across a kit definition's targets). Record format and skip
semantics: bin/AGENTS.md "Kit resource record sidecar + embedded icon".
- `_vfscommon.vfs/` is an auto-generated merge of common libraries; manually editing it will be overwritten. - `_vfscommon.vfs/` is an auto-generated merge of common libraries; manually editing it will be overwritten.
- `_config/punk_main.tcl` accepts an optional package_mode argument before the subcommand. Valid modes are `dev`, `os`, `internal`, and `src`, dash-delimited in priority order (e.g `src-internal`). `internal` is always appended if omitted. An optional `proj:` prefix (G-033, e.g `proj:internal-src`) makes `dev`/`src` resolve against the project containing the cwd (walk-up to the nearest git/fossil repo root with a punkshell-style src tree, via `::punkboot::proj_root_find`) instead of the executable's own project; discovery outcome is always reported on stderr and a failed discovery leaves dev/src unbound rather than falling back exe-relative. - `_config/punk_main.tcl` accepts an optional package_mode argument before the subcommand. Valid modes are `dev`, `os`, `internal`, and `src`, dash-delimited in priority order (e.g `src-internal`). `internal` is always appended if omitted. An optional `proj:` prefix (G-033, e.g `proj:internal-src`) makes `dev`/`src` resolve against the project containing the cwd (walk-up to the nearest git/fossil repo root with a punkshell-style src tree, via `::punkboot::proj_root_find`) instead of the executable's own project; discovery outcome is always reported on stderr and a failed discovery leaves dev/src unbound rather than falling back exe-relative.
- `_config/punk_main.tcl` captures the runtime's static/builtin packages at boot (G-058): empty-filename `info loaded` prefixes are probe-loaded in a throwaway interp (denylist `::punkboot::static_probe_denylist`, default `tk* vfs mk4tcl vlerq tdbc*` - side-effecting or composite inits) and each package a probe-load actually PROVIDES is recorded in `::punkboot::static_packages` {pkgname {version <v> prefix <p>}} with `::punkboot::static_prefixes` alongside. The boot interp and every punkshell-fabricated interp/thread (punk::lib::interp_sync_package_paths / snapshot_package_paths, repl codethread, shellthread workers) seed `package ifneeded <name> <ver> {load {} <prefix>}` from it, and punk::packagepreference resolves static-vs-bundled version-aware. Composite statics whose script layer lived in the runtime's own (replaced) zipfs provide nothing under the probe and are correctly left to bundled copies. - `_config/punk_main.tcl` captures the runtime's static/builtin packages at boot (G-058): empty-filename `info loaded` prefixes are probe-loaded in a throwaway interp (denylist `::punkboot::static_probe_denylist`, default `tk* vfs mk4tcl vlerq tdbc*` - side-effecting or composite inits) and each package a probe-load actually PROVIDES is recorded in `::punkboot::static_packages` {pkgname {version <v> prefix <p>}} with `::punkboot::static_prefixes` alongside. The boot interp and every punkshell-fabricated interp/thread (punk::lib::interp_sync_package_paths / snapshot_package_paths, repl codethread, shellthread workers) seed `package ifneeded <name> <ver> {load {} <prefix>}` from it, and punk::packagepreference resolves static-vs-bundled version-aware. Composite statics whose script layer lived in the runtime's own (replaced) zipfs provide nothing under the probe and are correctly left to bundled copies.

Loading…
Cancel
Save