- **Kit anatomy.** Each `src/vfs/*.vfs` folder is a runtime payload; `src/runtime/mapvfs.toml` (G-024, tomlish-parsed; deprecated `mapvfs.config` line format still readable) maps payload folders to platform runtimes under `bin/runtime/<platform>/` as named kit outputs, with named groups and generative version-named schemes; an optional sibling `src/vfs/<name>.vfs.toml` declares payload packages materialized INTO the folder with drop-in-wins precedence (G-115 - spec: `src/vfs/README.md`); `src/vfs/_vfscommon.vfs/` is a generated merge of common libraries (never hand-edited); `src/vfs/_config/` holds the entry scripts. Sources: `src/vfs/AGENTS.md`, `src/runtime/AGENTS.md`.
- **Entry point.**`src/vfs/_config/punk_main.tcl`. An optional first argument is a dash-delimited package mode composed of tokens from `dev`, `os`, `src`, `internal` (`internal` is always appended when absent), optionally scoped with the `proj:` prefix (G-033: `dev`/`src` resolve against the project containing the cwd - walk-up to the nearest git/fossil repo root with a punkshell-style src tree - instead of the executable's own project; discovery is always reported, never a silent rebind). The next argument is the subcommand: `shell`, `script`, `punk`, `tclsh`, `shellspy`. Any other first argument is treated as a script invocation; no arguments at all means interactive shell. Subcommands map to app packages under `src/lib/` (`app-punkshell`, `app-punkscript`, `app-repl`, `app-shellspy`).
- **Package modes pick module provenance.**`internal` uses module snapshots baked into the kit at bake time; `dev` loads minted outputs from repo-root `modules/` and `lib/`; `src` loads the unbuilt working tree (`src/modules`, `src/lib`, `src/bootsupport`, `src/vendormodules`) with `package prefer latest` so magic-version dev modules (`999999.0a1.0`) beat stamped snapshots. `src` mode is the standard way to verify working-tree changes without a rebuild. Source: `bin/AGENTS.md` "Launch package modes".
- **Entry point.**`src/vfs/_config/punk_main.tcl`. An optional first argument is a dash-delimited package mode composed of tokens from `minted`, `os`, `src`, `internal` (`internal` is always appended when absent; `minted` was named `dev` pre-0.43.0), optionally scoped with the `proj:` prefix (G-033: `minted`/`src` resolve against the project containing the cwd - walk-up to the nearest git/fossil repo root with a punkshell-style src tree - instead of the executable's own project; discovery is always reported, never a silent rebind). The next argument is the subcommand: `shell`, `script`, `punk`, `tclsh`, `shellspy`. Any other first argument is treated as a script invocation; no arguments at all means interactive shell. Subcommands map to app packages under `src/lib/` (`app-punkshell`, `app-punkscript`, `app-repl`, `app-shellspy`).
- **Package modes pick module provenance.**`internal` uses module snapshots baked into the kit at bake time; `minted` loads the mint output trees at repo-root `modules/` and `lib/`; `src` loads the unbuilt working tree (`src/modules`, `src/lib`, `src/bootsupport`, `src/vendormodules`) with `package prefer latest` so magic-version dev modules (`999999.0a1.0`) beat stamped snapshots. `src` mode is the standard way to verify working-tree changes without a rebuild. Source: `bin/AGENTS.md` "Launch package modes".
- **Payload mount derivation (G-129, achieved).** The boot keys zipfs presence on `tcl::zipfs::mount` and derives where the executable's attached archive actually mounted from the mount table itself (the entry whose archive file is the executable; fallback: the mount containing the boot script) instead of assuming `tcl::zipfs::root` + `//zipfs:/app`. Modern runtimes still answer `//zipfs:/app`; the androwish/undroidwish 8.6 backport has no `root` command, mounts at the executable's own path, and boots the same payload through its `app/main.tcl` in-archive hook (`src/vfs/punk8win.vfs` carries fauxlinks for both conventions). A mounted archive the boot cannot attribute is reported on stderr rather than silently yielding no internal paths. The derivation procs stay defined post-boot (`::punkboot::zipfs_kit_mountbase`). Sources: `src/vfs/AGENTS.md`, `bin/AGENTS.md` "Kit-wrappable runtime requirements", `src/tests/shell/testsuites/punkexe/kitmountpoint.test`.
- **Static package capture (G-058, achieved).** Boot probe-loads the runtime's statically linked packages in a throwaway interp and records what each provides; every interp the shell fabricates (boot, codethread, shellthread workers) seeds `package ifneeded <name> <ver> {load {} <prefix>}` from that record, and `punk::packagepreference` resolves static-vs-bundled version-aware. Sources: `src/vfs/AGENTS.md`, `goals/archive/G-058-static-runtime-packages.md`.
- **`script` subcommand (G-015, achieved).** The lean non-interactive path: default punk shell module/alias environment, no shellfilter stacks/transforms, honest exit codes, launch plumbing emits nothing on stdout/stderr (exec-style callers see only the script's own output). Supports `lib:<name>` scriptlib resolution. App package: `src/lib/app-punkscript/`.
@ -97,7 +97,7 @@ platform-specific difference left in examples is path separator style
### Launch package modes (built punk shells)
The first argument to a built punk shell may be a dash-delimited package mode composed of tokens from `dev`, `os`, `src`, `internal` (e.g. `punksys src`, `punk902z dev-os`), optionally scoped with the `proj:` prefix (e.g. `punk91 proj:internal-src`). `internal` is the default and is always appended when absent. A first argument that is not a valid mode list is treated as a subcommand instead (a `proj:` prefix on a non-mode string is not consumed either). Implementation: `src/vfs/_config/punk_main.tcl` (search `all_package_modes`). The full packagemode contract (block meanings, ordering, proj: examples) is the punk::args documentation at id `(script)::punkexe` (module `punk::args::moduledoc::punkexe`).
The first argument to a built punk shell may be a dash-delimited package mode composed of tokens from `minted`, `os`, `src`, `internal` (e.g. `punksys src`, `punk902z minted-os`), optionally scoped with the `proj:` prefix (e.g. `punk91 proj:internal-src`). (`minted` was named `dev` before punkshell 0.43.0 - clean rename, no alias: old kits accept only `dev`, current kits only `minted`.)`internal` is the default and is always appended when absent. A first argument that is not a valid mode list is treated as a subcommand instead (a `proj:` prefix on a non-mode string is not consumed either). Implementation: `src/vfs/_config/punk_main.tcl` (search `all_package_modes`). The full packagemode contract (block meanings, ordering, proj: examples) is the punk::args documentation at id `(script)::punkexe` (module `punk::args::moduledoc::punkexe`).
`src` mode is the one that matters for verifying working-tree changes:
@ -105,10 +105,10 @@ The first argument to a built punk shell may be a dash-delimited package mode co
- Prepends `src/modules`, `src/modules_tcl<N>`, `src/bootsupport/modules{,_tcl<N>}` and `src/vendormodules{,_tcl<N>}` to the module path, sets `package prefer latest` so dev-numbered `999999.0a1.0` source modules beat kit-stamped snapshots on unversioned `package require`, and registers `#modpod` modules from `src/modules` (startup notice: `src mode: registered N #modpod modules from .../src/modules`).
- Consequence: `punksys src` / `punk902z src` exercises current working-tree source with no kit rebuild; a plain launch (`punksys`) exercises the module snapshots baked into the kit at build time. `package present <pkg>` reporting `999999.0a1.0` (vs a release version like `0.7.1`) tells you which set a session is running - runbooks with version expectations must state the intended launch mode.
`proj:` scope (G-033, achieved - see goals/archive/G-033-proj-mode-cwd-project.md) makes `dev`/`src` resolve against the project containing the CURRENT DIRECTORY instead of the executable's own project - visitor mode for an installed/standalone punk binary exploring a project that builds no shell of its own (the project may be modules-only, e.g. tomlish):
`proj:` scope (G-033, achieved - see goals/archive/G-033-proj-mode-cwd-project.md) makes `minted`/`src` resolve against the project containing the CURRENT DIRECTORY instead of the executable's own project - visitor mode for an installed/standalone punk binary exploring a project that builds no shell of its own (the project may be modules-only, e.g. tomlish):
- Root discovery walks up from the cwd to the nearest git/fossil repo root that looks like a punkshell-style project (has `./src` plus one of `src/modules`, `src/vfs`, `src/scriptapps`, or `punkproject.toml` - a lean boot mirror of `punk::repo::is_project_root`).
- The launch always reports the detected root and effective mode precedence on stderr; when no project is found it warns and proceeds with dev/src unbound (never a silent or false rebind, no exe-relative fallback). `proj:` with no dev/src block warns that it has no effect.
- The launch always reports the detected root and effective mode precedence on stderr; when no project is found it warns and proceeds with minted/src unbound (never a silent or false rebind, no exe-relative fallback). `proj:` with no minted/src block warns that it has no effect.
- Canonical visitor invocation: `<punkexe> proj:internal-src shell` - kit copies win same-version ties, protecting the visiting shell's own infrastructure. `proj:src` is the faithful-vintage variant where the visited project's copies win ties. The project's genuinely-own code (dev-versioned or absent from the kit) loads from the project in either order.
@ -75,7 +75,7 @@ Recovery after a wrong path guess:
- **Payload/target consistency checks (G-133), both ADVISORY** - warnings are recapped `BAKE-WARNING`s and the kit still bakes and deploys (unlike the G-125 gate). (a) **Binary-arch scan**, at the same post-merge seam as the gate: every binary library (`*.dll`/`*.so`/`*.dylib`) in the merged tree is classified by header bytes (`punkboot::utils::binary_arch_classify` - PE Machine field, ELF e_machine, Mach-O incl. universal; unclassifiable content is honestly `unknown` and never warned about) against the kit's target platform. Structural and non-executing, so it runs for cross-target kits too (measured ~30-140ms per kit, avg ~93ms across the 12 assembled trees). Libraries under a platform-discriminated subdir - canonical `<os>-<cpu>` platform-dir names, the universal `macosx` folder, or a recognised vendor spelling (`win-x64` etc; the lists are namespace variables in `punkboot::utils`) - are exempt: multi-arch payloads are legitimate there. First real sweep (2026-07-27) found a true latent instance: `zint.dll` 2.13.0 in `src/vfs/punk8win.vfs/lib_tcl8/` is 32-bit (i386) and can never load in the x64 tcl8 kits (punk86/punkbi/punksys) that carry it - those bakes warn until the payload is fixed. (b) **Smoke-require probe**: a kit declaring packages in `src/runtime/mapvfs.toml` (`smokerequire` key - see `src/runtime/AGENTS.md`) has each one plain-`package require`d INSIDE the freshly built artifact via its tclsh subcommand, which exits cleanly even on runtimes whose full repl teardown is fragile. This is the only check that observes actual package RESOLUTION - the punkluck86 2026-07-27 incident class (a higher-versioned wrong-arch Thread shadowing the runtime's working copy on plain require) is invisible to structural checks because the working file exists too. Failures are recapped naming kit, package and the actual error; cross-target kits skip with a stated reason; undeclared kits run nothing new; the probe only runs when the kit actually rebakes. **What the checks do NOT guarantee:** statically linked packages, pure-tcl packages whose binary dependency lives elsewhere, and version-preference outcomes are visible only to the smoke probe - and only for the declared package set; the arch scan proves nothing about loadability beyond architecture, and an `unknown` classification is silence, not a pass. Both degrade to a NOTE when the bootsupport `punkboot::utils` snapshot is stale (same guarded require as the G-125 gate); `tclsh src/make.tcl check` reports the scan's ACTIVE/UNAVAILABLE state and the currently declared smoke-require kits.
- **Kit offset-style pin (G-134), ADVISORY** - at the same seam family, every ASSEMBLED kit image is probed with `punk::zip::archive_info` (via `punkboot::utils::kit_offsetstyle_report`, same guarded-require degradation to a NOTE; `make.tcl check` reports ACTIVE/UNAVAILABLE): a FILE-relative attached zip payload earns a recapped `BAKE-WARNING` naming the kit, because the pipeline emits ARCHIVE-relative by construction and the G-128 stamper refuses file-relative by default - a warning here means an assembly path regressed the output convention. **What the pin does NOT cover:**`plain` and `none` results (a bare zip, or no attached zip at all - the metakit kit shape, and any unreadable input) are silence, never warnings - the pin asserts the offset CONVENTION of an attached zip, not the presence of one; and it asserts only what make.tcl's own assembly paths EMIT - `punk::zip::mkzip -offsettype file` (and modpod's equivalent) remain available for deliberate manual creation of file-relative artifacts, and file-relative INPUT artifacts remain tolerated by the G-124 reader and normalized by any re-bake.
- Kit bakes consume the punk-runtime WORKING COPIES under `bin/runtime/<platform>/`: `make.tcl bake`/`bakehouse` emit a `BAKE-WARNING:` (recapped at end of run) when a wrapped runtime's beside-toml revision is older than an `-r<N>` artifact present in the same folder - the forgot-to-switch-back guard for deliberate `punk-runtime use <old-rN>` testing excursions. Heed it before trusting freshly baked family kits; `bin/punk-runtime.cmd use <artifact-r<N>>` (`.exe` suffix optional) re-materializes the working copy.
- `tclsh src/make.tcl bakelist ?kitname|@group ...?` (G-121/G-024) reports the kit outputs configured in `src/runtime/mapvfs.toml`: kit name, kit type, runtime (with presence in the runtime store), vfs folder, and the deployed state of `bin/<kit>` vs the `src/_bake` build product (`current|stale|absent|nobake`), with anomalies (`runtime=missing`, `vfs=missing`, `rtrev=r<cur><r<max>` materialization staleness), the cross-target marker `target=<platform>`, groups (`group=<name>`), full-bake exclusion (`default=no`) and scheme roles (`scheme=versioned|dev|release`) in a trailing notes column. A nonexistent store tier is flagged loudly per tier actually referenced (header `(FOLDER MISSING)` for the default tier + stderr derivation; bake's no-runtimes exit self-diagnoses the same way). Name/@group arguments filter the report and add a per-kit detail block (resolved store tier, target and provenance of the target, config entry, group, paths/sizes/mtimes). `make.tcl bake ?kitname|@group ...?` bakes and deploys only the named kits - other kits' `_build`/`bin` artifacts and punkcheck records are untouched and the vfslibs phase narrows to the named kits' vfs folders; flags go before kit names (`make.tcl bake -confirm 0 punk91`). Kitname arguments are DECLARED restricted choices (2026-08-02, declaration-authoritative per the G-143 arc): an unknown name is rejected at dispatch with the punk::args choice error (before any build; the choices list the configured names + `@groups`), unambiguous prefixes resolve to canonical names, and the dry-run help mirrors the verdict. The handlers' own validation remains the backstop where the declarations cannot gate: `PUNKBOOT_PLAIN=1` degraded mode, and a definition-time mapping-read failure (the choices clause is then omitted). Bare `bake` processes all configured kits except `bake_default=false` entries; a `versioned`-scheme release output (plain `punk<gen>` name) is created when absent and otherwise skipped - a normal bake never overwrites it (the explicit release step is G-023's). Both surfaces consume the shared parsed-mapping helpers (`::punkboot::lib::mapvfs_*`) rather than the file format (G-024: toml reader canonical, deprecated `mapvfs.config` line reader retained as fallback; `PUNK_MAPVFS_CONFIG` env points at an alternate config for characterization), and all mapping consumers - the definition-time choices and every handler - share one memoized read per invocation (`mapvfs_model`; success cached, a throwing parse diagnoses fresh per caller). Piped characterization: `src/tests/shell/testsuites/punkexe/maketclbakelist.test`.
- `tclsh src/make.tcl bakelist ?kitname|@group ...?` (G-121/G-024) reports the kit outputs configured in `src/runtime/mapvfs.toml`: kit name, kit type, runtime (with presence in the runtime store), vfs folder, and the deployed state of `bin/<kit>` vs the `src/_bake` build product (`current|stale|absent|nobake`), with anomalies (`runtime=missing`, `vfs=missing`, `rtrev=r<cur><r<max>` materialization staleness), the cross-target marker `target=<platform>`, groups (`group=<name>`), full-bake exclusion (`default=no`) and scheme roles (`scheme=versioned|dev|release`) in a trailing notes column. A nonexistent store tier is flagged loudly per tier actually referenced (header `(FOLDER MISSING)` for the default tier + stderr derivation; bake's no-runtimes exit self-diagnoses the same way). Name/@group arguments filter the report and add a per-kit detail block (resolved store tier, target and provenance of the target, config entry, group, paths/sizes/mtimes). `make.tcl bake ?kitname|@group ...?` bakes and deploys only the named kits - other kits' `_bake`/`bin` artifacts and punkcheck records are untouched and the vfslibs phase narrows to the named kits' vfs folders; flags go before kit names (`make.tcl bake -confirm 0 punk91`). Kitname arguments are DECLARED restricted choices (2026-08-02, declaration-authoritative per the G-143 arc): an unknown name is rejected at dispatch with the punk::args choice error (before any build; the choices list the configured names + `@groups`), unambiguous prefixes resolve to canonical names, and the dry-run help mirrors the verdict. The handlers' own validation remains the backstop where the declarations cannot gate: `PUNKBOOT_PLAIN=1` degraded mode, and a definition-time mapping-read failure (the choices clause is then omitted). Bare `bake` processes all configured kits except `bake_default=false` entries; a `versioned`-scheme release output (plain `punk<gen>` name) is created when absent and otherwise skipped - a normal bake never overwrites it (the explicit release step is G-023's). Both surfaces consume the shared parsed-mapping helpers (`::punkboot::lib::mapvfs_*`) rather than the file format (G-024: toml reader canonical, deprecated `mapvfs.config` line reader retained as fallback; `PUNK_MAPVFS_CONFIG` env points at an alternate config for characterization), and all mapping consumers - the definition-time choices and every handler - share one memoized read per invocation (`mapvfs_model`; success cached, a throwing parse diagnoses fresh per caller). Piped characterization: `src/tests/shell/testsuites/punkexe/maketclbakelist.test`.
- **Host vs target platform (G-122).** Everything a bake EMITS is keyed by the artifact's TARGET platform, never by the driving tclsh's personality: the `bin/runtime/<tier>` store the runtime is read from, `.exe` suffixing of runtime files and kit outputs, the presence checks behind `runtime=missing`, and whether the pre-deploy process sweep uses `tasklist`/`taskkill` or `ps`/`kill`. Host semantics - copy commands, path handling, filesystem case rules, prompts - stay keyed to the host. The default target is the host's own platform canon, EXCEPT a cygwin-family host (an msys2/cygwin-runtime tclsh, which reports `tcl_platform(platform)``unix` on windows and canonizes as `msys-x86_64`/`cygwin-x86_64`), which targets `win32-x86_64`: such a host now drives the identical kit set, names and store addressing as a native tclsh. `tclsh src/make.tcl check` prints the derivation on one `platform (G-122): host=... target=... store=... exe-suffix=... process-tooling=...` line. A mapvfs entry may declare its own target platform (`target` key - see `src/runtime/AGENTS.md`), which is then read from that platform's tier, named with that platform's executable convention, and skipped by the process sweep (its processes are not visible to this host). Traps this closes, all field-verified 2026-07-26: msys `ps` cannot see a natively-launched kit (only `tasklist` can), and msys2 rewrites arguments that look like absolute posix paths when spawning a native windows program - so `taskkill /PID <n>` arrived as `taskkill C:/<msysroot>/PID <n>`; native-windows command lines therefore go through `::punkboot::exec_nativeargs` (sets `MSYS2_ARG_CONV_EXCL=*`, inert elsewhere). Also note a cygwin-family tclsh is a POSIX Tcl: name the script the way that shell spells paths (`tclsh /c/repo/.../src/make.tcl`, not `C:/repo/...`, which it resolves relative to the cwd) - make.tcl diagnoses the windows-spelling case. Piped characterization: `src/tests/shell/testsuites/punkexe/maketclplatform.test` (the cygwin-host tests self-gate on finding and probing a real msys/cygwin tclsh; `PUNK_MSYS_TCLSH` names one explicitly).
- **Target-keyed kit OUTPUT locations (G-127) - the output half of the G-122 split.** A kit for the host's default target builds to `src/_bake/<kit>` and deploys to `bin/<kit>` exactly as always; any other target's kit builds under `src/_bake/kits/<platform>/` and deploys under `bin/kits/<platform>/` (per-tier `.punkcheck` ledger; the merged `.vfs` image, resource sidecar, arch scan, offset probe, smoke probe and process-sweep guards all follow the per-kit location). Same-named kits for different targets coexist - the artifact path is a pure function of (name, target) and `.exe` suffixing follows the target - so separate selective bakes can never overwrite each other's cross-target artifacts; only a same-name same-TARGET duplicate keeps the `<name>_<runtime>` disambiguation. A kit NAME matching several targets' entries selects all of them (bakelist and selective bake). Per-.vfs payload declarations gain the same axis: a `[payload.*]` source containing `%platform%` materializes once per CONSUMING kit target into `_targets/<platform>/` staging inside the `.vfs` folder (VCS-ignored), and each kit's merged image receives only its own target's subtree upstream of the arch scan and G-125 gate (`src/vfs/README.md` "Per-platform entries"). Characterization: `src/tests/shell/testsuites/punkexe/maketclkitlocations.test`; output-tier contract for consumers: `bin/AGENTS.md` "Cross-target kit outputs".
- Zip-type kit assembly does not require zipfs in the driving tcl (G-122): with `tcl::zipfs::mkimg` present it is used as before, otherwise the image is assembled by concatenation (raw-runtime split + `punk::zip::mkzip` + append, the same `::punkboot::assemble_zipcat_image` helper the `zipcat` kit type uses). Both mount identically - tcl zipfs reads the archive with archive-start-relative offsets.
#0.2.0 - package_mode 'dev' renamed 'minted' (clean break, no alias - stage-true vocabulary follow-on to G-155): mode docs updated; the built-output mode now names what it consumes (mint output trees)
@ -23,13 +23,13 @@ VFS (Virtual File System) folders define the runtime payloads that get wrapped i
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.
- `_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 `minted`, `os`, `internal`, and `src`, dash-delimited in priority order (e.g `src-internal`; `minted` was named `dev` pre-0.43.0, clean rename with no alias). An optional `proj:` prefix (G-033, e.g `proj:internal-src`) makes `minted`/`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 minted/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.
- `src` mode loads unbuilt modules and libraries from the project's `src/` tree (`src/modules`, `src/lib`, `src/bootsupport`, `src/vendormodules`) instead of built output. It also runs an inline `#modpod` package-ifneeded scanner (using Tcl builtins only, since no punk modules are loaded at boot time) and sets `package prefer latest` so `999999.0a1.0` dev modules are preferred over stable bootsupport/vendored copies.
- `_config/punk_main.tcl` and `_config/project_main.tcl` derive the kit's payload location from the runtime's own zipfs mount table (G-129): zipfs presence keys on `tcl::zipfs::mount` (not `tcl::zipfs::root`, which the androwish/undroidwish 8.6 backport lacks), the mount base is the table entry whose archive file is `[info nameofexecutable]` (fallback: the mount containing the boot script), `//zipfs:/app` stays the expected modern answer rather than a compiled-in assumption, and a mounted archive that cannot be attributed to the executable is reported on stderr. The derivation lives in `::punkboot` procs (`zipfs_kit_mountbase`, `zipfs_mount_pairs`, `path_within`) that remain defined after boot for probing and tests. Both files carry identical copies of this logic (G-031 is the planned consolidation). Characterization: `src/tests/shell/testsuites/punkexe/kitmountpoint.test`.
- `punk8win.vfs` carries TWO startup-script fauxlinks resolving to `_config/punk_main.tcl`: root `main.tcl` (modern zipfs and metakit convention) and `app/main.tcl` (the undroidwish family sources `app/main.tcl` INSIDE the attached archive; the file is inert in kits whose runtime does not look for it). Fauxlink targets are link-location-relative (symlink semantics): `make.tcl`'s `merge_over` resolves them against the link file's own directory, which is indistinguishable from the old vfs-root-relative resolution for root-level links.
- `punk8min.vfs` / `punk9min.vfs` are MINIMAL payloads for the win32-ix86 verification kits (punkluck86 / punk91ix86 in `src/runtime/mapvfs.toml`, group `verify-ix86`): both startup fauxlinks plus directory fauxlinks to MULTI-ARCH binary packages only - packages whose own tree carries a `win32-ix86` platform subdir (iocp-2.0.2 for both majors, twapi-5.0b1 for tcl8), linked from their existing homes in sibling `.vfs` folders so no binary is duplicated in VCS. Everything pure-tcl arrives via the `_vfscommon.vfs` overlay (which deliberately contains no dlls). Composition rule: an x64-only binary package must NOT be added to these payloads - a higher-versioned wrong-arch copy silently shadows a runtime's own working 32-bit package on plain `package require` (measured 2026-07-27: payload Thread 2.8.12 x64 beat the LUCK runtime's 2.8.5 and broke the repl), and wrong-arch-only packages surface as "couldn't load from current filesystem" at require time.
- `dev` mode loads built output from `<projectroot>/modules` and `<projectroot>/lib`; `src` mode loads unbuilt source from `<projectroot>/src/modules` etc. Use `src-dev-internal` to combine both with src priority.
- `minted` mode loads the mint output trees from `<projectroot>/modules` and `<projectroot>/lib`; `src` mode loads unbuilt source from `<projectroot>/src/modules` etc. Use `src-minted-internal` to combine both with src priority.