diff --git a/.fossil-settings/ignore-glob b/.fossil-settings/ignore-glob index a89e91cf..e4aabfd0 100644 --- a/.fossil-settings/ignore-glob +++ b/.fossil-settings/ignore-glob @@ -32,6 +32,11 @@ _aside */_aside _build */_build +#G-155 stage workdirs (see .gitignore): _mint module staging + _bake kit assembly +_mint +*/_mint +_bake +*/_bake scratch* */scratch* diff --git a/.gitignore b/.gitignore index 79773aaa..c9157eed 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,10 @@ /logs/ **/_aside/ **/_build/ +#G-155 stage workdirs: src/_bake (kit assembly) + per-srcdir _mint (module staging); +#**/_build/ stays for src/buildsuites/_build (true compile area) and stale checkouts +**/_mint/ +**/_bake/ scratch* #Built documentation diff --git a/AGENTS.md b/AGENTS.md index b0800d61..75a68c10 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -93,7 +93,7 @@ Default section order: When the user requests a durable behavior change, record it here or in the relevant child AGENTS.md - LF line endings are strongly preferred for all files in this repository. Converting a CRLF text file to LF when an edit touches it is correct and welcome - do not preserve CRLF for diff-minimisation. Preserve existing line endings only for files with deliberately mixed/CRLF endings (e.g. line-ending round-trip test data) or when explicitly instructed for a file. -- If the active editor is on a source-derived snapshot, bootstrap copy, or build output path such as `src/bootsupport/`, root `modules/`, root `lib/`, `modules_tcl8/`, `modules_tcl9/`, `lib_tcl8/`, or `lib_tcl9/`, confirm the intended target before editing unless the user explicitly named that path. +- If the active editor is on a source-derived snapshot, bootstrap copy, or generated output path such as `src/bootsupport/`, root `modules/`, root `lib/`, `modules_tcl8/`, `modules_tcl9/`, `lib_tcl8/`, or `lib_tcl9/`, confirm the intended target before editing unless the user explicitly named that path. - cmd.exe PATH truncation (this machine, and any Windows machine with a heavily populated PATH): cmd.exe truncates a long PATH, so a tool that resolves fine in PowerShell may be "not found" when invoked via `cmd.exe /c`. Use absolute executable paths inside any `cmd /c` command line, and prefer PowerShell-native invocation unless a console host is specifically required (e.g. hidden-console test harnesses). If a tool is missing only under cmd.exe, suspect truncation before absence. - Windows paths under POSIX shells (WSL, msys/git-bash): a `C:/...` path passed unconverted to a POSIX file command (`mkdir -p`, `cp`, output redirects) is a RELATIVE path - it silently creates a stray directory tree in the cwd whose first component is literally named `C:` (the NTFS-illegal `:` is stored as private-use character U+F03A, so it renders as `C` plus an odd dot/glyph in Explorer, and while the tree contains only empty directories it is invisible to git and fossil). Translate at the boundary (`wslpath` for WSL, `cygpath` for msys - msys auto-conversion does NOT cover paths inside quoted command strings or when MSYS_NO_PATHCONV/MSYS2_ARG_CONV_EXCL is set), and after WSL/msys-driven work glance at the repo root for a stray `C*` entry. (Origin: G-140 WSL smokes leaked an empty temp-dir skeleton into the repo root, found and removed 2026-07-31.) - Agent-authored text is plain ASCII by default: no em/en dashes, curly quotes, arrow or ellipsis characters, or other typographic Unicode - use ASCII equivalents (" - ", straight quotes, "->", "..."). The rule governs elements the agent generates, with extra force for outward-bound artifacts (ticket drafts, bug reports, emails, commit messages - anything likely to be pasted into an external system), which are verified before handover (e.g. grep for `[^\x00-\x7F]`). The exceptions are illustrative, not a closed list: non-ASCII subject matter (encoding/Unicode/ANSI-art test data, or documentation demonstrating such behaviour), verbatim quotes of existing material, and explicit user request are the common cases, but any good reason qualifies - state the reason when deviating. Content the agent did not author is outside the rule: existing files are never bulk-retrofitted, and while checking non-authored content (e.g. files being committed on the user's behalf) is fine, non-ASCII there is the author's prerogative - if unsure whether it is intentional, stop and ask rather than fix or block. @@ -145,13 +145,13 @@ The punkshell project version is tracked in `punkproject.toml` (`[project] versi An agent must bump the `punkproject.toml` version as part of its DOX closeout pass whenever its change ships user-visible shell behaviour. This is change-driven, not release-driven — the version stays honest between releases. -- **Patch** — bug fixes, internal refactors, doc-only updates that ship in a build without changing user-facing shell behaviour. +- **Patch** — bug fixes, internal refactors, doc-only updates that ship in baked kits without changing user-facing shell behaviour. - **Minor** — new shell commands, new launchers, new default modules visible at the REPL, backward-compatible behaviour additions. - **Major** — removed commands, changed default behaviour, changed launch invocation, breaking changes to the shell's user-facing contract. -Changes confined to tests, build tooling internals, or non-shipped surfaces do not require a bump. When in doubt, bump patch. +Changes confined to tests, make tooling internals, or non-shipped surfaces do not require a bump. When in doubt, bump patch. -The `make.tcl` command interface is part of the product surface: new subcommands, changed subcommand behaviour, or removed subcommands warrant at least a patch bump. Internal refactors of an existing subcommand's implementation that leave its interface and output unchanged stay exempt as build tooling internals. +The `make.tcl` command interface is part of the product surface: new subcommands, changed subcommand behaviour, or removed subcommands warrant at least a patch bump. Internal refactors of an existing subcommand's implementation that leave its interface and output unchanged stay exempt as make tooling internals. ### Changelog @@ -171,12 +171,12 @@ The project version is fully independent of module versions. A module bump (even ## Child DOX Index -- `src/` — Source tree root; editable source code, build scripts, tests, VFS payloads, vendor deps, docs (see src/AGENTS.md) +- `src/` — Source tree root; editable source code, make.tcl tooling, tests, VFS payloads, vendor deps, docs (see src/AGENTS.md) - `src/modules/` — Main editable module source (see src/modules/AGENTS.md) - `src/modules/punk/` — Core punk namespace modules (see src/modules/punk/AGENTS.md) - `src/modules/test/` — Installed-module test packages (see src/modules/test/AGENTS.md) - `src/modules/opunk/` — Alternative punk namespace, voo-based classes (see src/modules/opunk/AGENTS.md) - - `src/modules/punkcheck/` — Build/check system + - `src/modules/punkcheck/` — Install/provenance-check system - `src/modules_tcl8/` — Tcl 8 specific modules (see src/modules_tcl8/AGENTS.md) - `src/modules_tcl9/` — Tcl 9 specific modules (see src/modules_tcl9/AGENTS.md) - `src/lib/` — Editable library source (see src/lib/AGENTS.md) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 54c661e5..e33dec02 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -18,7 +18,7 @@ Rules that keep it useful instead of rotten: ## The ten-thousand-foot view -Punkshell is an alternative Tcl shell distributed as self-contained executables ("kits"): a zipfs/metakit-aware Tcl runtime wrapped with a virtual filesystem (VFS) payload carrying the punk module set. A kit boots through a single entry script, which selects a package mode (which module sources to trust) and a subcommand (which application to run: interactive shell, non-interactive script runner, stock tclsh emulation, and others). The interactive shell is a REPL in the main interp that evaluates user code in a separate code thread and talks to the terminal through a two-layer console abstraction. Everything is built, tested and released by a Tcl-driven build system (`src/make.tcl`) with file-level provenance tracking (`punkcheck`). +Punkshell is an alternative Tcl shell distributed as self-contained executables ("kits"): a zipfs/metakit-aware Tcl runtime wrapped with a virtual filesystem (VFS) payload carrying the punk module set. A kit boots through a single entry script, which selects a package mode (which module sources to trust) and a subcommand (which application to run: interactive shell, non-interactive script runner, stock tclsh emulation, and others). The interactive shell is a REPL in the main interp that evaluates user code in a separate code thread and talks to the terminal through a two-layer console abstraction. Everything is minted, baked, tested and released by a Tcl-driven make system (`src/make.tcl`) with file-level provenance tracking (`punkcheck`). ``` bin/.exe = Tcl runtime (zipfs/metakit) + .vfs payload @@ -43,7 +43,7 @@ app package from src/lib/ (app-punkshell, app-punkscript, app-repl, app-shellsp - **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//` as named kit outputs, with named groups and generative version-named schemes; an optional sibling `src/vfs/.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 build time; `dev` loads build 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". +- **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". - **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 {load {} }` 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:` scriptlib resolution. App package: `src/lib/app-punkscript/`. @@ -80,23 +80,23 @@ Two layers with a deliberate dependency direction (the class never depends on th - **Editable modules** live in `src/modules/` (+ `src/modules_tcl8/`, `src/modules_tcl9/` siblings); filenames carry the magic dev version `999999.0a1.0` with the real semver in a `-buildversion.txt` sidecar, and namespaces mirror directory layout (`punk/ansi/` = `punk::ansi`). `punk::libunknown` is the manually-versioned exception. Source: `src/modules/AGENTS.md`. - **`punk::args` is both parser and documentation system.** `PUNKARGS`/`argdoc` blocks travel with each proc and power inline usage tables (`i ` at the repl); even manually-parsing procs carry documentation-only definitions. Much of the goals-era work has been hardening this system - see the `punkargs` entries across `GOALS.md` and `GOALS-archive.md`. -- **Discovery and modpods.** `punk::libunknown` provides module discovery/registration beyond `tcl::tm` defaults; `#modpod-*` source directories pack into zip-based multi-file `.tm` modules at build time (src mode registers them via an inline boot scanner written in builtins). -- **Bootsupport.** `src/bootsupport/` holds snapshot copies of build-time-critical modules (manifest: `include_modules.config`), analogous to devDependencies. `make.tcl` classifies snapshot staleness for five runtime-critical packages (`punkcheck`, `punk::repo`, `punk::mix`, `punk::tdl`, `punk::args`) as abort/prompt/warn from the version delta. Source: `src/bootsupport/AGENTS.md`. +- **Discovery and modpods.** `punk::libunknown` provides module discovery/registration beyond `tcl::tm` defaults; `#modpod-*` source directories pack into zip-based multi-file `.tm` modules at mint time (src mode registers them via an inline boot scanner written in builtins). +- **Bootsupport.** `src/bootsupport/` holds snapshot copies of make-critical modules (manifest: `include_modules.config`), analogous to devDependencies. `make.tcl` classifies snapshot staleness for five runtime-critical packages (`punkcheck`, `punk::repo`, `punk::mix`, `punk::tdl`, `punk::args`) as abort/prompt/warn from the version delta. Source: `src/bootsupport/AGENTS.md`. - **opunk layer.** `src/modules/opunk/` explores `voo`-based value-OO reimplementations (objects as plain Tcl values); the `punk::*` modules remain the production implementations. - **Vendored code.** Third-party packages live in `src/vendormodules/` and `src/vendorlib/` (+ `_tcl8`/`_tcl9` siblings), refreshed by `make.tcl vendorupdate` from config; never hand-edited (enforcement policy is proposed as G-026). -## Build, provenance and kits +## Mint, bake, provenance and kits -- **`src/make.tcl` is the single build entry.** Key subcommands: `modules`/`libs`/`packages` (repo-root build outputs), `vfscommonupdate` (regenerate `_vfscommon.vfs`), `bake` (kit assembly into `bin/`; optional kit names or `@group` selectors confine the run to those kits - G-121/G-024; `bake_default=false` entries build only when selected), `bakelist` (report the configured kit matrix with runtime/vfs presence, deployed state, groups and scheme roles), `vfslibs` (materialize the per-.vfs payload declarations - G-115), `bin`, `bakehouse` (packages + bake for a clean checkout - G-112 rename, achieved; the transitional `project`/`vfs` aliases were removed 2026-08-01), `bootsupport` (snapshot refresh), `vendorupdate`, `check`, `workflow`, `projectversion`. Dispatch and help dogfood `punk::args` (G-030, achieved) and degrade to plain scan/help when bootsupport `punk::args` is stale (`PUNKBOOT_PLAIN=1` forces the degraded mode). Source: `src/AGENTS.md`. +- **`src/make.tcl` is the single make entry.** Stage verbs are strict (TERMINOLOGY block in `make.tcl workflow` - G-155): build = compile (buildsuites/tool), mint = stamp/pack modules from src, promote = the gates, bake = kit assembly. Key subcommands: `modules`/`libs`/`packages` (mint - repo-root output trees), `vfscommonupdate` (regenerate `_vfscommon.vfs`), `bake` (kit assembly into `bin/`; optional kit names or `@group` selectors confine the run to those kits - G-121/G-024; `bake_default=false` entries bake only when selected), `bakelist` (report the configured kit matrix with runtime/vfs presence, deployed state, groups and scheme roles), `vfslibs` (materialize the per-.vfs payload declarations - G-115), `bin`, `bakehouse` (packages + bake for a clean checkout - G-112 rename, achieved; the transitional `project`/`vfs` aliases were removed 2026-08-01), `bootsupport` (snapshot refresh), `vendorupdate`, `check`, `workflow`, `projectversion`. Dispatch and help dogfood `punk::args` (G-030, achieved) and degrade to plain scan/help when bootsupport `punk::args` is stale (`PUNKBOOT_PLAIN=1` forces the degraded mode). Source: `src/AGENTS.md`. - **Host vs target platform (G-122).** The kit surfaces separate what the driving tclsh IS from what a bake is FOR. Target-keyed: the `bin/runtime/` store a runtime is read from, `.exe` suffixing of runtimes and kit outputs, presence checks, and the pre-deploy process sweep's tooling (`tasklist`/`taskkill` vs `ps`/`kill`, skipped when the target's processes cannot exist on this host). Host-keyed: copy commands, path handling, filesystem case rules, prompts. The default target is the host canon except for cygwin-family hosts (msys2/cygwin-runtime tclsh - `tcl_platform(platform)` `unix` on windows), which target `win32-x86_64`; a `mapvfs.toml` entry may declare its own target and is then addressed in that platform's tier. `make.tcl check` prints the derivation. Zip-type kits assemble without zipfs in the driving tcl (raw-runtime split + `punk::zip::mkzip` + concatenation), and since G-124 they EXTRACT without it too: `punk::zip` reads a zip - plain, or attached to an executable under either offset convention - with stock Tcl only, so a bake needs neither zipfs nor tcllib to carry a runtime's `tcl_library` into the kit. Sources: `src/AGENTS.md`, `src/runtime/AGENTS.md`, `src/modules/punk/platform-999999.0a1.0.tm`, `src/modules/punk/zip-999999.0a1.0.tm`. - **punkcheck** records every install/delete as events in per-folder `.punkcheck` directories - the basis for skip/copy change detection, superseded-module pruning and provenance. Single OO record lifecycle (G-094, achieved) with atomic saves and advisory event-scoped locking for concurrent writers (G-095, achieved). -- **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.** Producing commands (mint/promote/bake) 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/` 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 + G-134), all 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 `-` names, vendor spellings like `win-x64`) earn recapped `BUILD-WARNING`s. After assembly, a kit declaring smoke-require packages (`mapvfs.toml` `smokerequire` key) 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. The assembled image is also probed for its zip offset convention (G-134, `punkboot::utils::kit_offsetstyle_report` over `punk::zip::archive_info`): a FILE-relative attached payload warns (the pipeline emits archive-relative; the G-128 stamper refuses file-relative by default), no-zip/plain results stay silent. Same guarded-require degradation; `make.tcl check` reports all three. None 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 `.resources.toml` sidecar (deployed beside `bin/`) 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`. +- **Payload/target consistency checks (G-133 + G-134), all 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 `-` names, vendor spellings like `win-x64`) earn recapped `BAKE-WARNING`s. After assembly, a kit declaring smoke-require packages (`mapvfs.toml` `smokerequire` key) 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. The assembled image is also probed for its zip offset convention (G-134, `punkboot::utils::kit_offsetstyle_report` over `punk::zip::archive_info`): a FILE-relative attached payload warns (the pipeline emits archive-relative; the G-128 stamper refuses file-relative by default), no-zip/plain results stay silent. Same guarded-require degradation; `make.tcl check` reports all three. None 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 produces gets a `.resources.toml` sidecar (deployed beside `bin/`) recording the bake-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 bake 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. Both suites also emit the punkbin LIBRARY tier (G-138, achieved): verified tcllib/tcllibc installs as generation-tagged immutable zips (`lib/allplatforms` + `lib/`, embedded schema-v2 class=library records, punkzip-deterministic) - the `library-artifacts` step in each recipe. The tier's `` axis includes cross-built lanes: suite_tcl90's `tcllibc-linux` step (G-140, achieved) cross-builds the critcl accelerators for linux-x86_64 via critcl driving `zig cc -target` (stubs linkage - no linux host involved), structurally ELF-gated on the build host and consumed by the punk9linux kit payload. Consumption (G-139, achieved): `make.tcl libfetch` materializes declared artifacts into the untracked `bin/packages/` tier with server-trust consent, and the PACKAGES_tcl libs phase + per-.vfs payload declarations with `source_root = "packages"` (G-115) feed the deployed `lib_tcl` trees and kit vfs payloads - the vendored tcllib trees are retired, and embedded records ride into baked kits. `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__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; VCS-config payloads stored inert as `gitignore.in` and materialized to `.gitignore` at composition - G-012) 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 release pipeline (TERMINOLOGY + mint/promote/bake), with its own update contract in `src/AGENTS.md`. This section deliberately summarises rather than copies it. ## Test harness diff --git a/README.md b/README.md index 687be0d8..934be6b5 100644 --- a/README.md +++ b/README.md @@ -11,22 +11,22 @@ Version 0.11.0 (2026-07) — this is **alpha** level software and still highly e ### Getting Started -The project uses a Tcl-based build system (`src/make.tcl`). From the project root: +The project uses a Tcl-based make system (`src/make.tcl`) with strict stage verbs - mint (stamp/package modules from src), promote (the gates), bake (assemble kits); 'build' means compiling binaries (buildsuites/tools). `tclsh src/make.tcl workflow` prints the TERMINOLOGY key and data flow. From the project root: ``` # Fetch a suitable Tcl runtime (cross-platform polyglot wrapper — runs from bash, powershell, or cmd.exe) ./bin/punk-runtime.cmd fetch -# Build modules and libraries into the project root +# Mint modules and libraries into the project root tclsh src/make.tcl packages -# Full consumer build from a clean checkout (packages + baked kit binaries) +# Full consumer run from a clean checkout (minted packages + baked kit binaries) tclsh src/make.tcl bakehouse ``` -See `src/README.md` for detailed build instructions and `bin/AGENTS.md` for the runtime manager. +See `src/README.md` for detailed make instructions and `bin/AGENTS.md` for the runtime manager. -For evaluating uncommitted source without a full build, a built executable can run directly against the source tree: +For evaluating uncommitted source without minting or baking, a built executable can run directly against the source tree: ``` src shell @@ -139,7 +139,7 @@ For evaluating uncommitted source without a full build, a built executable can r ### Documentation -- `src/README.md` — detailed build instructions +- `src/README.md` — detailed make instructions - `CHANGELOG.md` — version history and recent changes - `AGENTS.md` (root) + child AGENTS.md files — contributor guidance and project structure (DOX hierarchy) - `GOALS.md` — technical goal index with per-goal detail files under `goals/` diff --git a/bin/AGENTS.md b/bin/AGENTS.md index fbffd6e5..56cf6da6 100644 --- a/bin/AGENTS.md +++ b/bin/AGENTS.md @@ -2,7 +2,7 @@ ## Purpose -Built punk shell executables (kits with the punk boot layer), assorted build/experiment tooling, and plain runtime kits under `runtime/`. Executables here are build outputs - agents do not hand-edit binaries. +Baked punk shell executables (kits with the punk boot layer), assorted tooling, and plain runtime kits under `runtime/`. Executables here are outputs of the bake and tool-build steps - agents do not hand-edit binaries. ### Generated polyglot .cmd scripts - never edit in place @@ -155,19 +155,19 @@ A `bin/` that a bake deployed has passed the G-125 boot-precondition gate ( merged vfs supplies a tcl library - a kit failing that is never deployed) and the G-133 advisory checks have run: a structural binary-arch scan of its payload (a wrong-arch `.dll`/`.so`/`.dylib` outside a platform-discriminated subdir earned a -recapped `BUILD-WARNING` - advisory, so heed the bake recap before trusting a warned +recapped `BAKE-WARNING` - advisory, so heed the bake recap before trusting a warned kit) and, when its `src/runtime/mapvfs.toml` entry declares smoke-require packages and the kit is host-runnable, a plain `package require` of each inside the built artifact via its tclsh subcommand. The assembled image was also probed for its zip offset convention (G-134, advisory): a FILE-relative attached payload earned a -recapped `BUILD-WARNING` (the pipeline emits archive-relative; the G-128 stamper +recapped `BAKE-WARNING` (the pipeline emits archive-relative; the G-128 stamper refuses file-relative by default), while kits with no attached zip (metakit shapes) probe as `none` and stay silent. What that does NOT guarantee: statically linked packages and pure-tcl packages with binary dependencies are invisible to the arch scan; package-resolution outcomes (a wrong-arch higher-versioned copy shadowing a working one) are visible only to the smoke probe and only for the declared package set; and an unclassifiable binary is silence, not a pass. A kit whose bake recap -showed no `BUILD-WARNING`s still only proves what those checks measure - not that +showed no `BAKE-WARNING`s still only proves what those checks measure - not that every payload package loads. ### Cross-target kit outputs (`bin/kits//`, G-127) @@ -176,11 +176,11 @@ Kit OUTPUT locations are keyed by each kit's TARGET platform (the mapping's `tar key - G-122's output half): - A kit for this host's own default target deploys flat to `bin/` exactly as - always (build product `src/_build/`). -- Any other target's kit deploys to `bin/kits//` (build product - `src/_build/kits//`), each tier with its own `.punkcheck` install + always (bake product `src/_bake/`). +- Any other target's kit deploys to `bin/kits//` (bake product + `src/_bake/kits//`), each tier with its own `.punkcheck` install ledger and the `.resources.toml` sidecar beside the kit as usual. `bin/kits/` - rather than `bin//` because `bin/runtime//` already means build + rather than `bin//` because `bin/runtime//` already means bake INPUTS - the two tiers sit side by side as input vs output. - Same-named kits for DIFFERENT targets therefore coexist (the artifact path is a pure function of name + target, and `.exe` suffixing follows the target); only a @@ -188,7 +188,7 @@ key - G-122's output half): - `make.tcl bakelist` marks non-default-target rows with `out=kits//` and its per-kit detail block prints the tiered paths; a kit NAME spanning several targets selects all of them (bakelist and selective bake alike). -- Everything under `bin/kits/` is a build output covered by the existing `/bin/*` +- Everything under `bin/kits/` is a bake output covered by the existing `/bin/*` ignore rules in both VCS - never commit from it. - Relocations at the 2026-07-31 switch: the linux `punkshell902` moved from `bin/punkshell902` to `bin/kits/linux-x86_64/punkshell902` (intended relocation - @@ -200,9 +200,9 @@ key - G-122's output half): ### Kit resource record sidecar + embedded icon (G-057) -Every kit a bake builds ships with a `bin/.resources.toml` text -sidecar (deployed beside the kit; the build copy sits in `src/_build/`). -It records the build-time icon choice for EVERY target, and on win32 targets +Every kit a bake produces ships with a `bin/.resources.toml` text +sidecar (deployed beside the kit; the bake copy sits in `src/_bake/`). +It records the bake-time icon choice for EVERY target, and on win32 targets baked by a capable host the same icon is embedded into the kit executable as PE RT_ICON/RT_GROUP_ICON resources (stub stamped before the payload is appended so the vfs payload is never at risk; runtime store originals are @@ -250,10 +250,10 @@ RT_VERSION stamping extends the same file. and twapi unloadable or a non-windows build host) records `unavailable` with a combined reason naming both gaps and the punkres build remedy (`make.tcl tool build punkres` - G-128). In every case the sidecar is still - written and the build completes. + written and the bake completes. - Byte-stable at unchanged input and host capability: no timestamps, fixed field order, rewritten only when bytes change. The default icon is part of - the kit's punkcheck source set, so changing it rebuilds kits. + the kit's punkcheck source set, so changing it rebakes kits. ### Runtime fetch/selection (`punk-runtime.cmd`) @@ -262,7 +262,7 @@ RT_VERSION stamping extends the same file. verification against its `sha1sums.txt` - both the powershell payload on windows and the bash payload on unix verify; a fetch whose checksum fails leaves only a `.tmp`). The `` folders are store TIERS keyed by the platform a runtime is FOR, and the -kit build reads them the same way: `src/make.tcl` picks a tier per kit from that kit's +kit bake reads them the same way: `src/make.tcl` picks a tier per kit from that kit's target platform, not from the driving tclsh's own personality (G-122 - see `src/AGENTS.md` and `src/runtime/AGENTS.md`), so a tier holding runtimes for another platform is a first-class thing to populate here. @@ -314,7 +314,7 @@ payload - `$PunkRuntimeSupportExt`/`Test-PunkRuntimeSupportName` in the ps1, because the listings are required to agree byte-for-byte; extend both and re-wrap. What a tier is expected to contain is documented for users in `bin/runtime/README.md`. Forgot-to-switch-back guard (2026-07-25): `make.tcl bake`/`bakehouse` emit a -BUILD-WARNING (recapped at end of run) when a working runtime they wrap is materialized +BAKE-WARNING (recapped at end of run) when a working runtime they wrap is materialized from an older revision than an `-r` artifact present beside it - a deliberate `use ` (e.g to exercise `list -remote` row marking) that was never switched back no longer bakes stale kits silently (see src/AGENTS.md Work Guidance). diff --git a/src/AGENTS.md b/src/AGENTS.md index a9c39bd0..0f19b236 100644 --- a/src/AGENTS.md +++ b/src/AGENTS.md @@ -2,18 +2,18 @@ ## Purpose -The source tree root contains all editable source code, build scripts, test suites, VFS payloads, vendor dependencies, and documentation. This is the primary development area. +The source tree root contains all editable source code, the make.tcl tooling, test suites, VFS payloads, vendor dependencies, and documentation. This is the primary development area. ## Ownership - The `src/` tree is where agents perform development work. -- Generated/output directories at the project root (`modules/`, `lib/`, `lib_tcl8/`, `lib_tcl9/`, `modules_tcl8/`, `modules_tcl9/`) are build targets — agents must not directly modify them. +- Generated/output directories at the project root (`modules/`, `lib/`, `lib_tcl8/`, `lib_tcl9/`, `modules_tcl8/`, `modules_tcl9/`) are mint output trees — agents must not directly modify them. - VFS payloads, runtime mappings, vendored dependencies, generated docs, and entry-point scripts have child AGENTS.md files with local ownership rules. ## Local Contracts -- `make.tcl` is the primary build entry point: `tclsh src/make.tcl `. -- The build system handles bootstrap loading, version assignment, module/library packaging, and VFS packaging. +- `make.tcl` is the primary make entry point: `tclsh src/make.tcl `. Stage verbs are strict (see the TERMINOLOGY block in `make.tcl workflow`): build = compile (buildsuites/tool only), mint = stamp/pack modules from src into the projectroot trees, promote = the bootsupport/vfscommonupdate gates, bake = kit assembly + deploy. +- make.tcl handles bootstrap loading, version stamping, module/library minting, and kit-payload packaging. - Shell launcher entry points include `tclsh src/make.tcl shell`, built launchers under the project `bin/` directory, scripts sourced from `src/scriptapps/`, and executable entry scripts under `src/vfs/_config/`. - Tcl 8.6+ is required and Tcl 9.0 is supported; gate 9.0-specific behavior behind version checks or existing `punk::lib::compat` helpers. - Primary target is Windows (`win32-x86_64`); Linux, macOS, and FreeBSD are secondary targets. @@ -59,38 +59,38 @@ Recovery after a wrong path guess: ## Work Guidance - Run `tclsh src/make.tcl packages` once after cloning to populate generated module and library assets. -- Use `tclsh src/make.tcl bakehouse` for full builds from a clean checkout (packages + bake; refuses uncommitted src by default - `-dirty-abort 0` overrides). -- Use `tclsh src/make.tcl modules` to build just the module packages. -- Use `tclsh src/make.tcl libs` to build just the library packages. -- Use `tclsh src/make.tcl packages` to build both modules and libraries. +- Use `tclsh src/make.tcl bakehouse` for full consumer runs from a clean checkout (mint + bake; refuses uncommitted src by default - `-dirty-abort 0` overrides). +- Use `tclsh src/make.tcl modules` to mint just the module packages. +- Use `tclsh src/make.tcl libs` to mint just the library packages. +- Use `tclsh src/make.tcl packages` to mint both modules and libraries. - make.tcl colour is terminal-aware (G-113): piped/redirected runs (agent harnesses, CI, log capture) automatically produce fully ESC-free output with no caller action required - an ansistrip channel transform on stdout+stderr guarantees zero ESC bytes for every emitter, including module-side ones (punkcheck summaries, punk::args tables). Interactive terminal runs keep colour (stdout tty probe via the `-winsize` channel option, Tcl 8.7+/9). Precedence: `NO_COLOR` (any value) always suppresses colour; `PUNK_FORCE_COLOR`/`FORCE_COLOR` (value other than 0/false/no/off) re-enables ANSI on piped output; otherwise the probe decides. Tcl 8.6 terminals are auto-detected without dependencies: windows consoles via the console channel's utf-16 encoding signature (`-encoding unicode` - only 8.6 console channels report it; the byte-level strip transform is never pushed onto a utf-16-class channel, which it would corrupt - per-channel push, so `> file` from an 8.6 console wraps stdout only), and unix-class hosts (linux/WSL/mac, plus msys2/cygwin-runtime tclsh builds that report platform unix on windows) via the tty channel signature (real ttys expose `-mode` etc; pipes/files lack them). The force vars remain for exotic environments. stderr follows the stdout decision; `make.tcl shell` pops the transform (repl colour is the shell's own concern). The ansistrip transform also holds split ANSI sequences across write chunks, so piped output carries no orphan sequence-fragment text ('0;1m' beside table borders etc - G-145): the transform must NOT declare the `clear` op in its supported-methods list - the Tcl core delivers clear before EVERY write op (intentional, under-documented core behaviour documented as read-side/seek-scoped), and the former clear handler's drop of the per-channel carry was the fragment source; `finalize` still drops the carry. `tclsh src/make.tcl check` reports the active policy (`colour policy (G-113): mode=...` line; modes tty|forced|nocolor|piped-plain|tcl86-plain). Pinned by `src/tests/shell/testsuites/punkexe/maketclcolour.test`. Agents no longer need to set NO_COLOR for captured runs (setting it remains harmless). - Use `tclsh src/make.tcl vendorupdate` to refresh vendormodules from config. It warns (non-fatal) for each source project whose fossil/git checkout is dirty - vendored artifacts built from a dirty tree have no committed provenance; commit in the source project to clear the warning (enforcement policy tracked by goal G-026). -- All build/promotion commands (`bakehouse`, `packages`, `modules`, `libs`, `bake`, `vfslibs`, `bin`, `bootsupport`, `vfscommonupdate`) warn similarly when this project's own `src/` has uncommitted fossil/git changes (dirt outside `src/` is ignored). Warn-only by default EXCEPT `bakehouse` (aborts by default; `-dirty-abort 0` overrides); pass `-dirty-abort` elsewhere to make the check aborting. For evaluating uncommitted source without a build, prefer ` src` / ` src shell`. The check is `punkboot::utils::vcs_dirty_warnings` (optional scope argument) loaded guardedly from bootsupport - if the snapshot is stale/missing the check degrades to a skip notice (but `-dirty-abort` then aborts rather than silently losing the requested strictness). -- Provenance warnings (dirty-src gate + vendorupdate source-project check) print with a plain column-0 `PROVENANCE-WARNING:` token (grep for it in captured build output) and are recapped at the end of the run via make.tcl's wrapped `::exit`. Interactive terminal runs get a 3-second ctrl-c grace countdown before a dirty build proceeds; piped/agent runs skip it. `tclsh src/make.tcl check` reports the current src provenance status and what the build commands would do. +- All producing commands (mint/promote/bake: `bakehouse`, `packages`, `modules`, `libs`, `bake`, `vfslibs`, `bin`, `bootsupport`, `vfscommonupdate`) warn similarly when this project's own `src/` has uncommitted fossil/git changes (dirt outside `src/` is ignored). Warn-only by default EXCEPT `bakehouse` (aborts by default; `-dirty-abort 0` overrides); pass `-dirty-abort` elsewhere to make the check aborting. For evaluating uncommitted source without minting or baking, prefer ` src` / ` src shell`. The check is `punkboot::utils::vcs_dirty_warnings` (optional scope argument) loaded guardedly from bootsupport - if the snapshot is stale/missing the check degrades to a skip notice (but `-dirty-abort` then aborts rather than silently losing the requested strictness). +- Provenance warnings (dirty-src gate + vendorupdate source-project check) print with a plain column-0 `PROVENANCE-WARNING:` token (grep for it in captured make.tcl output) and are recapped at the end of the run via make.tcl's wrapped `::exit`. Interactive terminal runs get a 3-second ctrl-c grace countdown before a dirty run proceeds; piped/agent runs skip it. `tclsh src/make.tcl check` reports the current src provenance status and what the producing commands would do. - Use `tclsh src/make.tcl vfscommonupdate` to rebuild `_vfscommon.vfs`. The REPLACE confirmation prompts on an interactive terminal; unattended/agent runs must pass `-confirm 0` (with the default `-confirm 1` and a piped/closed stdin, make.tcl aborts fast with guidance instead of reading stdin - do not pipe `y`). -- `tclsh src/make.tcl workflow` prints an embedded ASCII data-flow overview of the build/release workflow (release-ready command sequence, source→outputs folder flow, kit assembly, keyed notes). The text lives in `::punkboot::workflow_text` in `src/make.tcl` - embedded rather than a data file so it travels with the make.tcl copies seeded into generated projects. **Update contract (agents):** whenever build data flow changes - a make.tcl subcommand added/removed/repurposed, a source or output folder added or rerouted, a propagation target added, a gate (staleness/provenance/confirm) or deploy behaviour changed - update the workflow text in the same change-set. Keep it plain ASCII, max line width 100, and preserve the RELEASE SEQUENCE / DIAGRAM / KEY-NOTES / MAINTENANCE structure; verify by running `tclsh src/make.tcl workflow` (and once under `PUNKBOOT_PLAIN=1`). Adding/changing a subcommand also means: SUMMARIES + HELPTEXTS + its braced `punk::args::define` block (+ SUBGROUPS) in `::punkboot::argdoc`, `known_commands`, the plain `punkboot_gethelp` text, and a project-version bump (make.tcl interface is product surface per root AGENTS.md). Layout make.tcl copies pick the change up via the thin-layout sync step in any `make.tcl modules`/`libs`/`packages`/`bakehouse` run - do not hand-sync them. +- `tclsh src/make.tcl workflow` prints an embedded ASCII data-flow overview of the release workflow (the TERMINOLOGY stage-verb key, release-ready command sequence, source→outputs folder flow, kit assembly, keyed notes). The text lives in `::punkboot::workflow_text` in `src/make.tcl` - embedded rather than a data file so it travels with the make.tcl copies seeded into generated projects. **Update contract (agents):** whenever make.tcl data flow changes - a make.tcl subcommand added/removed/repurposed, a source or output folder added or rerouted, a propagation target added, a gate (staleness/provenance/confirm) or deploy behaviour changed - update the workflow text in the same change-set. Keep it plain ASCII, max line width 100, and preserve the TERMINOLOGY / RELEASE SEQUENCE / DIAGRAM / KEY-NOTES / MAINTENANCE structure; verify by running `tclsh src/make.tcl workflow` (and once under `PUNKBOOT_PLAIN=1`). Adding/changing a subcommand also means: SUMMARIES + HELPTEXTS + its braced `punk::args::define` block (+ SUBGROUPS) in `::punkboot::argdoc`, `known_commands`, the plain `punkboot_gethelp` text, and a project-version bump (make.tcl interface is product surface per root AGENTS.md). Layout make.tcl copies pick the change up via the thin-layout sync step in any `make.tcl modules`/`libs`/`packages`/`bakehouse` run - do not hand-sync them. - make.tcl subcommands and flags are punk::args-declared (G-030; help depth G-143, achieved): `tclsh src/make.tcl help ?subcommand? ?arg ...?` or ` ?arg ...? -help` shows tabled usage; invalid arguments produce punk::args usage errors. Bare `make.tcl help` (and `make.tcl`/`-help`) renders a rich top-level overview (2026-08-02, the `i info` style): per-subcommand cells carrying the one-line summary plus that subcommand's own auto-generated synopsis line(s) - per-form lines for the multi-form subcommands - grouped by SUBGROUPS (rich `-choicelabels` built by `::punkboot::argdoc::overview_labels` from `punk::args::synopsis` per id, hung on the separate `(script)::punkboot.overview` id so dispatch never pays the label cost; the lean `(script)::punkboot` id remains the dispatch surface). `-choicecolumns` is 1 for now - the long one-line summaries make a 2-column layout too wide without table CELL WRAPPING; revisit `-choicecolumns 2` when that lands (user decision 2026-08-02; the `## FORM` header lines are likewise deliberately dropped from the cells). tool and buildsuite are multi-form definitions (one @form per action with a literal action leader), so whole-subcommand help renders one synopsis line per action, and help accepts the subcommand's own COMMAND LINE after the subject and DRY-RUNS it through that subcommand's declaration: `make.tcl help tool build -test 0 punkzip` (equivalently that command line with `-help` appended) parses via punk::args form auto-selection and renders the build form's usage, while a line the subcommand would reject (unknown action word, option-first line, unknown flag in option position) gets the same pointed punk::args noformmatch diagnosis dispatch gives - synopsis plus per-form reasons - on stderr with exit 1, never a plain-help fallback. There is deliberately no bare-action carve-out: an action word alone is dry-run too, so a form with required values reports them via the diagnosis (`help buildsuite build` exits 1 naming the missing suitename - the error table carries the form's argument rows, so it IS the form documentation). An accepted line is confirmed with a one-line received-args report after the table (`dry-run: line accepted (form build) - action = build | -test = 0 | toolname = punkzip`); punk::args' positional model consumes flag-like words at/after the first value position as VALUES where the value arg is unconstrained (tool's toolname), and the report makes such swallows visible - value args with restricted choices (bake/bakelist kitnames as of 2026-08-02) instead reject the flag-like word at the choice gate, exactly as dispatch does. Declaration-level passthroughs (shell args, buildsuite driver args) always parse clean; numeric form indexes are deliberately not an interface. tool DISPATCH parses through its definition: unknown actions/flags are punk::args usage errors (exit 1), and the declared positional model puts options before the tool names (`make.tcl tool build -test 0 ...`, matching bake's flags-before-names convention; the historic flag-anywhere order is deliberately not accepted - a flag-shaped tool name earns a stderr hint). buildsuite keeps its passthrough driver-args contract - its forms serve help/synopsis accuracy only. The dispatch degrades to plain scan/help when the bootsupport punk::args (or its rendering stack) is stale or unavailable; `PUNKBOOT_PLAIN=1` forces the degraded mode for troubleshooting (the degraded tool handler keeps the historic manual tail parse and exit-2 surface). Piped characterization: `src/tests/shell/testsuites/punkexe/maketclhelp.test`. The `::punkboot::argdoc` definitions are braced file-style blocks using the G-045 authoring mechanisms — `-&` record continuations, tstr placeholders pulling SUMMARIES/HELPTEXTS and the shared `OPT_*` option fragments — with `-help` bodies expanding as deferred display fields so the HELPTEXTS block indentation deliberately renders as a centred Description (no `@normalize` re-basing). Synopses are the automatic punk::args bracket notation via the G-144 `@cmd -name` fallback; explicit `@form -synopsis` overrides were retired 2026-08-01 except the top-level `make.tcl ?subcommand? ?flags?` line (it states the bare-invocation/flags reality the auto render cannot) - do not reintroduce per-subcommand overrides without cause. See src/modules/AGENTS.md "punk::args definition authoring ergonomics" before editing them or authoring similar definitions. - Uncommitted `make.tcl`-generated outputs may be batched into one commit, regardless of how many `make.tcl` invocations produced them. This covers punkcheck-managed build outputs that are VCS-tracked: `src/bootsupport/`, `_vfscommon.vfs/modules` + `/lib`, declared per-kit `*.vfs/lib_tcl/` subfolders, the thin-layout sync copies (`src/project_layouts/vendor/punk//src/{make.tcl,build.tcl}` + bootsupport manifest copies + the inert `gitignore.in` payload copies refreshed from the root `.gitignore` - G-012), and the module-shipped layout payload under `src/modules/punk/mix/#modpod-templates-*/templates/project_layouts/` (G-087: synced from `src/project_layouts` - never hand-edit the modpod copy). (Root `modules/`, `lib/`, `modules_tcl/`, `lib_tcl/` are gitignored and never committed.) Each module's old→new version rename is atomic; a regeneration reflects one build-output refresh, not independent hand-edits. This is a carve-out from generic "split aggressively" commit guidance for punkcheck-managed build outputs only — it does not cover user-curated VFS content (`_config/`, per-kit `*.vfs/` outside declared `lib_tcl` subfolders, `_aside/`, `mkzipfix.vfs`, `_vfscommon.vfs/doc`), which commits separately per its own concerns. -- **Boot-precondition gate (G-125).** A bake refuses any kit whose merged `.vfs` supplies no tcl library: the kit is listed under `FAILED KITS` with a reason naming the cause, and NOTHING is written - no `src/_build/`, no deploy, and the previously deployed `bin/` is left byte-identical. This is deliberately a failure rather than a warning: the deploy step deletes the old kit before copying the new one, so the pre-gate behaviour replaced a working shell with an artifact that died at startup with `application-specific initialization failed: Cannot find a usable init.tcl`. The check is structural and non-executing (so it covers cross-target kits too): `init.tcl` in `tcl_library/`, `lib/tcl./` or `tcl./` - the third for runtimes whose archive mounts at the executable's own path rather than `//zipfs:/app`, so `[info library]` is `/tcl8.6` (the androwish/undroidwish zipfs backport for 8.6 does this) - plus one companion file a real Tcl library carries beside it (`tm.tcl`, `package.tcl`, `auto.tcl`, `clock.tcl`, `history.tcl`, `word.tcl`) or an `encoding/` directory - without that second test the `lib/BWidget1.10.1/init.tcl` every punkshell kit carries would answer for a tcl library it cannot provide. It reads the MERGED tree rather than asking whether extraction ran, so a `.vfs` that legitimately supplies its own tcl library (`src/vfs/punk8_statictwapi.vfs`, `src/vfs/punk9test.vfs`) builds and deploys unchanged. **Remedy when a kit is refused:** the usual cause is that the runtime's own payload could not be extracted - read the recapped `BUILD-WARNING` naming what was tried, then either fix extraction (a driving tclsh with no zipfs needs punk::zip >= 0.2.0 in bootsupport - see the extraction bullet above), point the kit at a runtime that carries a payload, or have the kit's `.vfs` supply a tcl library itself. The predicate is `punkboot::utils::vfs_boot_library_report` called through a guarded require, exactly as the dirty-src provenance check is: a stale or missing bootsupport snapshot degrades the gate to a `NOTE` rather than failing every kit. `tclsh src/make.tcl check` reports whether the gate is `ACTIVE` or `UNAVAILABLE`. -- **Payload/target consistency checks (G-133), both ADVISORY** - warnings are recapped `BUILD-WARNING`s and the kit still builds 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 `-` 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 rebuilds. **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 `BUILD-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//`: `make.tcl bake`/`bakehouse` emit a `BUILD-WARNING:` (recapped at end of run) when a wrapped runtime's beside-toml revision is older than an `-r` artifact present in the same folder - the forgot-to-switch-back guard for deliberate `punk-runtime use ` testing excursions. Heed it before trusting freshly baked family kits; `bin/punk-runtime.cmd use >` (`.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/` vs the `src/_build` build product (`current|stale|absent|nobuild`), with anomalies (`runtime=missing`, `vfs=missing`, `rtrev=r` materialization staleness), the cross-target marker `target=`, groups (`group=`), 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` 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`. +- **Boot-precondition gate (G-125).** A bake refuses any kit whose merged `.vfs` supplies no tcl library: the kit is listed under `FAILED KITS` with a reason naming the cause, and NOTHING is written - no `src/_bake/`, no deploy, and the previously deployed `bin/` is left byte-identical. This is deliberately a failure rather than a warning: the deploy step deletes the old kit before copying the new one, so the pre-gate behaviour replaced a working shell with an artifact that died at startup with `application-specific initialization failed: Cannot find a usable init.tcl`. The check is structural and non-executing (so it covers cross-target kits too): `init.tcl` in `tcl_library/`, `lib/tcl./` or `tcl./` - the third for runtimes whose archive mounts at the executable's own path rather than `//zipfs:/app`, so `[info library]` is `/tcl8.6` (the androwish/undroidwish zipfs backport for 8.6 does this) - plus one companion file a real Tcl library carries beside it (`tm.tcl`, `package.tcl`, `auto.tcl`, `clock.tcl`, `history.tcl`, `word.tcl`) or an `encoding/` directory - without that second test the `lib/BWidget1.10.1/init.tcl` every punkshell kit carries would answer for a tcl library it cannot provide. It reads the MERGED tree rather than asking whether extraction ran, so a `.vfs` that legitimately supplies its own tcl library (`src/vfs/punk8_statictwapi.vfs`, `src/vfs/punk9test.vfs`) bakes and deploys unchanged. **Remedy when a kit is refused:** the usual cause is that the runtime's own payload could not be extracted - read the recapped `BAKE-WARNING` naming what was tried, then either fix extraction (a driving tclsh with no zipfs needs punk::zip >= 0.2.0 in bootsupport - see the extraction bullet above), point the kit at a runtime that carries a payload, or have the kit's `.vfs` supply a tcl library itself. The predicate is `punkboot::utils::vfs_boot_library_report` called through a guarded require, exactly as the dirty-src provenance check is: a stale or missing bootsupport snapshot degrades the gate to a `NOTE` rather than failing every kit. `tclsh src/make.tcl check` reports whether the gate is `ACTIVE` or `UNAVAILABLE`. +- **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 `-` 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//`: `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` artifact present in the same folder - the forgot-to-switch-back guard for deliberate `punk-runtime use ` testing excursions. Heed it before trusting freshly baked family kits; `bin/punk-runtime.cmd use >` (`.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/` vs the `src/_bake` build product (`current|stale|absent|nobake`), with anomalies (`runtime=missing`, `vfs=missing`, `rtrev=r` materialization staleness), the cross-target marker `target=`, groups (`group=`), 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` 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/` 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 ` arrived as `taskkill C://PID `; 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/_build/` and deploys to `bin/` exactly as always; any other target's kit builds under `src/_build/kits//` and deploys under `bin/kits//` (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 `_` 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//` 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". +- **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/` and deploys to `bin/` exactly as always; any other target's kit builds under `src/_bake/kits//` and deploys under `bin/kits//` (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 `_` 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//` 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. - Neither is EXTRACTING the runtime's own attached zip (needed to carry its `tcl_library` into the kit): `punk::zip` >= 0.2.0 reads a zip with stock Tcl only - no zipfs, no vfs::zip, no tcllib (G-124, the former tcllib `zipfile::decode` dependency is gone). The zipfs-less bake path splits off the executable prefix with `punk::zip::extract_preamble` and then reads the MEMBERS from the original runtime with `punk::zip::unzip`, never from the split-off intermediate: a runtime whose zip offsets are file-relative (the historical `zipfs mkimg` convention - `tclsh90b4_piperepl.exe` in the store is one) splits into a .zip whose offsets still count from the removed prefix, which plain zip readers reject. Reading the whole file at the derived base offset makes the two offset conventions indistinguishable to callers; `punk::zip::archive_info ` reports which one a given artifact uses. Verified 2026-07-26 by baking a zip kit from msys2's `/usr/bin/tclsh8.6` (no zipfs, no vfs::zip, no tcllib) and booting the result with its `tcl_library` present. - What the RUNTIME must provide to be zip-kit-wrappable - which zipfs commands, mount conventions and startup hooks are supported - is documented in `bin/AGENTS.md` "Kit-wrappable runtime requirements (G-129)". Short form: `tcl::zipfs::mount` with pairwise no-arg output (`tcl::zipfs::root` NOT required), any attached-archive mount point (the boot derives it from the runtime's own mount table - the androwish/undroidwish 8.6 backport mounts at the executable's own path), a `main.tcl`/`app/main.tcl` startup hook, and a liftable library payload for the G-125 gate. The bake's runtime capability probe keys `has_zipfs` on `tcl::zipfs::mount` accordingly. -- Use `punk make.tcl bakehouse` or `punk902z make.tcl bakehouse` inside Punk shell when building binaries through Punk. Driving make.tcl from a built punk executable is supported for informational/update subcommands and for kit builds of *other* kits — the kit whose deployed executable is running the build is skipped with a warning (it cannot be replaced while running, and the pre-deploy process sweep must not kill the build itself; the sweep also excludes the build's own pid in all cases). Rebuild that kit from tclsh or a different kit. +- Use `punk make.tcl bakehouse` or `punk902z make.tcl bakehouse` inside Punk shell when baking binaries through Punk. Driving make.tcl from a built punk executable is supported for informational/update subcommands and for bakes of *other* kits — the kit whose deployed executable is running the bake is skipped with a warning (it cannot be replaced while running, and the pre-deploy process sweep must not kill the bake itself; the sweep also excludes the bake's own pid in all cases). Rebake that kit from tclsh or a different kit. - **Punk-exe-hosted make.tcl runs in a pre-loaded interp, not a virgin one** — the kit's script-mode boot has already loaded much of the punk stack (punk, punk::lib, punk::repl, punk::console, punk::du, flagfilter, struct::set ...) and set process state (app-punkscript forces `::tcl_interactive 0` for script semantics; libunknown/packagepreference are active). Consequences make.tcl must (and now does) handle explicitly: `package require` of an already-provided package is a no-op, so anything make.tcl breaks in the interp (the accelerator-reload block forgets+destroys sha1/md5/struct::* — it re-requires what was loaded), and anything computed at package-load time (punk::repl's `::tcl_interactive` probe — the shell branch recomputes it before `repl::start`), must be restored deliberately rather than relying on later loads to re-fire. Also note the copies that run in this mode are the *kit's* pre-loaded modules, not the bootsupport snapshots make.tcl's paths would otherwise prefer — silent provenance mixing when versions diverge. When adding interp-surgery or load-time-state assumptions to make.tcl, test under both `tclsh src/make.tcl ...` and ` src/make.tcl ...`. -- Binary images are platform-specific; build on each target platform rather than expecting a cross-platform flag. -- Remove `_build/` artifacts only when a clean/resync is needed, then rerun the relevant `make.tcl` command. Avoid partial cleans that break boot modules. +- Binary images are platform-specific; bake on each target platform rather than expecting a cross-platform flag. +- Remove `_bake/` / `_mint/` artifacts only when a clean/resync is needed, then rerun the relevant `make.tcl` command. Avoid partial cleans that break boot modules. - Superseded module intermediates are pruned automatically so payload wrapping inherits clean trees: - `punk::mix::cli::lib::prune_superseded_target_modules` runs inside `build_modules_from_source_to_base` after each module install/skip (covers root `modules/`, `modules_tcl8/`, `modules_tcl9/`), and from `make.tcl bootsupport` for non-glob `include_modules.config` entries (glob entries may intentionally track multiple versions and are never pruned). - `punk::mix::cli::lib::prune_sourcevanished_targets` mirror-prunes recorded targets whose recorded source files no longer exist: root `modules*/` vendormodule copies (installer `make.tcl`) and the thin-layout/modpod sync copies recorded in `src/project_layouts/.punkcheck` (installer `make.tcl`, all file types). - Every deletion is recorded as a punkcheck DELETE event in the owning `.punkcheck`, so change detection stays consistent. Files without a qualifying punkcheck install record (e.g placed manually) are never deleted — they are reported to stderr and must be removed by hand if unwanted. - Install records carry virtual `module_name`/`module_version` SOURCE entries (punkcheck `targetset_addsource_virtual`, punkcheck >= 0.3.0) identifying which product of a source fileset a target is — needed because successive versions are typically built from the same physical source files. Prune trusts this identity; for legacy records it falls back to requiring the candidate's recorded sources to share the keep-version's source folder(s) and module-name prefix. - - The make.tcl call sites are guarded with `info commands` checks: after changing this tooling itself, the first `make.tcl modules` + `make.tcl bootsupport` pass builds/propagates the new tooling (prune skipped with a stderr note) and the next pass prunes. + - The make.tcl call sites are guarded with `info commands` checks: after changing this tooling itself, the first `make.tcl modules` + `make.tcl bootsupport` pass mints/propagates the new tooling (prune skipped with a stderr note) and the next pass prunes. - Use `tcl::tm::path add ` to surface project modules when writing focused tooling. - Review VS Code Tcl lint diagnostics before submitting new agent-produced Tcl code, but do not use lint tooling to reformat existing code. - When touching VFS payloads, describe regeneration steps in durable docs if the workflow changes. @@ -103,8 +103,8 @@ Recovery after a wrong path guess: - VS Code Tcl lint diagnostics are reviewed for modified Tcl files when available. - Relevant tests pass, either `tclsh src/tests/runtests.tcl` or a specific `tclsh src/tests/modules//tests/all.tcl`. -- `tclsh src/make.tcl packages` is verified when touching build-critical code. -- `tclsh src/make.tcl bakehouse` (with `-dirty-abort 0` when verifying a deliberately dirty tree) completes without errors when changing build, runtime, or VFS behavior. +- `tclsh src/make.tcl packages` is verified when touching mint/bake-critical code. +- `tclsh src/make.tcl bakehouse` (with `-dirty-abort 0` when verifying a deliberately dirty tree) completes without errors when changing make.tcl, runtime, or VFS behavior. - Documentation/comments are updated for new behavior, flags, workflow, or ownership rules. - Diffs are reviewed so no stray whitespace or debugging output remains. diff --git a/src/README.md b/src/README.md index 8598545d..cd367229 100644 --- a/src/README.md +++ b/src/README.md @@ -17,16 +17,16 @@ Runtimes ``` -Build Instructions +Make Instructions (mint / promote / bake) ------------------------------ -+ Use `tclsh| make.tcl ` to build .tm modules and rebuild the punk executable ++ Use `tclsh| make.tcl ` to mint .tm modules and rebake the punk executables In normal use it should be called from the project root. e.g ``` tclsh src/make.tcl vendorupdate ;# if needed - tclsh src/make.tcl packages ;# build/install the unversioned libs / modules to + tclsh src/make.tcl packages ;# mint the libs / modules from src to (version-stamped) # or separately: # tclsh src/make.tcl modules ;# src/modules -> /modules (etc) # tclsh src/make.tcl libs ;# src/lib -> /lib (etc) diff --git a/src/bootsupport/AGENTS.md b/src/bootsupport/AGENTS.md index a2507b9d..0902508b 100644 --- a/src/bootsupport/AGENTS.md +++ b/src/bootsupport/AGENTS.md @@ -2,13 +2,13 @@ ## Purpose -Modules and libraries required during the build/bootstrap/make process before the full Punk module set is available. These are analogous to npm devDependencies — they must be self-contained with minimal dependencies. +Modules and libraries required during the make/bootstrap process before the full Punk module set is available. These are analogous to npm devDependencies — they must be self-contained with minimal dependencies. ## Ownership - Agents should not directly modify files in this tree unless the task specifically targets boot behaviour. - Bootsupport modules are snapshots that may lag behind or diverge from the corresponding `src/modules/` versions intentionally. -- The systematic update workflow is `modules/include_modules.config` (entries are ` ` pairs; base `src/vendormodules` for vendored modules, base `modules` for the project's *built* root modules - build with `make.tcl modules` first) followed by `tclsh src/make.tcl bootsupport`. Project layouts store no bootsupport snapshots (G-087): `dev project.new` injects bootsupport into generated projects from the generating shell at generation time, and the layouts carry only manifest copies of `include_modules.config` (synced by the thin-layout sync step of `make.tcl modules`/`libs`/`packages`/`project` runs - a manifest edit reaches layouts and the templates modpod on the next such build). +- The systematic update workflow is `modules/include_modules.config` (entries are ` ` pairs; base `src/vendormodules` for vendored modules, base `modules` for the project's *minted* root modules - mint with `make.tcl modules` first) followed by `tclsh src/make.tcl bootsupport`. Project layouts store no bootsupport snapshots (G-087): `dev project.new` injects bootsupport into generated projects from the generating shell at generation time, and the layouts carry only manifest copies of `include_modules.config` (synced by the thin-layout sync step of `make.tcl modules`/`libs`/`packages`/`project` runs - a manifest edit reaches layouts and the templates modpod on the next such build). - For non-glob config entries only the latest version is tracked: `make.tcl bootsupport` prunes punkcheck-recorded superseded older `.tm` versions from the bootsupport folders (recorded as DELETE events in `src/bootsupport/.punkcheck`). Use a glob entry to intentionally keep multiple versions. Files without punkcheck install records are never pruned automatically. - The manifest is expected to be complete: a module physically present in bootsupport but missing from `include_modules.config` (a recordless legacy file) works for this checkout but is invisible to generation-time injection - generated projects then lack it. cmdline and struct::set were re-added to the manifest this way (2026-07-19). `make.tcl bootsupport` itself copies only manifest-listed `.tm` files; injection additionally carries adjacent non-.tm support files (e.g struct's `sets_*.tcl`, textutil's `.tex` data) that some modules load from their own directory. - `dev lib.copyasmodule` is a manual convenience for copying a module (or a single-file pkgIndex.tcl library, converting it to .tm form) from a running punk shell - see `modules/README.md`; it is not the primary update mechanism. @@ -45,7 +45,7 @@ For modules outside this tracked set (including `punk::mix::util`, `punk::mix::c If the set of runtime-critical packages in `make.tcl`'s `_runtime_deps` list ever grows, update this list (and the matching one in `src/modules/AGENTS.md`) so the two stay in sync. -After changing any build-critical module (`punkcheck`, `punk::repo`, `punk::mix`, `punk::tdl`, `punk::args`), rebuild bootsupport with `cd src && tclsh make.tcl modules && tclsh make.tcl bootsupport` so the snapshot matches the source version and staleness does not trip (append `-confirm 0` for unattended runs). +After changing any bootstrap-tracked module (`punkcheck`, `punk::repo`, `punk::mix`, `punk::tdl`, `punk::args`), refresh bootsupport with `cd src && tclsh make.tcl modules && tclsh make.tcl bootsupport` so the snapshot matches the source version and staleness does not trip (append `-confirm 0` for unattended runs). ## Work Guidance @@ -60,7 +60,7 @@ overwritten in place while any process has it MOUNTED. A zipfs mount memory-maps archive (`tclZipfs.c`: `CreateFileMappingW` + `MapViewOfFile`), and windows refuses to overwrite a file with a user-mapped section open - `ERROR_USER_MAPPED_FILE` (1224). Any holder blocks it: a running punk shell that loaded the modpod, a `src`-mode session, or the -build itself. +make.tcl run itself. Tcl reports it as **`invalid argument`**, which names nothing useful. That is not a bad argument: `Tcl_WinConvertError` maps only Win32 codes 0..267 and sends everything above @@ -73,7 +73,7 @@ attempts the ordinary `file copy -force`, and on failure falls back to **delete- - unlinking a mapped file IS permitted, the holder keeps reading its own mapping, and new content lands at the name. The replacement content is staged to a sibling `.punkboot-new` first so a mid-sequence failure can never leave the target missing; -a `broken` return (unlinked and unrestorable) is reported as a build failure naming the +a `broken` return (unlinked and unrestorable) is reported as a run failure naming the file to restore by hand. A genuine failure additionally prints `::punkboot::mapped_file_hint`, which explains the catch-all rather than leaving `invalid argument` bare. @@ -89,8 +89,8 @@ see it fail, the hint line tells you which process class to look for. Chicken-and-egg-safe ordering when adding to punkboot::utils (make.tcl must never reference a proc its loaded snapshot lacks): 1. Edit `src/modules/punkboot/utils-999999.0a1.0.tm` and bump its buildversion. -2. `tclsh src/make.tcl modules` (build to root `modules/`). -3. `tclsh src/make.tcl bootsupport` (pull the new build into `src/bootsupport/modules/`). +2. `tclsh src/make.tcl modules` (mint to root `modules/`). +3. `tclsh src/make.tcl bootsupport` (pull the new minted copies into `src/bootsupport/modules/`). 4. Only then repoint make.tcl call sites to the new proc. make.tcl call sites must use a guarded `package require punkboot::utils` and degrade gracefully (skip the feature with a warning) when the proc is unavailable — a stale or broken bootsupport snapshot must never brick the make.tcl commands used to repair it (`modules`, `bootsupport`). diff --git a/src/buildsuites/AGENTS.md b/src/buildsuites/AGENTS.md index bc24cebd..358103eb 100644 --- a/src/buildsuites/AGENTS.md +++ b/src/buildsuites/AGENTS.md @@ -4,7 +4,7 @@ Suites that build Tcl runtimes and binary companions from external upstream sources using the pinned zig toolchain (zig-only build policy). Arm's-length -from the project build/bake stages: inputs are upstream checkouts/pins, not +from the project mint/bake stages: inputs are upstream checkouts/pins, not this project's `src/` tree. ## Ownership diff --git a/src/make.tcl b/src/make.tcl index 030847da..42e50740 100644 --- a/src/make.tcl +++ b/src/make.tcl @@ -175,7 +175,7 @@ apply {{} { }} # Colour-policy gate for raw-SGR emission sites that can run before # define_global_ansi / punk::ansi are available (early package-load -# diagnostics and kit-build warnings). Returns the SGR sequence, or an empty +# diagnostics and kit-bake warnings). Returns the SGR sequence, or an empty # string when colour is disabled. Empty/omitted params give the reset. proc ::punkboot::sgr {{sgrparams ""}} { if {[info exists ::punk::console::colour_disabled] && $::punk::console::colour_disabled} { @@ -490,7 +490,7 @@ namespace eval ::punkboot::lib { # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # G-122 host/target platform split. # platform_punk answers "what is THIS tclsh" (the HOST canon). Everything a - # build EMITS is a separate question keyed by TARGET: which bin/runtime/ + # bake EMITS is a separate question keyed by TARGET: which bin/runtime/ # store holds the runtime, whether artifacts carry .exe, and which process # tooling can see/kill a running artifact. The two diverge for the whole # cygwin family: an msys2/cygwin-runtime tclsh on windows reports @@ -522,12 +522,12 @@ namespace eval ::punkboot::lib { return [expr {[platform_os $platform] in {msys cygwin}}] } #Windows-family platforms: native win32 AND the cygwin-family personalities. - #They share what matters to a build: executables are .exe files and running + #They share what matters to a bake: executables are .exe files and running #processes are windows processes (tasklist/taskkill), whatever tcl_platform says. proc platform_is_windows_family {platform} { return [expr {[platform_os $platform] in {win32 msys cygwin}}] } - #Default TARGET platform for a host canon. A cygwin-family host builds native + #Default TARGET platform for a host canon. A cygwin-family host bakes native #windows kits (there is no separate msys kit lineage - third-party msys #runtimes are addressed by an explicit per-entry target instead). proc platform_target_default {hostplatform} { @@ -708,7 +708,7 @@ proc ::punkboot::lib::mapvfs_locate {rt_sourcefolder} { #tomlish::to_dict values are type-tagged (e.g {type STRING value x}, {type ARRAY value {...}}); #tables are plain nested dicts. Shared by the mapvfs toml reader, the per-.vfs -#payload declarations (G-115) and any other build-side toml consumption. +#payload declarations (G-115) and any other bake-side toml consumption. proc ::punkboot::lib::toml_untag {tagged} { if {[dict get $tagged type] eq "ARRAY"} { set plain [list] @@ -1200,7 +1200,7 @@ proc ::punkboot::lib::mapvfs_parse_config {mapfile rtbase sourcefolder default_t # the vfs rootname, kit_type defaulting to 'kit', '-' runtime -> .kit, # TARGET .exe suffix, duplicate appname -> _) so listed names # match what a bake produces. Entries whose vfs folder is missing on disk never -# reach the kit loop - they are appended after the buildable set so 'bakelist' +# reach the kit loop - they are appended after the bakeable set so 'bakelist' # can surface them as broken config. Duplicate-name disambiguation is per TARGET # (G-127): same-named kits for different targets coexist under their own output # tiers; a same-target duplicate assumes the config keeps appnames unique (as @@ -1217,7 +1217,7 @@ proc ::punkboot::lib::mapvfs_parse_config {mapfile rtbase sourcefolder default_t # runtime_dir store tier folder holding the runtime ("" for "-") # target target platform (e.g win32-x86_64) # store_tier bin/runtime tier folder name for the target -# out_tier kit OUTPUT tier relative to bin/ and src/_build/ - "" for the +# out_tier kit OUTPUT tier relative to bin/ and src/_bake/ - "" for the # default (host) target's flat locations, "kits/" for any # other target (G-127) # vfs vfs folder tail (e.g punk9wintk903.vfs) @@ -1413,7 +1413,7 @@ proc ::punkboot::lib::mapvfs_match_outputs {kit_outputs names} { } # Local runtime-materialization staleness core (shared by the bake-path -# BUILD-WARNING and the bakelist report - the G-121 reuse of the G-103/G-117 +# BAKE-WARNING and the bakelist report - the G-121 reuse of the G-103/G-117 # toml-revision metadata). Compares a punk-runtime WORKING COPY's beside-toml # revision against the highest -r artifact revision present in the same # folder. Returns an empty dict when there is nothing to report (pre-family @@ -1491,23 +1491,23 @@ proc ::punkboot::lib::files_content_identical {patha pathb} { } # Deployed-state classification for a configured kit output (G-121 bakelist): -# the deployed copy (/bin/) vs the build product -# (src/_build/). +# the deployed copy (/bin/) vs the bake product +# (src/_bake/). # absent - no deployed copy in the bin folder -# nobuild - deployed copy exists but there is no build product to compare against -# current - deployed copy is byte-identical to the build product -# stale - deployed copy differs from the build product +# nobake - deployed copy exists but there is no bake product to compare against +# current - deployed copy is byte-identical to the bake product +# stale - deployed copy differs from the bake product # Size mismatch decides 'stale' cheaply; equal size + equal mtime short-circuits # to 'current' (the deploy step is a plain 'file copy'); otherwise a full content # compare decides. -proc ::punkboot::lib::kit_deploy_state {buildfolder deployfolder targetkit} { - set built [file join $buildfolder $targetkit] +proc ::punkboot::lib::kit_deploy_state {bakefolder deployfolder targetkit} { + set built [file join $bakefolder $targetkit] set deployed [file join $deployfolder $targetkit] if {![file isfile $deployed]} { return absent } if {![file isfile $built]} { - return nobuild + return nobake } if {[file size $built] != [file size $deployed]} { return stale @@ -1553,10 +1553,10 @@ set this_platform_generic [punkboot::lib::platform_punk] ;#normalized punkshell # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- #G-122 host/target split. $this_platform_generic is the HOST canon and stays the #key for everything that describes THIS interpreter (bootsupport/vendorlib -#platform dirs below, diagnostics). What the build EMITS is keyed by target: +#platform dirs below, diagnostics). What the bake EMITS is keyed by target: # host_platform - canon of the driving tclsh (same value, named for clarity) # target_platform - default target for kit outputs; a cygwin-family host -# (msys2/cygwin runtime on windows) builds win32 kits. +# (msys2/cygwin runtime on windows) bakes win32 kits. # Per-entry mapvfs.config declarations override it per runtime. # host_windows - host process/filesystem semantics are windows-like # (native windows OR cygwin family): drives copy commands, @@ -1608,8 +1608,8 @@ set sourcesupport_module_paths [list] set sourcesupport_library_paths [list] set sourcesupport_paths_exist 0 #we deliberately don't use [pwd]/modules because commonly the launch dir may be the project dir. -#The /modules are the very modules we are building - and may be in a broken state, which punkboot then can't fix. -#The 'building' is generally just assigning a version instead of 999999.0a1 (and some doc string substitution?) +#The /modules are the very modules we are minting - and may be in a broken state, which punkboot then can't fix. +#The mint is generally just stamping a version instead of 999999.0a1 (plus modpod packing and doc string substitution) #(most?) Modules in src/modules etc should still be runnable directly in certain cases like this where we point to them. if {[file tail $startdir] eq "src"} { #todo - other src 'module' dirs.. @@ -2578,32 +2578,32 @@ proc ::punkboot::punkboot_gethelp {args} { append h " $scriptname -help or $scriptname --help or $scriptname /? or just $scriptname" \n append h " - This help." \n \n append h " $scriptname bakehouse ?-k? ?-dirty-abort 1|0?" \n - append h " - consumer build from a clean checkout: runs the packages stage (modules + libs) then bakes kit/zipkit executables to /bin" \n + append h " - consumer run from a clean checkout: mints the packages (modules + libs) then bakes kit/zipkit executables to /bin" \n append h " - refuses uncommitted src by default (-dirty-abort defaults ON: the bakehouse bakes from the committed recipe; pass -dirty-abort 0 to override)" \n - append h " - the optional -k flag will terminate running processes matching the executable being built (if applicable)" \n + append h " - the optional -k flag will terminate running processes matching the executable being baked (if applicable)" \n append h " - does NOT run the promotion gates (bootsupport, vfscommonupdate) - on a clean checkout they are already satisfied by the committed tree" \n \n append h " $scriptname bake ?-k? ?kitname ...?" \n append h " - assemble kit/zipkit executables from the promoted payload (src/vfs) and src/runtime runtimes into /bin" \n - append h " - includes the vfslibs phase; does not rebuild modules/libs and does not run the promotion gates" \n - append h " - with kitname arguments, bakes and deploys only the named configured kits (unknown names error before any build)" \n \n + append h " - includes the vfslibs phase; does not re-mint modules/libs and does not run the promotion gates" \n + append h " - with kitname arguments, bakes and deploys only the named configured kits (unknown names error before any bake)" \n \n append h " $scriptname bakelist ?kitname ...?" \n append h " - list the kit outputs configured in src/runtime/mapvfs.toml: name, kit type, runtime (with presence)," \n - append h " vfs folder and deployed state (bin copy absent/current/stale/nobuild vs the src/_build product)" \n + append h " vfs folder and deployed state (bin copy absent/current/stale/nobake vs the src/_bake product)" \n append h " - kitname arguments filter to the named entries (per-kit detail)" \n \n append h " $scriptname modules" \n - append h " - build (or copy if build not required) .tm modules from src/modules src/vendormodules etc to their corresponding locations under " \n - append h " This does not scan src/runtime and src/vfs folders to build kit/zipkit/cookfs executables" \n \n + append h " - mint (stamp real versions, pack modpods; plain copy where no stamping applies) .tm modules from src/modules src/vendormodules etc to their corresponding locations under " \n + append h " This does not scan src/runtime and src/vfs folders to bake kit/zipkit/cookfs executables" \n \n append h " $scriptname libs" \n - append h " - build (or copy if build not required) pkgIndex.tcl based libraries from src/lib src/vendorlib etc to their corresponding locations under " \n - append h " This does not scan src/runtime and src/vfs folders to build kit/zipkit/cookfs executables" \n \n + append h " - mint (or plain copy where no stamping applies) pkgIndex.tcl based libraries from src/lib src/vendorlib etc to their corresponding locations under " \n + append h " This does not scan src/runtime and src/vfs folders to bake kit/zipkit/cookfs executables" \n \n append h " $scriptname packages" \n - append h " - build (or copy if build not required) both .tm and pkgIndex.tcl based packages from src to their corresponding locations under " \n - append h " This does not scan src/runtime and src/vfs folders to build kit/zipkit/cookfs executables" \n \n + append h " - mint both .tm and pkgIndex.tcl based packages from src to their corresponding locations under (= modules + libs)" \n + append h " This does not scan src/runtime and src/vfs folders to bake kit/zipkit/cookfs executables" \n \n append h " $scriptname bootsupport" \n append h " - update the src/bootsupport modules" \n append h " - bootsupport modules are pulled from locations specified in include_modules.config files within each src/bootsupport subdirectory" \n append h " - project layouts store no bootsupport module snapshots: generated projects get bootsupport injected at generation time by 'dev project.new'" \n - append h " - This should usually be from modules that have been built and tested in /modules /lib etc." \n + append h " - This should usually be from modules that have been minted and tested in /modules /lib etc." \n append h " - bootsupport modules are available to make.tcl" \n \n append h " $scriptname vendorupdate" \n append h " - update the src/vendormodules based on src/vendormodules/include_modules.config" \n \n @@ -2617,11 +2617,11 @@ proc ::punkboot::punkboot_gethelp {args} { append h " - sha1-verified against the server's per-target sha1sums.txt; materializes package trees under bin/packages//tcl" \n append h " - canonical origin trusted by default; other servers (incl. PUNKBIN_URL overrides) require -trust-server" \n \n append h " $scriptname vfscommonupdate" \n - append h " - promotion gate: update the src/vfs/_vfscommon.vfs from compiled src/modules and src/lib etc" \n + append h " - promotion gate: update the src/vfs/_vfscommon.vfs kit payload from the minted module/lib trees" \n append h " - before calling this (followed by '$scriptname bake') - you can test using '(.exe) dev'" \n append h " this will load modules from your /module /lib paths instead of from the kit/zipkit" \n \n append h " $scriptname info" \n - append h " - show the name and base folder of the project to be built" \n \n + append h " - show the name and base folder of the project" \n \n append h " $scriptname check" \n append h " - show module/library paths and any potentially problematic packages for running this script" \n append h " $scriptname shell" \n @@ -2629,7 +2629,7 @@ proc ::punkboot::punkboot_gethelp {args} { append h " $scriptname projectversion" \n append h " - advisory check: verify CHANGELOG.md matches punkproject.toml and warn if src/ has changes since the last project-version bump." \n \n append h " $scriptname workflow" \n - append h " - print an ASCII data-flow overview of the build/release workflow (edit -> packages -> bootsupport -> kits)" \n \n + append h " - print an ASCII data-flow overview of the release workflow (edit -> mint -> promote -> bake) incl. the TERMINOLOGY key" \n \n append h " $scriptname buildsuite list|info|build ?? ?driver-args ...?" \n append h " - list the defined buildsuites under src/buildsuites (zig runtime factory), show a suite's configured" \n append h " detail (sources/zig pin/products from its sources.config), or run its driver forwarding the args" \n \n @@ -2652,33 +2652,61 @@ proc ::punkboot::punkboot_gethelp {args} { append h " Use -confirm 0 for unattended runs: the bootsupport minor-staleness gate and the vfscommonupdate REPLACE" \n append h " confirmation proceed without prompting; kits with a source/target kit-type mismatch are skipped." \n append h " -dirty-abort" \n - append h " - abort build/promotion commands (bakehouse packages modules libs bake vfslibs bin bootsupport vfscommonupdate) when src/ has" \n + append h " - abort producing commands (mint/promote/bake: bakehouse packages modules libs bake vfslibs bin bootsupport vfscommonupdate) when src/ has" \n append h " uncommitted VCS changes. Default is warn-only EXCEPT bakehouse (defaults ON there; -dirty-abort 0 overrides):" \n - append h " artifacts built from dirty src have no committed provenance." \n + append h " artifacts produced from dirty src have no committed provenance." \n append h " Warnings carry a plain PROVENANCE-WARNING: prefix (greppable in redirected output) and are recapped at the end of the run." \n - append h " Use '$scriptname check' to see the current provenance status. To evaluate uncommitted source without building," \n + append h " Use '$scriptname check' to see the current provenance status. To evaluate uncommitted source without minting or baking," \n append h " use ' src' or ' src shell'." \n \n append h "" \n append h [punkboot_availability_note] return $h } -#Embedded build/release workflow overview - the output of the 'workflow' subcommand. +#Embedded release-workflow overview - the output of the 'workflow' subcommand. #Embedded (rather than a data file) so it travels with make.tcl wherever it runs, including #the make.tcl copies seeded into generated projects via the project layouts. -#Contract for updates (see also src/AGENTS.md 'Work Guidance'): when build data flow changes +#Contract for updates (see also src/AGENTS.md 'Work Guidance'): when make.tcl data flow changes #(subcommand added/removed/repurposed, source or output folder flow changed, new propagation #target), this text changes in the same commit. Plain ASCII only, max line width 100. proc ::punkboot::workflow_text {} { set txt { -build & release workflow - from module edit to kits + bootsupport (punk project layout) +mint, promote & bake - the release workflow from module edit to kits + bootsupport (punk layout) ============================================================================= Scope: data flow from editing a module under src/ through to a release-ready -rebuild (built packages, bootsupport refresh, kit vfs, kit executables). +refresh (minted packages, bootsupport refresh, kit vfs, kit executables). All commands run from the projectroot with a native tclsh, e.g: tclsh src/make.tcl -confirm 0 (see [K6]) -TWO PERSONAS (stage-true subcommand model - one build stage, two promotion +TERMINOLOGY (stage verbs - one word, one stage) +---------------------------------------------------------------------------- + build compile source to binaries. Lives in the arm's-length factories: + 'make.tcl buildsuite' (whole Tcl runtimes from external sources, + src/buildsuites, workdir src/buildsuites/_build) and 'make.tcl + tool build' (vendored zig tools, src/tools). Nothing in + mint/promote/bake compiles anything: bakes succeed with no build + toolchain installed. + mint stamp real versions onto magic-version sources (999999.0a1.0 -> + the -buildversion.txt value), pack #modpod-* trees, prune + superseded copies and install the results into the projectroot + trees (modules*/ lib*/). The modules/libs/packages subcommands + are the mint stage; staging area /_mint. + promote propagate minted packages into the two gated consumption trees: + src/bootsupport (make.tcl's own boot environment) and + src/vfs/_vfscommon.vfs (the committed kit payload) - the + bootsupport and vfscommonupdate promotion gates. + bake assemble kit/zipkit executables from promoted payload + runtimes + (workdir src/_bake) and deploy them to bin/. Consumer umbrella: + bakehouse = mint + bake from the committed recipe. + fetch bring third-party inputs to the tree: libfetch (punkbin lib + artifacts), vendorupdate (vendored sources). + deploy the final copy of a baked kit from src/_bake to bin/. +Mechanism words keep their scoped meanings: stamp (version fields at mint, +icons/resources at bake via punkres), install (punkcheck-recorded placement +at any stage), sync (thin-layout copies), materialize (vfslibs payload +declarations, libfetch trees). + +TWO PERSONAS (stage-true subcommand model - one mint stage, two promotion gates, one bake) ---------------------------------------------------------------------------- CONSUMER (clean checkout, wants baked kits): @@ -2688,7 +2716,7 @@ gates, one bake) default (-dirty-abort defaults ON: the bakehouse bakes from the committed recipe; -dirty-abort 0 overrides). DEVELOPER (changing payload): pass the gates explicitly - the commit is the - publishing act, not a build step. That is the RELEASE SEQUENCE below. + publishing act, not a producing step. That is the RELEASE SEQUENCE below. RELEASE SEQUENCE (the developer order that satisfies the staleness + provenance gates) ---------------------------------------------------------------------------- @@ -2698,18 +2726,18 @@ RELEASE SEQUENCE (the developer order that satisfies the staleness + provenance punkproject.toml + CHANGELOG.md project version (if shipped behaviour) [K2] (3) test tclsh src/tests/runtests.tcl ... runs against src/ trees (if present) (4) commit source changes (git/fossil) clean tree -> committed provenance [K3] - (5) build tclsh src/make.tcl modules -confirm 0 (or 'packages' = modules + libs) - (6) build tclsh src/make.tcl bootsupport -confirm 0 run twice: 2nd pass must copy 0 files [K4] - (7) build tclsh src/make.tcl vfscommonupdate -confirm 0 - (8) build tclsh src/make.tcl bake -confirm 0 kits; close running kit shells first [K5] - (9) commit tracked build outputs src/bootsupport, thin-layout script/ + (5) mint tclsh src/make.tcl modules -confirm 0 (or 'packages' = modules + libs) + (6) promote tclsh src/make.tcl bootsupport -confirm 0 run twice: 2nd pass must copy 0 files [K4] + (7) promote tclsh src/make.tcl vfscommonupdate -confirm 0 + (8) bake tclsh src/make.tcl bake -confirm 0 kits; close running kit shells first [K5] + (9) commit tracked output trees src/bootsupport, thin-layout script/ manifest/gitignore.in payload copies (src/project_layouts + templates modpod payload), src/vfs/_vfscommon.vfs -DIAGRAM 1 - DATA FLOW: SOURCE -> BUILT PACKAGES -> PROPAGATION TARGETS +DIAGRAM 1 - DATA FLOW: SOURCE -> MINTED PACKAGES -> PROMOTION TARGETS ---------------------------------------------------------------------------- src/modules/foo-999999.0a1.0.tm [K1] src/lib/ @@ -2722,7 +2750,7 @@ DIAGRAM 1 - DATA FLOW: SOURCE -> BUILT PACKAGES -> PROPAGATION TARGETS v v modules/ modules_tcl8/ modules_tcl9/ lib/ lib_tcl8/ lib_tcl9/ e.g. modules/foo-0.12.4.tm - == BUILT PACKAGES (projectroot output trees, punkcheck-recorded [K3]) == + == MINTED PACKAGES (projectroot output trees, punkcheck-recorded [K3]) == | +--------------------------------------+ | | @@ -2735,7 +2763,7 @@ DIAGRAM 1 - DATA FLOW: SOURCE -> BUILT PACKAGES -> PROPAGATION TARGETS Project layouts store NO module | snapshots - 'dev project.new' | make.tcl bake (kit-assembly stage; injects bootsupport into generated v consumer umbrella: bakehouse) - projects from the generating src/_build/.exe --deploy--> bin/.exe + projects from the generating src/_bake/.exe --deploy--> bin/.exe shell at generation time - G-087) (see DIAGRAM 2) [K5] @@ -2753,7 +2781,7 @@ DIAGRAM 1b - THIN-LAYOUT SYNC (part of modules/libs/packages/bakehouse runs) | store -> modpod payload sync (punk.project layout only; excludes bin/sdx.kit) v src/modules/punk/mix/#modpod-templates-*/templates/project_layouts/ - (packed into the punk::mix::templates module by the modules build, so a bare + (packed into the punk::mix::templates module by the modules mint, so a bare kit outside any project can list and generate the punk.project layout) @@ -2769,9 +2797,9 @@ DIAGRAM 2 - KIT ASSEMBLY DETAIL (the 'make.tcl bake' stage; incl. vfslibs phase) configured kit outputs (presence + deployed state); 'make.tcl bake ?name|@group ...?' bakes only the named kits (bare bake = all entries except bake_default=false - ones; unknown names error before any build) + ones; unknown names error before any bake) bin/runtime// bare Tcl runtime (tclkit / tclsfe / suite build), in the - store tier of the TARGET platform it builds kits for [K9] + store tier of the TARGET platform it bakes kits for [K9] src/vfs/_vfscommon.vfs/ common payload (built modules + libs, main boot support) src/vfs/.vfs/ per-kit overlay (main.tcl, kit-only modules/config) src/vfs/.vfs.toml optional per-.vfs payload declaration (G-115): [payload.*] @@ -2789,10 +2817,10 @@ DIAGRAM 2 - KIT ASSEMBLY DETAIL (the 'make.tcl bake' stage; incl. vfslibs phase) +-----------+----------+ | copy common, then merge overlay over it v - src/_build/.exe.vfs + src/_bake/.exe.vfs | | advisory payload/target binary-arch scan of the merged - | tree (wrong-arch libraries -> recapped BUILD-WARNING) [K11] + | tree (wrong-arch libraries -> recapped BAKE-WARNING) [K11] | boot-precondition gate: merged vfs must supply a tcl | library (tcl_library/, lib/tcl./, tcl./) [K10] v @@ -2811,7 +2839,7 @@ DIAGRAM 2 - KIT ASSEMBLY DETAIL (the 'make.tcl bake' stage; incl. vfslibs phase) | mkimg, or (driving tcl without zipfs, e.g 8.6) raw-runtime | split + punk::zip::mkzip + concatenation - both mount the same v - src/_build/.exe (+ .exe.resources.toml) + src/_bake/.exe (+ .exe.resources.toml) | | smoke-require probe (host-runnable kits with declared | packages): plain 'package require' inside the artifact [K11] @@ -2857,7 +2885,7 @@ KEY / NOTES [K1] Source modules carry the literal magic version 999999.0a1.0 in the filename. The real version is the first line of the sibling -buildversion.txt; bump it per semver (patch=fix, minor=api add, major=breaking) and append a - '# - ...' changelog comment line below it. The modules build stamps + '# - ...' changelog comment line below it. The mint stamps the real version into the output filename and package provide. (A project may carry manually-versioned exceptions - see src/modules/AGENTS.md if present.) @@ -2866,10 +2894,11 @@ KEY / NOTES entry) is change-driven: bump when the change ships user-visible behaviour. Advisory check: tclsh src/make.tcl projectversion -[K3] Every build target root gets a .punkcheck file recording what was installed - from where (punkcheck provenance). Building from a tree with uncommitted - changes under src/ works but emits PROVENANCE-WARNINGs - commit source first - for release builds. Output-tree commits (step 9) come after the builds. +[K3] Every output target root gets a .punkcheck file recording what was installed + from where (punkcheck provenance). Minting/promoting/baking from a tree with + uncommitted changes under src/ works but emits PROVENANCE-WARNINGs - commit + source first for release runs. Output-tree commits (step 9) come after the + producing steps. [K4] Bootsupport staleness gate: make.tcl compares tracked module versions in src/bootsupport against built sources; a stale bootsupport makes other @@ -2879,10 +2908,10 @@ KEY / NOTES [K5] The deploy step cannot replace a kit exe that is currently executing. Close running kit shells before step 8, or rerun 'make.tcl bake -confirm 0' - afterwards - the freshly built kits wait in src/_build. punkcheck records + afterwards - the freshly baked kits wait in src/_bake. punkcheck records mean the rerun only redoes the failed deploys. When iterating on one kit, - 'make.tcl bake ' rebuilds/deploys just that kit; 'make.tcl - bakelist' shows each configured kit's deployed state (bin vs src/_build). + 'make.tcl bake ' rebakes/deploys just that kit; 'make.tcl + bakelist' shows each configured kit's deployed state (bin vs src/_bake). [K6] All confirmation prompts follow -confirm: unattended/agent runs must pass -confirm 0 (non-interactive stdin aborts fast at prompts; piping 'y' is @@ -2891,13 +2920,13 @@ KEY / NOTES [K7] Testing hooks along the way: - src/tests/runtests.tcl exercises the src/ trees directly (dev modules). - '.exe dev' (or ' src') runs a built shell against the - project dev modules - useful for testing built packages before they are + project dev modules - useful for testing minted packages before they are baked into kits via vfscommonupdate + bake. -[K8] What is VCS-tracked where (checkin targets after a build): +[K8] What is VCS-tracked where (checkin targets after a make.tcl run): tracked: src/** (sources, src/bootsupport, src/project_layouts copies, src/vfs/_vfscommon.vfs), punkproject.toml, CHANGELOG.md - untracked: modules*/ lib*/ at projectroot, src/_build/, bin/.exe, + untracked: modules*/ lib*/ at projectroot, src/_bake/, bin/.exe, bin/kits// (cross-target kit outputs - G-127), src/vfs/*.vfs/_targets/ (per-platform payload staging) (bin/ scripts/tools are tracked; kit executables are not) @@ -2915,7 +2944,7 @@ KEY / NOTES 'make.tcl check' prints the derivation; 'make.tcl bakelist' shows per-kit targets, with a target= note on rows that are not on the default target. OUTPUT locations are target-keyed too (G-127): default-target kits keep the - flat src/_build/ + bin/ locations, any other target's kit builds + flat src/_bake/ + bin/ locations, any other target's kit bakes and deploys under the kits// tier of both (bin/kits/ = outputs, beside bin/runtime/ = inputs), so same-named kits for different targets coexist instead of overwriting each other; bakelist marks such rows with @@ -2924,7 +2953,7 @@ KEY / NOTES [K10] BOOT-PRECONDITION gate (G-125). A kit whose merged vfs has no tcl library cannot initialise at all ('Cannot find a usable init.tcl'), so the bake refuses it: the kit is listed under FAILED KITS and NOTHING is written - - no src/_build/, no deploy, and the previously deployed bin/ is + no src/_bake/, no deploy, and the previously deployed bin/ is left exactly as it was. This is deliberately not a warning: the deploy step deletes the old kit before copying the new one, so warning-and-proceeding replaced a working shell with one that could not start. The check is @@ -2933,18 +2962,18 @@ KEY / NOTES executable's own path rather than //zipfs:/app), plus a companion file so a package's own init.tcl cannot answer for a tcl library - and runs on the MERGED tree, not on whether extraction ran - a .vfs that - supplies its own tcl library builds and deploys as normal. Nothing is + supplies its own tcl library bakes and deploys as normal. Nothing is executed, so cross-target kits are covered too. Usual cause: the runtime's - own payload could not be extracted - see the BUILD-WARNING naming what was + own payload could not be extracted - see the BAKE-WARNING naming what was tried. 'make.tcl check' reports whether the gate is ACTIVE. [K11] PAYLOAD/TARGET consistency checks (G-133), both ADVISORY - warnings recap at - end of run, the kit still builds and deploys. (a) Binary-arch scan at the same + end of run, the kit still bakes and deploys. (a) Binary-arch scan at the same seam as [K10]: each binary library (*.dll/*.so/*.dylib) in the merged tree is classified by header (PE/ELF/Mach-O - structural, nothing executed, so cross-target kits are covered) against the kit's target platform; wrong-arch libraries outside platform-discriminated subdirs (win32-ix86/, win-x64/ etc - - multi-arch payloads are legitimate there) earn recapped BUILD-WARNINGs. + multi-arch payloads are legitimate there) earn recapped BAKE-WARNINGs. (b) Smoke-require probe: a kit declaring packages (mapvfs.toml smokerequire key; legacy config: 5th element) has each one plain-'package require'd INSIDE the freshly built artifact via its tclsh subcommand - the only check that sees resolution-order @@ -2964,7 +2993,7 @@ OUT-OF-BAND SUBSYSTEMS (not part of the packages/bake data flow above) MAINTENANCE (agents take note) ---------------------------------------------------------------------------- -This text is embedded in make.tcl (::punkboot::workflow_text). When the build +This text is embedded in make.tcl (::punkboot::workflow_text). When the make.tcl data flow changes - a make.tcl subcommand added/removed/repurposed, a source or output folder added or rerouted, a new propagation target, a changed gate or deploy behaviour - update this text in the same change-set and verify with @@ -3014,7 +3043,7 @@ proc ::punkboot::punkboot_availability_note {} { append h " Call 'make.tcl check' and examine the last table (which includes bootsupport + executable-provided packages)" \n append h " See if there are any items marked missing or broken that aren't marked as '(known optional)'" \n append h " If all are marked (known optional) then it should work." \n - append h " A package marked (known optional) and (RECOMMENDED) may make the build/install processes run a lot faster. (e.g tcllibc)" \n + append h " A package marked (known optional) and (RECOMMENDED) may make the mint/bake and install processes run a lot faster. (e.g tcllibc)" \n append h "* $A(HIGHLIGHT)** *** *** ***$A(RST)" \n\n #append h "Successfully Loaded packages:" \n #append h " " [join $::punkboot::pkg_loaded "\n "] \n @@ -3056,14 +3085,14 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO #single source for the subcommand one-line summaries: each subcommand definition's #@cmd -summary and the top-level subcommand -choicelabels are both built from this. variable SUMMARIES { - bakehouse "Consumer build from a clean checkout: packages then bake - refuses uncommitted src by default" - packages "Build .tm modules and pkgIndex.tcl libraries from src into (no kit executables)" - modules "Build .tm modules from src/modules, src/vendormodules etc into /modules etc" - libs "Build pkgIndex.tcl libraries from src/lib, src/vendorlib etc into /lib etc" + bakehouse "Consumer run from a clean checkout: mint packages then bake - refuses uncommitted src by default" + packages "Mint .tm modules and pkgIndex.tcl libraries from src into (no kit executables)" + modules "Mint .tm modules from src/modules, src/vendormodules etc into /modules etc" + libs "Mint pkgIndex.tcl libraries from src/lib, src/vendorlib etc into /lib etc" bake "Assemble kit/zipkit executables from promoted payload (src/vfs) and runtimes into /bin" bakelist "List the kit outputs configured in src/runtime/mapvfs.toml: type, runtime/vfs presence, deployed state, groups" vfslibs "Materialize per-.vfs payload declarations (src/vfs/.vfs.toml - G-115) into kit vfs folders; drop-ins preserved" - bin "Install executables from src/bin into /bin, then build kits as for bake" + bin "Install executables from src/bin into /bin, then bake kits as for bake" vendorupdate "Update src/vendormodules based on src/vendormodules/include_modules.config" libfetch "Fetch declared punkbin lib-tier library artifacts into bin/packages/ (sha1-verified) and materialize the package trees" bootsupport "Promotion gate: update src/bootsupport modules from built project modules" @@ -3071,7 +3100,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO info "Show the name and base folder of the project to be built" check "Show module/library paths and any potentially problematic packages for running this script" projectversion "Advisory check: CHANGELOG.md vs punkproject.toml and src/ changes since last version bump" - workflow "Print an ASCII data-flow overview of the build/release workflow (edit -> packages -> gates -> bake)" + workflow "Print an ASCII data-flow overview of the release workflow (edit -> mint -> promote -> bake)" shell "Run the punk shell using bootsupport libraries" help "Show usage for make.tcl or one of its subcommands" buildsuite "List, describe or run the defined buildsuites under src/buildsuites (zig runtime factory)" @@ -3094,41 +3123,43 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO to run when src/ has uncommitted changes (-dirty-abort defaults ON), pointing at the granular developer flow (packages -> test -> bootsupport/vfscommonupdate -> commit -> bake). Pass -dirty-abort 0 - to build anyway with PROVENANCE-WARNINGs. + to proceed anyway with PROVENANCE-WARNINGs. Deliberately does NOT run the promotion gates (bootsupport, vfscommonupdate): payload promotion is a confirm-gated, committed act - on a clean checkout the gates are already satisfied by the committed tree." packages " - Build (or copy if build not required) both .tm and pkgIndex.tcl based + Mint (stamp real versions, pack modpods; plain copy where no + stamping applies) both .tm and pkgIndex.tcl based packages from src to their corresponding locations under . - This does not scan src/runtime and src/vfs folders to build kit/zipkit + This does not scan src/runtime and src/vfs folders to bake kit/zipkit executables." modules " - Build (or copy if build not required) .tm modules from src/modules, + Mint (stamp real versions, pack modpods; plain copy where no + stamping applies) .tm modules from src/modules, src/vendormodules etc to their corresponding locations under . - This does not scan src/runtime and src/vfs folders to build kit/zipkit + This does not scan src/runtime and src/vfs folders to bake kit/zipkit executables." libs " - Build (or copy if build not required) pkgIndex.tcl based libraries from + Mint (or plain copy where no stamping applies) pkgIndex.tcl based libraries from src/lib, src/vendorlib etc to their corresponding locations under . - This does not scan src/runtime and src/vfs folders to build kit/zipkit + This does not scan src/runtime and src/vfs folders to bake kit/zipkit executables." bake " Assemble kit/zipkit executables: scan src/vfs and src/runtime folders, - build each configured kit from the promoted payload + bake each configured kit from the promoted payload (src/vfs/_vfscommon.vfs + custom vfs folders) and its runtime, and install to /bin. With kitname (or @groupname - G-024 groups) arguments, bake and deploy ONLY the named configured kits (see 'make.tcl bakelist' - for the configured names and groups) - other kits' build + for the configured names and groups) - other kits' bake products, bin copies and punkcheck records are left untouched. - An unknown name errors before any build, listing the configured + An unknown name errors before any bake, listing the configured names. Bare 'bake' processes all configured kits except bake_default=false entries (those bake only by name/@group). Includes the vfslibs phase (per-.vfs payload declarations @@ -3147,12 +3178,12 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO kit name, kit type (kit|zip|zipcat...), runtime with presence in the runtime store of that kit's TARGET platform (/bin/runtime/), vfs folder, and the - deployed state of /bin/ vs the src/_build build + deployed state of /bin/ vs the src/_bake bake product: - current - deployed copy is identical to the build product - stale - deployed copy differs from the build product + current - deployed copy is identical to the bake product + stale - deployed copy differs from the bake product absent - no deployed copy in /bin - nobuild - deployed copy exists but no build product to compare + nobake - deployed copy exists but no bake product to compare A trailing notes column flags anomalies (runtime=missing, vfs=missing, rtrev=r when the runtime working copy is materialized from an older revision than a -r artifact beside @@ -3161,14 +3192,14 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO default - 'make.tcl check' shows that default), G-024 groups (group=), entries excluded from full bakes (default=no) and scheme-expanded outputs (scheme=versioned|dev|release). - Non-default-target kits build and deploy under the - kits// tier of src/_build and bin (G-127) - their rows + Non-default-target kits bake and deploy under the + kits// tier of src/_bake and bin (G-127) - their rows carry out=kits// and the deployed state compares the tiered paths; a kit NAME shared by entries for several targets selects (and lists) every one of them. kitname (or @groupname) arguments filter the report to the named entries (per-kit detail, with resolved store tier, target, - config entry and paths). Reporting only - never builds." + config entry and paths). Reporting only - never bakes." vfslibs " Materialize the per-.vfs payload declarations (G-115): each @@ -3212,7 +3243,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO bin " Install executables from src/bin to /bin, then check vfs - folders and build kit/zipkit executables as for the bake subcommand." + folders and bake kit/zipkit executables as for the bake subcommand." vendorupdate " Update the src/vendormodules based on src/vendormodules/include_modules.config. @@ -3245,7 +3276,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO Also reports the colour policy, the host/target platform derivation (this tclsh's platform canon vs the default kit target, its runtime store tier, executable suffix and process tooling), bootsupport - staleness and the src provenance status (what the build/promotion + staleness and the src provenance status (what the producing commands would do)." projectversion " @@ -3253,13 +3284,13 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO if src/ has changes since the last project-version bump." workflow " - Print a plain-text (ASCII diagram) overview of the build/release + Print a plain-text (ASCII diagram) overview of the release workflow: the release-ready command sequence and how data flows from editing a module under src/ through built packages to bootsupport, the kit vfs and the kit executables. The text is embedded in make.tcl (::punkboot::workflow_text) so it is available wherever make.tcl runs; its MAINTENANCE key states the - update contract for keeping it in step with build behaviour." + update contract for keeping it in step with make.tcl behaviour." help " Show tabled usage for make.tcl as a whole, or for a single subcommand. @@ -3280,7 +3311,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO " Surface for the defined buildsuites under src/buildsuites (zig-built runtime factory - an arm's-length subsystem building Tcl runtimes - from external sources, distinct from the project build/bake stages). + from external sources, distinct from the project mint/bake stages). Actions: buildsuite list @@ -3337,7 +3368,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO the LOWEST release satisfying the floor wins (deterministic as newer toolchains appear beside the pinned one; dev builds count only when their base version exceeds the floor). zig is OPTIONAL - for punkshell builds: packages/bake never require this step - + for the punkshell mint/bake pipeline: packages/bake never require this step - without a suitable toolchain, list reports the state and build/test exit nonzero with fetch guidance (bin/punk-getzig.cmd). Build caches (.zig-cache/zig-out) are @@ -3358,7 +3389,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO non-interactive resolution: bootsupport minor-version staleness gate -> proceed vfscommonupdate REPLACE confirmation -> proceed - kit source/target type mismatch -> skip building that kit + kit source/target type mismatch -> skip baking that kit Note: Tcl 8.6 lacks the terminal probe (-inputmode) so stdin is assumed interactive there - piped runs under 8.6 should always pass -confirm explicitly." @@ -3370,13 +3401,13 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO provenance. Warnings carry a plain PROVENANCE-WARNING: prefix (greppable in redirected output) and are recapped at the end of the run. Use 'make.tcl check' to see the current provenance status. To evaluate - uncommitted source without building, use ' src' or + uncommitted source without minting or baking, use ' src' or ' src shell'." } variable OPT_FORCEKILL { -k -type none -default 0 -help\ "Terminate running processes matching the executable being built - (if applicable) so the build can install over it." + (if applicable) so the bake can install over it." } #bakehouse defaults the dirty gate ON: #the bakehouse bakes from the committed recipe (G-112 two-persona model). @@ -3384,10 +3415,10 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO -dirty-abort -type boolean -default 1 -help\ "Abort when src/ has uncommitted VCS changes - DEFAULT ON for this subcommand: the bakehouse bakes from the committed recipe. A - consumer build on a clean checkout runs uninterrupted; uncommitted + consumer run on a clean checkout proceeds uninterrupted; uncommitted developer changes get a refusal naming the granular flow (packages -> test -> bootsupport/vfscommonupdate -> commit -> bake). - Pass -dirty-abort 0 to build anyway with PROVENANCE-WARNINGs." + Pass -dirty-abort 0 to proceed anyway with PROVENANCE-WARNINGs." } #libfetch fragments (G-139): consent is keyed to SERVER TRUST (the G-123 #posture) - the canonical punkbin origin needs no acknowledgement, any @@ -3510,7 +3541,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO @ for every kit in a configured group (G-024) - see 'make.tcl bakelist' for the configured names and groups. With no kitname, all configured kits are processed except entries with - bake_default=false. An unknown name errors before any build." + bake_default=false. An unknown name errors before any bake." } punk::args::define { @id -id "(script)::punkboot::bakelist" @@ -3729,7 +3760,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO } #top-level definition: the subcommand table rendered by 'make.tcl' / 'make.tcl -help' variable SUBGROUPS { - "build & bake" {bakehouse packages modules libs bake vfslibs bin} + "mint & bake" {bakehouse packages modules libs bake vfslibs bin} "promotion gates" {bootsupport vfscommonupdate} "source maintenance" {vendorupdate libfetch} "buildsuites" {buildsuite} @@ -3756,7 +3787,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO punk::args::define { @id -id "(script)::punkboot" @cmd -name "make.tcl" -& - -summary "punkshell project build tool (punk boot)" -& + -summary "punkshell project make tool (punk boot)" -& -help -& {${$TOPLEVEL_HELP}} #sole remaining explicit synopsis override (G-143 retired the per-subcommand @@ -3805,7 +3836,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO punk::args::define { @id -id "(script)::punkboot.overview" @cmd -name "make.tcl" -& - -summary "punkshell project build tool (punk boot)" -& + -summary "punkshell project make tool (punk boot)" -& -help -& {${$TOPLEVEL_HELP}} @form -synopsis "make.tcl ?subcommand? ?flags?" @@ -4212,7 +4243,7 @@ set binfolder $projectroot/bin # ---------------------------------------- # G-121 selective bake: resolve requested kit names against the parsed kit-mapping -# model before ANY build machinery runs - an unknown name must error without building, +# model before ANY bake machinery runs - an unknown name must error without baking, # and a selected-but-unbuildable kit (missing runtime/vfs) fails fast rather than # silently doing nothing (bare 'bake' keeps the historical warn-and-continue # behaviour for the full configured set). The kit machinery and the vfslibs phase @@ -4277,12 +4308,12 @@ if {$::punkboot::command eq "bake" && [llength $::punkboot::opt_kitnames]} { } # ---------------------------------------- -# Provenance-warning presentation + dirty-src check for build/promotion commands (goal G-026 direction). -# Build/promotion commands stamp versions onto src content and propagate it into trees other +# Provenance-warning presentation + dirty-src check for producing commands (goal G-026 direction). +# Producing commands (mint/promote/bake) stamp versions onto src content and propagate it into trees other # things consume (root modules/, bootsupport snapshots, vfs payloads, kits/zipkits). # Artifacts built from uncommitted src have no committed provenance - warn by default, # abort if the -dirty-abort flag was given. To evaluate uncommitted source without -# building, use ' src' / ' src shell' instead. +# minting or baking, use ' src' / ' src shell' instead. # Guarded require: a stale or missing punkboot::utils bootsupport snapshot must never # brick the make.tcl commands used to repair it - the check degrades to a skip notice # (but -dirty-abort still aborts rather than silently skipping the requested strictness). @@ -4290,7 +4321,7 @@ if {$::punkboot::command eq "bake" && [llength $::punkboot::opt_kitnames]} { #Emit provenance warnings with a plain column-0 token for automated discovery (grep PROVENANCE-WARNING #in redirected output) and ANSI colour for humans. Lines are also accumulated in #::punkboot::provenance_warnings_pending unless -norecap is given, so the wrapped ::exit below can -#recap them at the tail of the output - build progress output is chatty and the original warning +#recap them at the tail of the output - make.tcl progress output is chatty and the original warning #position may scroll out of sight or even out of scrollback. set ::punkboot::provenance_warnings_pending [list] proc ::punkboot::print_provenance_warnings {warninglines args} { @@ -4305,22 +4336,22 @@ proc ::punkboot::print_provenance_warnings {warninglines args} { } flush stderr } -#General build warnings that must stay noticeable despite chatty build output - same +#General bake warnings that must stay noticeable despite chatty output - same #column-0 greppable-token + recap-at-exit treatment as provenance warnings above. -set ::punkboot::build_warnings_pending [list] -proc ::punkboot::print_build_warnings {warninglines args} { +set ::punkboot::bake_warnings_pending [list] +proc ::punkboot::print_bake_warnings {warninglines args} { global A if {![array size A]} {punkboot::define_global_ansi} foreach w $warninglines { regsub {^WARNING: } $w "" w - puts stderr "BUILD-WARNING: $A(BAD)$w$A(RST)" + puts stderr "BAKE-WARNING: $A(BAD)$w$A(RST)" if {"-norecap" ni $args} { - lappend ::punkboot::build_warnings_pending $w + lappend ::punkboot::bake_warnings_pending $w } } flush stderr } -#Availability probe + scoped dirty-src check, shared by the build/promotion gate below and the +#Availability probe + scoped dirty-src check, shared by the producing-commands gate below and the #'check' command report. Returns {available warninglist}. proc ::punkboot::get_src_provenance_warnings {projectroot label} { set available [expr {\ @@ -4338,7 +4369,7 @@ proc ::punkboot::get_src_provenance_warnings {projectroot label} { # #On windows an ordinary 'file copy -force' onto a mapped file is refused: a zipfs mount #maps its archive (tclZipfs.c CreateFileMappingW + MapViewOfFile), so a zip-based .tm -#modpod that any running shell - including this build - has mounted cannot be overwritten +#modpod that any running shell - including this make.tcl run - has mounted cannot be overwritten #in place. Windows reports ERROR_USER_MAPPED_FILE (1224); Tcl's Tcl_WinConvertError maps #only Win32 codes 0..267 and sends everything above them to EINVAL, so it surfaces as the #uninformative "invalid argument" (same code in 8.6 and 9.x). @@ -4385,7 +4416,7 @@ proc ::punkboot::mapped_file_hint {errmsg tgtfile} { } return "'invalid argument' is Tcl's catch-all for any windows error above 267 (Tcl_WinConvertError), not a bad argument.\ For a file replace the usual cause is ERROR_USER_MAPPED_FILE: '$tgtfile' is memory-mapped by a process that has it mounted -\ - a zipfs/modpod mount does this, so a running punk shell (or this build) holding that .tm blocks an in-place overwrite.\ + a zipfs/modpod mount does this, so a running punk shell (or this make.tcl run) holding that .tm blocks an in-place overwrite.\ Close shells holding it, or rerun - the update now replaces such files by delete-then-place rather than overwrite." } #Availability probe + boot-precondition check of an assembled kit vfs (G-125), shared by the @@ -4439,7 +4470,7 @@ proc ::punkboot::get_kit_offsetstyle_report {kitpath} { #file exists. The tclsh subcommand is used deliberately: it exits cleanly even on #runtimes whose full repl teardown is fragile, and a script argument with drained #stdin cannot reach any console-reopen path. ADVISORY: failures become recapped -#BUILD-WARNINGs naming kit, package and the actual error - the kit still deploys. +#BAKE-WARNINGs naming kit, package and the actual error - the kit still deploys. #Returns 1 when every declared package resolved, else 0. proc ::punkboot::kit_smoke_require_probe {kitpath targetkit packages} { set probescript [file rootname $kitpath]_smokerequire.tcl @@ -4459,13 +4490,13 @@ exit 0} close $fd } errM]} { catch {close $fd} - ::punkboot::print_build_warnings [list "smoke-require for kit $targetkit could not write its probe script ($probescript): $errM"] + ::punkboot::print_bake_warnings [list "smoke-require for kit $targetkit could not write its probe script ($probescript): $errM"] return 0 } if {[catch { lassign [punk::lib::invoke [list [file nativename $kitpath] tclsh [file nativename $probescript] << ""]] p_stdout p_stderr p_exitcode } errM]} { - ::punkboot::print_build_warnings [list "smoke-require FAILED for kit $targetkit: could not execute freshly built artifact via its tclsh subcommand ($errM)"] + ::punkboot::print_bake_warnings [list "smoke-require FAILED for kit $targetkit: could not execute freshly built artifact via its tclsh subcommand ($errM)"] return 0 } set seen [dict create] @@ -4502,7 +4533,7 @@ exit 0} lappend warnings "smoke-require for kit $targetkit: artifact exited with code $p_exitcode via its tclsh subcommand (expected 0)" } if {[llength $warnings]} { - ::punkboot::print_build_warnings $warnings + ::punkboot::print_bake_warnings $warnings } return $allok } @@ -4516,10 +4547,10 @@ if {![llength [info commands ::punkboot::exit_original]]} { puts stderr "PROVENANCE-WARNING: recap of warning(s) emitted earlier in this run:" ::punkboot::print_provenance_warnings $::punkboot::provenance_warnings_pending -norecap } - if {[info exists ::punkboot::build_warnings_pending] && [llength $::punkboot::build_warnings_pending]} { + if {[info exists ::punkboot::bake_warnings_pending] && [llength $::punkboot::bake_warnings_pending]} { puts stderr "" - puts stderr "BUILD-WARNING: recap of warning(s) emitted earlier in this run:" - ::punkboot::print_build_warnings $::punkboot::build_warnings_pending -norecap + puts stderr "BAKE-WARNING: recap of warning(s) emitted earlier in this run:" + ::punkboot::print_bake_warnings $::punkboot::bake_warnings_pending -norecap } ::punkboot::exit_original $returnCode } @@ -4531,7 +4562,7 @@ if {$::punkboot::command in {bakehouse packages modules libs bake vfslibs bin bo if {$have_scoped_dirty_check} { if {[llength $dirty_warnings]} { ::punkboot::print_provenance_warnings $dirty_warnings - puts stderr " To evaluate uncommitted source without building, use ' src' or ' src shell'." + puts stderr " To evaluate uncommitted source without minting or baking, use ' src' or ' src shell'." if {$dirty_abort} { set ::punkboot::provenance_warnings_pending [list] ;#no recap needed - aborting adjacent to the warning if {$::punkboot::command eq "bakehouse"} { @@ -4540,9 +4571,9 @@ if {$::punkboot::command in {bakehouse packages modules libs bake vfslibs bin bo puts stderr " make.tcl packages -> test (' src', src/tests/runtests.tcl)" puts stderr " make.tcl bootsupport + make.tcl vfscommonupdate (promotion gates)" puts stderr " commit -> make.tcl bake" - puts stderr " To build anyway without committed provenance: make.tcl bakehouse -dirty-abort 0" + puts stderr " To proceed anyway without committed provenance: make.tcl bakehouse -dirty-abort 0" } else { - puts stderr "-aborted- (-dirty-abort given and src has uncommitted changes - commit first, or rerun without -dirty-abort to build with a warning)" + puts stderr "-aborted- (-dirty-abort given and src has uncommitted changes - commit first, or rerun without -dirty-abort to proceed with a warning)" } exit 1 } @@ -4734,19 +4765,19 @@ if {$::punkboot::command eq "check"} { puts stderr " cd \[projectroot\]/src && tclsh make.tcl modules && tclsh make.tcl bootsupport" puts stderr "==============================================================================" } - # Dirty-src provenance status - what the build/promotion commands would do + # Dirty-src provenance status - what the producing commands would do puts stdout $sep lassign [::punkboot::get_src_provenance_warnings $projectroot "make.tcl check"] _prov_available _prov_warnings if {!$_prov_available} { puts stdout "src provenance: check unavailable (punkboot::utils vcs_dirty_warnings with scope support not loadable from bootsupport)" - puts stdout " build/promotion commands will proceed with a NOTE; -dirty-abort would abort as unverifiable." + puts stdout " producing commands (mint/promote/bake) will proceed with a NOTE; -dirty-abort would abort as unverifiable." } elseif {![llength $_prov_warnings]} { puts stdout "src provenance: OK (no uncommitted fossil/git changes under src/)" - puts stdout " build/promotion commands (project packages modules libs vfs vfslibs bin bootsupport vfscommonupdate) will proceed without provenance warnings." + puts stdout " producing commands (bakehouse packages modules libs bake vfslibs bin bootsupport vfscommonupdate) will proceed without provenance warnings." } else { ::punkboot::print_provenance_warnings $_prov_warnings -norecap - puts stdout " build/promotion commands (project packages modules libs vfs vfslibs bin bootsupport vfscommonupdate) will WARN as above and proceed." - puts stdout " With -dirty-abort they would abort. To evaluate uncommitted source without building, use ' src' or ' src shell'." + puts stdout " producing commands (bakehouse packages modules libs bake vfslibs bin bootsupport vfscommonupdate) will WARN as above and proceed." + puts stdout " With -dirty-abort they would abort. To evaluate uncommitted source without minting or baking, use ' src' or ' src shell'." } # Kit boot-precondition gate status - whether a bake can refuse an unbootable kit puts stdout $sep @@ -4755,7 +4786,7 @@ if {$::punkboot::command eq "check"} { if {$_boot_available} { puts stdout "boot-precondition gate (G-125): ACTIVE" puts stdout " bake checks each kit's merged vfs for a tcl library (tcl_library/, lib/tcl./ or" - puts stdout " tcl./) before building it. A kit with none is reported under FAILED KITS and is" + puts stdout " tcl./) before baking it. A kit with none is reported under FAILED KITS and is" puts stdout " neither built nor deployed, so a previously deployed kit is never replaced by an artifact that" puts stdout " cannot initialise." } else { @@ -4770,7 +4801,7 @@ if {$::punkboot::command eq "check"} { puts stdout "payload/target arch scan (G-133): ACTIVE (advisory)" puts stdout " bake classifies each merged kit's binary libraries (*.dll/*.so/*.dylib header bytes - structural," puts stdout " nothing executed, cross-target kits included) against the kit's target platform and emits" - puts stdout " recapped BUILD-WARNINGs for wrong-arch libraries outside platform-discriminated subdirs" + puts stdout " recapped BAKE-WARNINGs for wrong-arch libraries outside platform-discriminated subdirs" puts stdout " (canonical - names and recognised vendor spellings such as win-x64 are exempt)." } else { puts stdout "payload/target arch scan (G-133): UNAVAILABLE (punkboot::utils vfs_binary_arch_report not loadable from bootsupport)" @@ -4783,7 +4814,7 @@ if {$::punkboot::command eq "check"} { if {$_off_available} { puts stdout "kit offset-style pin (G-134): ACTIVE (advisory)" puts stdout " bake probes each assembled kit image with punk::zip::archive_info and emits a recapped" - puts stdout " BUILD-WARNING when an attached zip payload records FILE-relative offsets (the pipeline" + puts stdout " BAKE-WARNING when an attached zip payload records FILE-relative offsets (the pipeline" puts stdout " emits archive-relative by construction; the G-128 stamper refuses file-relative by default)." puts stdout " plain/none results (no attached zip - e.g the metakit kit shape) are silence, not warnings." } else { @@ -4804,7 +4835,7 @@ if {$::punkboot::command eq "check"} { puts stdout " (mapvfs.toml smokerequire key; legacy mapvfs.config 5th entry element) have each one plain-'package require'd inside the built" puts stdout " artifact via its tclsh subcommand - the only check that sees resolution-order defects such as" puts stdout " a wrong-arch higher-versioned package shadowing a working copy. Failures are recapped" - puts stdout " BUILD-WARNINGs; cross-target kits skip with a stated reason; undeclared kits run nothing new." + puts stdout " BAKE-WARNINGs; cross-target kits skip with a stated reason; undeclared kits run nothing new." if {[llength $_smoke_declared]} { puts stdout " declared: [join $_smoke_declared {; }]" } else { @@ -4995,7 +5026,7 @@ if {$::punkboot::command eq "workflow"} { if {$::punkboot::command eq "bakelist"} { #G-121: report the kit outputs configured in src/runtime/mapvfs.config, consuming #the same parsed mapping model as the bake kit machinery (::punkboot::lib::mapvfs_*). - #Reporting only - never builds. Data rows are single-line and column-stable for + #Reporting only - never bakes. Data rows are single-line and column-stable for #grepping; expected state sits in the columns, anomalies surface in a trailing #sparse notes column (key=value tags). Kit name arguments filter the report and #add a per-kit detail block (resolved paths/sizes/mtimes). @@ -5007,7 +5038,7 @@ if {$::punkboot::command eq "bakelist"} { set rt_os_arch [punkboot::lib::platform_store_tier $rt_default_target] set rtbase $binfolder/runtime set rtfolder $rtbase/$rt_os_arch - set buildfolder $sourcefolder/_build + set bakefolder $sourcefolder/_bake set mapfile [punkboot::lib::mapvfs_locate $sourcefolder/runtime] set mapmodel [punkboot::lib::mapvfs_model $sourcefolder/runtime $rtbase $sourcefolder $rt_default_target] foreach errline [dict get $mapmodel configerrors] { @@ -5076,12 +5107,12 @@ if {$::punkboot::command eq "bakelist"} { set runtime [dict get $rec runtime] set vfstail [dict get $rec vfs] #G-127: deploy-state roots follow the record's output tier (non-default - #targets live under kits// in both bin/ and src/_build/) + #targets live under kits// in both bin/ and src/_bake/) set out_tier [dict get $rec out_tier] if {$out_tier eq ""} { - set deployed [punkboot::lib::kit_deploy_state $buildfolder $binfolder [dict get $rec targetkit]] + set deployed [punkboot::lib::kit_deploy_state $bakefolder $binfolder [dict get $rec targetkit]] } else { - set deployed [punkboot::lib::kit_deploy_state $buildfolder/$out_tier $binfolder/$out_tier [dict get $rec targetkit]] + set deployed [punkboot::lib::kit_deploy_state $bakefolder/$out_tier $binfolder/$out_tier [dict get $rec targetkit]] } set notes [list] if {$runtime ne "-" && ![dict get $rec runtime_present]} { @@ -5094,7 +5125,7 @@ if {$::punkboot::command eq "bakelist"} { #cross-target entry: its runtime, store tier and artifact naming follow #its own platform, not this host's default lappend notes target=[dict get $rec target] - #G-127: and its build/deploy locations sit under the kits// tier + #G-127: and its bake/deploy locations sit under the kits// tier lappend notes out=$out_tier/ } if {[dict get $rec group] ne ""} { @@ -5136,7 +5167,7 @@ if {$::punkboot::command eq "bakelist"} { append map_display " (deprecated format)" } } - puts stdout "# mapvfs: $map_display runtimes: bin/runtime/$rt_os_arch$rt_store_note deployed: bin/ vs src/_build/ (out= rows: under kits//)" + puts stdout "# mapvfs: $map_display runtimes: bin/runtime/$rt_os_arch$rt_store_note deployed: bin/ vs src/_bake/ (out= rows: under kits//)" set headline "" foreach h $headings w $widths { append headline [format "%-*s " $w $h] @@ -5176,10 +5207,10 @@ if {$::punkboot::command eq "bakelist"} { if {[dict get $rec group] ne ""} { puts stdout " group: [dict get $rec group][expr {[dict get $rec bake_default] ? "" : " (bake_default=false - bake by name or @[dict get $rec group])"}]" } elseif {![dict get $rec bake_default]} { - puts stdout " bake_default: false (excluded from full bakes - bake by name to build)" + puts stdout " bake_default: false (excluded from full bakes - bake it by name)" } set relkit [expr {[dict get $rec out_tier] eq "" ? [dict get $rec targetkit] : "[dict get $rec out_tier]/[dict get $rec targetkit]"}] - puts stdout " build product: src/_build/$relkit [punkboot::lib::bakelist_file_detail $buildfolder/$relkit]" + puts stdout " bake product: src/_bake/$relkit [punkboot::lib::bakelist_file_detail $bakefolder/$relkit]" puts stdout " deployed: bin/$relkit [punkboot::lib::bakelist_file_detail $binfolder/$relkit] state=[lindex $row 4]" } } @@ -6114,7 +6145,7 @@ if {$::punkboot::command eq "bootsupport"} { #Project layouts store no bootsupport module snapshots - 'dev project.new' injects bootsupport #into generated projects from the generating shell at generation time. Layout-carried scripts #and bootsupport manifests are kept current by the thin-layout sync step (see DIAGRAM 1b in - #::punkboot::workflow_text), which runs during modules/libs/packages/bakehouse builds. + #::punkboot::workflow_text), which runs during modules/libs/packages/bakehouse runs. puts stdout " bootsupport done " flush stderr @@ -6434,7 +6465,7 @@ if {$::punkboot::command ni {bakehouse packages modules libs bake vfslibs bin}} -#external libs and modules first - and any supporting files - no 'building' required +#external libs and modules first - and any supporting files - no minting required #install src vendor contents (from version controlled src folder) to base of project (same target folders as our own src/modules etc ie to paths that go on the auto_path and in tcl::tm::list) @@ -6962,7 +6993,7 @@ if {$::punkboot::command in {bakehouse packages modules libs}} { #store -> modpod payload sync: the punk::mix::templates module ships the thin punk.project layout #so module-pathtype layout refs resolve and a bare kit outside any project can generate from it. - #The modpod copy is build-managed - do not hand-edit it. Excludes: bin/sdx.kit (no new binaries + #The modpod copy is sync-managed - do not hand-edit it. Excludes: bin/sdx.kit (no new binaries #inside zip-based .tm modules). (The unimplemented child-side src/PROJECT_LAYOUTS_* marker was #retired by G-087 stage 5 - thin layouts + generation-time injection made it moot.) set store_layout $sourcefolder/project_layouts/vendor/punk/project-0.1 @@ -6978,7 +7009,7 @@ if {$::punkboot::command in {bakehouse packages modules libs}} { -installer make.tcl -overwrite installedsourcechanged-targets -createempty 1 - -exclude-paths-core {#* **/#* _aside **/_aside _build **/_build .git **/.git} + -exclude-paths-core {#* **/#* _aside **/_aside _build **/_build _mint **/_mint _bake **/_bake .git **/.git} -exclude-paths {bin/sdx.kit} }] puts stdout [punkcheck::summarize_install_resultdict $resultdict] @@ -7084,7 +7115,7 @@ if {$::punkboot::command ni {bakehouse bake bin}} { #command = packages/modules/libs/vfslibs - stops before kit assembly puts stdout "vfs folders not checked" puts stdout " - use 'make.tcl vfscommonupdate' to promote built modules into the base vfs folder (promotion gate - commit for provenance)" - puts stdout " - use 'make.tcl bake' to build executable kits/zipkits from the vfs folders if you have runtimes installed" + puts stdout " - use 'make.tcl bake' to bake executable kits/zipkits from the vfs folders if you have runtimes installed" puts stdout " Note that without the vfscommonupdate step, 'make.tcl bake' will include any manual changes in the *custom* vfs folders but" puts stdout " without the latest built modules." puts stdout " calling 'builtexename(.exe) dev' will allow testing of built modules before they are baked into the kits/zipkits via 'vfscommonupdate' then 'bake'" @@ -7094,9 +7125,18 @@ if {$::punkboot::command ni {bakehouse bake bin}} { } -set buildfolder [punk::mix::cli::lib::get_build_workdir $sourcefolder] -if {$buildfolder ne "$sourcefolder/_build"} { - puts stderr "$sourcefolder/_build doesn't match the project buildfolder $buildfolder - check project filestructure" +#G-155: the bake workdir resolver was renamed get_build_workdir -> get_bake_workdir with the +#src/_build -> src/_bake flip. Fall back to a direct mkdir when driving a stale punk::mix +#snapshot (old bootsupport, or a generated project mid-update) so the mixed state stays runnable. +if {[llength [info commands ::punk::mix::cli::lib::get_bake_workdir]]} { + set bakefolder [punk::mix::cli::lib::get_bake_workdir $sourcefolder] +} else { + puts stderr "NOTE: punk::mix snapshot predates get_bake_workdir (G-155) - using $sourcefolder/_bake directly. Refresh with 'make.tcl modules' + 'make.tcl bootsupport'." + file mkdir $sourcefolder/_bake + set bakefolder $sourcefolder/_bake +} +if {$bakefolder ne "$sourcefolder/_bake"} { + puts stderr "$sourcefolder/_bake doesn't match the project bakefolder $bakefolder - check project filestructure" puts stdout " -aborted- " exit 2 } @@ -7134,7 +7174,7 @@ set rt_sourcefolder $sourcefolder/runtime ;#where our config lives #driving tclsh's platform. The copy is the same binary as its source, so it must #keep the source's executable convention - an .exe stays an .exe whether a native #windows tclsh, an msys/cygwin-runtime tclsh (platform 'unix', .exe files) or a -#cross-target host is driving the build. +#cross-target host is driving the bake. #Mapping key for a runtime FILE name: the name as mapvfs.config spells it, i.e #with a windows .exe suffix removed. Only .exe may be stripped - 'file rootname' #would eat the last dotted segment of version-named runtimes such as tclsh9.0.5, @@ -7200,7 +7240,7 @@ proc ::punkboot::runtime_materialization_warning {rtfolder runtime_fullname} { set current_rev [dict get $stale current_rev] set maxrev [dict get $stale maxrev] set maxname [dict get $stale maxname] - ::punkboot::print_build_warnings [list "runtime $runtime_fullname working copy is materialized from revision r$current_rev but $maxname (r$maxrev) is present beside it - kits wrapping this runtime get r$current_rev. To bake with r$maxrev: bin/punk-runtime.cmd use $maxname then re-run the bake"] + ::punkboot::print_bake_warnings [list "runtime $runtime_fullname working copy is materialized from revision r$current_rev but $maxname (r$maxrev) is present beside it - kits wrapping this runtime get r$current_rev. To bake with r$maxrev: bin/punk-runtime.cmd use $maxname then re-run the bake"] } return } @@ -7238,7 +7278,7 @@ if {[llength $missing]} { #declaration. A missing runtime FILE is environment, not declaration: store #tiers are legitimately part-populated (fresh clones; runtimes arrive via the #consent-gated fetch tiers), so those entries skip with a recapped - #BUILD-WARNING naming the entry (cross-target wording states the tier reason). + #BAKE-WARNING naming the entry (cross-target wording states the tier reason). #bake_default=false entries are not in the full-bake set; selective bakes #fail fast at selection instead. set _strict_fatal [list] @@ -7268,7 +7308,7 @@ if {[llength $missing]} { exit 3 } if {[llength $_strict_warn]} { - ::punkboot::print_build_warnings $_strict_warn + ::punkboot::print_bake_warnings $_strict_warn } unset -nocomplain _rec _entrylabel _strict_fatal _strict_warn _line } else { @@ -7359,7 +7399,7 @@ dict for {_rtname _rttarget} $runtime_target { continue ;#absent cross-target runtime already warned by the parse } if {[dict exists $rtfolder_of $_file]} { - puts stderr "WARNING: runtime file $_file is present in more than one store tier ([dict get $rtfolder_of $_file] and $_dir) - using the first found. Rename one of them to build both." + puts stderr "WARNING: runtime file $_file is present in more than one store tier ([dict get $rtfolder_of $_file] and $_dir) - using the first found. Rename one of them to bake both." continue } lappend runtimes $_file @@ -7370,14 +7410,14 @@ if {[llength $cross_target_tiers]} { } unset -nocomplain _rtname _rttarget _tier _dir _file if {![llength $runtimes]} { - puts stderr "No executable runtimes found in $rtfolder - unable to build any .vfs folders into executables." + puts stderr "No executable runtimes found in $rtfolder - unable to bake any .vfs folders into executables." puts stderr "Add runtimes to $rtfolder if required" if {![file isdirectory $rtfolder]} { #same store-tier self-diagnosis as bakelist puts stderr "NOTE: that runtime store folder does not exist. Default target '$rt_default_target' derives from THIS tclsh: tcl_platform(os)='$::tcl_platform(os)' tcl_platform(platform)='$::tcl_platform(platform)' -> host canon '$::punkboot::host_platform' -> target '$rt_default_target'." puts stderr " Populate it with 'bin/punk-runtime.cmd' (or by hand), or declare a per-entry target platform in mapvfs.toml for runtimes stored elsewhere." } - #todo - don't exit - it is valid to use runtime of - to just build a .kit/.zipkit ? + #todo - don't exit - it is valid to use runtime of - to just bake a .kit/.zipkit ? exit 0 } #G-121 selective bake: restrict processing to the runtimes the selected kits wrap - @@ -7494,7 +7534,7 @@ dict for {vfstail -} $vfs_runtime_map { } } #G-121 selective bake: only the selected kits' vfs folders get checked/checksummed - -#other vfs folders' punkcheck build events never fire. +#other vfs folders' punkcheck bake events never fire. if {[llength $::punkboot::bake_selected_kitnames]} { set vfs_tails [lmap _vt $vfs_tails { if {$_vt ni $::punkboot::bake_selected_vfs} { @@ -7505,22 +7545,22 @@ if {[llength $::punkboot::bake_selected_kitnames]} { unset -nocomplain _vt } if {![llength $vfs_tails]} { - puts stdout "No .vfs folders found at '$sourcefolder/vfs' - no kits to build" + puts stdout "No .vfs folders found at '$sourcefolder/vfs' - no kits to bake" puts stdout " -done- " exit 0 } -set vfs_folder_changes [dict create] ;#cache whether each .vfs folder has changes so we don't re-run tests if building from same .vfs with multiple runtime executables +set vfs_folder_changes [dict create] ;#cache whether each .vfs folder has changes so we don't re-run tests if baking from same .vfs with multiple runtime executables # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- -#make build copy for all runtimes - not just those in the map - because even without a mapvfs.config file entry we build an exe for a runtime that matches .vfs folder name - REVIEW. +#make build copy for all runtimes - not just those in the map - because even without a mapvfs.config file entry we bake an exe for a runtime that matches .vfs folder name - REVIEW. foreach runtimefile $runtimes { #runtimefile e.g tclkit86bi.exe for a win32 target, tclkit86bi for a posix one - #sdx *may* be pointed to use the runtime we use to build the kit, or the user may manually use this runtime if they don't have tclsh + #sdx *may* be pointed to use the runtime we use to bake the kit, or the user may manually use this runtime if they don't have tclsh #sdx will complain if the same runtime is used for the shell as is used in the -runtime argument - so we make a copy (REVIEW) - #if {![file exists $buildfolder/buildruntime.exe]} { - # file copy $rtfolder/$runtimefile $buildfolder/buildruntime.exe + #if {![file exists $bakefolder/buildruntime.exe]} { + # file copy $rtfolder/$runtimefile $bakefolder/buildruntime.exe #} #G-122: each runtime is read from the tier its target platform names, not @@ -7540,18 +7580,18 @@ foreach runtimefile $runtimes { set useruntimefile $runtimefile } - set basedir $buildfolder + set basedir $bakefolder set config [dict create {*}{ -make-step copy_runtime }] #---------- set installer [punkcheck::installtrack new $installername $basedir/.punkcheck] - $installer set_source_target $rt_dir $buildfolder + $installer set_source_target $rt_dir $bakefolder set event [$installer start_event $config] - $event targetset_init INSTALL $buildfolder/build_$runtimefile + $event targetset_init INSTALL $bakefolder/build_$runtimefile #$event targetset_addsource $rt_dir/$runtimefile $event targetset_addsource $rt_dir/$useruntimefile ;#possibly the _BUILDCOPY in the runtime folder (created for when mounted in current executable as a tclkit) - $event targetset_addsource $buildfolder/build_$runtimefile ;#self as source for change detection + $event targetset_addsource $bakefolder/build_$runtimefile ;#self as source for change detection #---------- #set changed_unchanged [punkcheck::recordlist::file_install_record_source_changes [lindex [dict get $file_record body] end]] @@ -7562,11 +7602,11 @@ foreach runtimefile $runtimes { $event targetset_started # -- --- --- --- --- --- #This is the full runtime - *possibly* with some sort of vfs attached. - puts stdout "Copying runtime (as is) from $rt_dir/$useruntimefile to $buildfolder/build_$runtimefile" + puts stdout "Copying runtime (as is) from $rt_dir/$useruntimefile to $bakefolder/build_$runtimefile" if {[catch { - file copy -force $rt_dir/$useruntimefile $buildfolder/build_$runtimefile ;#becomes building_runtime + file copy -force $rt_dir/$useruntimefile $bakefolder/build_$runtimefile ;#becomes baking_runtime } errM]} { - puts stderr " >> copy runtime to $buildfolder/build_$runtimefile FAILED" + puts stderr " >> copy runtime to $bakefolder/build_$runtimefile FAILED" $event targetset_end FAILED } else { $event targetset_end OK @@ -7804,7 +7844,7 @@ proc vfs_startup_script_warning {vfsfolder} { append detail "; main.tcl fauxlink target '$linktarget' does not exist" } } - return "vfs folder $vfsfolder has NO STARTUP SCRIPT: no root main.tcl and no root fauxlink resolving to main.tcl with an existing .tcl target - kits built from it will have no boot script (build proceeding anyway)$detail" + return "vfs folder $vfsfolder has NO STARTUP SCRIPT: no root main.tcl and no root fauxlink resolving to main.tcl with an existing .tcl target - kits built from it will have no boot script (bake proceeding anyway)$detail" } #Cat-style zipkit assembly: a raw (vfs-free) runtime followed by a freshly built #zip, concatenated. This is the zipfs-less assembly path for BOTH zip-type kits @@ -7845,7 +7885,7 @@ proc ::punkboot::assemble_zipcat_image {raw_runtime wrapvfs outfile zipfile} { # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- #G-057 kit icon step. Every built kit gets a .resources.toml sidecar -#recording the build-time icon choice (default src/runtime/punkshell.ico, +#recording the bake-time icon choice (default src/runtime/punkshell.ico, #overridable by a root-level punkshell.ico in the kit's own custom .vfs folder, #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 @@ -7856,7 +7896,7 @@ proc ::punkboot::assemble_zipcat_image {raw_runtime wrapvfs outfile zipfile} { #adopted from the first replaced group; idempotent by construction, parity #recorded in the G-128 detail file): the vendored punkres portable stamper #(G-128, src/tools/punkres, built by 'make.tcl tool build punkres') is -#selected when bin/punkres(.exe) exists and works from ANY build host; +#selected when bin/punkres(.exe) exists and works from ANY bake 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 @@ -8195,12 +8235,12 @@ proc ::punkboot::kit_icon_embed_twapi {exepath icopath {group_override {}}} { #G-057 single internal entry point. Decides the kit's icon (override: root #punkshell.ico in the kit's own custom .vfs folder, pre-merge; else the project #default src/runtime/punkshell.ico), writes/refreshes the kit's -#.resources.toml sidecar in the build folder, and - when the target +#.resources.toml sidecar in the bake folder, and - when the target #has PE resources and this host can write them - stamps a per-kit copy of the #payload-free raw runtime prefix. Returns {wrap_runtime sidecarpath}: #wrap_runtime is the runtime prefix the assembly step must consume (the stamped #copy when embedding happened, the untouched raw prefix otherwise). -proc ::punkboot::kit_icon_process {targetkit rt_target rtname kit_type sourcefolder vfstail raw_runtime buildfolder} { +proc ::punkboot::kit_icon_process {targetkit rt_target rtname kit_type sourcefolder vfstail raw_runtime bakefolder} { set repo_root [file dirname $sourcefolder] set override_icon $sourcefolder/vfs/$vfstail/punkshell.ico if {[file isfile $override_icon]} { @@ -8253,7 +8293,7 @@ proc ::punkboot::kit_icon_process {targetkit rt_target rtname kit_type sourcefol } set wrap_runtime $raw_runtime if {$status eq ""} { - set stamped $buildfolder/iconed_$targetkit + set stamped $bakefolder/iconed_$targetkit file copy -force $raw_runtime $stamped catch {exec chmod +w $stamped} if {$punkres_ok} { @@ -8264,7 +8304,7 @@ proc ::punkboot::kit_icon_process {targetkit rt_target rtname kit_type sourcefol set embed_cmd [list ::punkboot::kit_icon_embed_twapi $stamped $icon_path $icon_group] } 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_bake_warnings [list "kit icon embedding FAILED for $targetkit ($icon_origin icon $icon_path via $embedding): $embed_result - kit keeps its runtime's own icon"] set status failed set reason $embed_result catch {file delete $stamped} @@ -8303,7 +8343,7 @@ proc ::punkboot::kit_icon_process {targetkit rt_target rtname kit_type sourcefol lappend lines "embedding = \"$embedding\"" lappend lines "embedding_status = \"$status\"" lappend lines "embedding_reason = \"[$esc $reason]\"" - set sidecar $buildfolder/$targetkit.resources.toml + set sidecar $bakefolder/$targetkit.resources.toml ::punkboot::kiticon::writefile_ifchanged $sidecar "[join $lines \n]\n" return [list $wrap_runtime $sidecar] } @@ -8311,18 +8351,18 @@ proc ::punkboot::kit_icon_process {targetkit rt_target rtname kit_type sourcefol set startdir [pwd] puts stdout "Found [llength $vfs_tails] .vfs folders - checking each for executables that may need to be built" -cd [file dirname $buildfolder] +cd [file dirname $bakefolder] #root folder mtime is insufficient for change detection. Tree mtime of folders only is a barely passable mechanism for vfs change detection in some circumstances - e.g if files added/removed but never edited in place #a hash of full tree file & dir mtime may be more reasonable - but it remains to be seen if just tar & checksum is any/much slower. #Simply rebuilding all the time may be close the speed of detecting change anyway - and almost certainly much faster when there is a change. -#Using first mtime encountered that is later than target is another option - but likely to be highly variable in speed. Last file in the tree could happen to be the latest, and this mechanism doesn't handle build on reversion to older source. +#Using first mtime encountered that is later than target is another option - but likely to be highly variable in speed. Last file in the tree could happen to be the latest, and this mechanism doesn't handle re-bake on reversion to older source. set exe_names_seen [list] set path_cksum_cache [dict create] dict set path_cksum_cache {*}[punk::mix::base::lib::get_relativecksum_from_base $basedir $sourcefolder/vfs/_vfscommon.vfs] # -# loop over vfs_tails and for each one, loop over configured (or matching) runtimes - build with sdx or zipfs if source .vfs or source runtime exe has changed. -# we are using punkcheck to install result to buildfolder so we create a .punkcheck file at the target folder to store metadata. +# loop over vfs_tails and for each one, loop over configured (or matching) runtimes - bake with sdx or zipfs if source .vfs or source runtime exe has changed. +# we are using punkcheck to install result to bakefolder so we create a .punkcheck file at the target folder to store metadata. # punkcheck allows us to not rely purely on timestamps (which may be unreliable) # foreach vfstail $vfs_tails { @@ -8330,11 +8370,11 @@ foreach vfstail $vfs_tails { set vfsname [file rootname $vfstail] puts stdout " ------------------------------------" puts stdout " checking vfs $sourcefolder/vfs/$vfstail for configured runtimes" - set skipped_vfs_build 0 + set skipped_vfs_bake 0 # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- - set basedir $buildfolder + set basedir $bakefolder set config [dict create {*}{ - -make-step build_vfs + -make-step bake_vfs }] @@ -8366,7 +8406,7 @@ foreach vfstail $vfs_tails { } } else { #only match this vfs to a correspondingly named runtime if there was no explicit entry for that runtime - #review - should this only be done if there are NO explicit entries? how does a user stop builds of unneeded exes that match without renaming files/folders? + #review - should this only be done if there are NO explicit entries? how does a user stop bakes of unneeded exes that match without renaming files/folders? #but conversely, adding an extra entry shouldn't stop default builds that used to run.. set matchrt [file rootname [file tail $vfstail]] ;#e.g project.vfs -> project if {![dict exists $runtime_vfs_map $matchrt]} { @@ -8385,7 +8425,7 @@ foreach vfstail $vfs_tails { #(e.g _vfscommon.vfs is a merge overlay with no runtime mapping and legitimately has no main.tcl) set startup_warning [vfs_startup_script_warning $sourcefolder/vfs/$vfstail] if {$startup_warning ne ""} { - ::punkboot::print_build_warnings [list $startup_warning] + ::punkboot::print_bake_warnings [list $startup_warning] } } #todo - non kit based - zipkit? @@ -8452,21 +8492,21 @@ foreach vfstail $vfs_tails { lassign $targetkit_info targetkit target_kit_type kit_smokerequires kit_attrs #G-127: output locations are keyed by the kit's TARGET. Kits for this #host's own default target keep the flat locations every launcher, test - #and habit expects (src/_build/, bin/); any other target's kit + #and habit expects (src/_bake/, bin/); any other target's kit #builds and deploys under a kits// tier so same-named kits for #different targets coexist instead of overwriting each other across #selective runs. bin/kits/ rather than bin// because #bin/runtime// already means build INPUTS. if {$rt_target eq $rt_default_target} { - set kit_builddir $buildfolder + set kit_bakedir $bakefolder set kit_deploydir $binfolder - set kit_relpath $targetkit ;#kit path relative to bin/ and src/_build/ + set kit_relpath $targetkit ;#kit path relative to bin/ and src/_bake/ } else { - set kit_builddir $buildfolder/kits/$rt_target + set kit_bakedir $bakefolder/kits/$rt_target set kit_deploydir $binfolder/kits/$rt_target set kit_relpath kits/$rt_target/$targetkit } - file mkdir $kit_builddir + file mkdir $kit_bakedir #G-024: bake_default=false entries (declared per entry or via their group) #are excluded from full bakes - explicit name/@group selection builds them. if {![llength $::punkboot::bake_selected_kitnames] @@ -8493,11 +8533,11 @@ foreach vfstail $vfs_tails { set self_exe [file normalize [info nameofexecutable]] set self_deploy_target [file normalize $kit_deploydir/$targetkit] if {$::punkboot::host_windows} { - set is_self_build [string equal -nocase $self_exe $self_deploy_target] + set is_self_bake [string equal -nocase $self_exe $self_deploy_target] } else { - set is_self_build [string equal $self_exe $self_deploy_target] + set is_self_bake [string equal $self_exe $self_deploy_target] } - if {$is_self_build} { + if {$is_self_bake} { puts stderr "SKIPPING kit $targetkit - its deployed executable is the one running this build ($self_exe)" puts stderr " Rerun 'make.tcl $::punkboot::command' under tclsh or a different built kit to rebuild $targetkit." lappend skipped_kits [list kit $targetkit reason "deployed executable is running this build"] @@ -8505,9 +8545,9 @@ foreach vfstail $vfs_tails { } # -- ---------- set vfs_installer [punkcheck::installtrack new $installername $basedir/.punkcheck] - $vfs_installer set_source_target $sourcefolder $buildfolder - set vfs_event [$vfs_installer start_event {-make-step build_vfs}] - $vfs_event targetset_init INSTALL $kit_builddir/$targetkit + $vfs_installer set_source_target $sourcefolder $bakefolder + set vfs_event [$vfs_installer start_event {-make-step bake_vfs}] + $vfs_event targetset_init INSTALL $kit_bakedir/$targetkit set relvfs [punkcheck::lib::path_relative $basedir $sourcefolder/vfs/$vfstail] if {![dict exists $path_cksum_cache $relvfs]} { #e.g ../vfs/punk87.vfs {cksum xxxx cksum_all_opts {-cksum_content 1 ... -cksum_algorithm sha1}} @@ -8523,11 +8563,11 @@ foreach vfstail $vfs_tails { $vfs_event targetset_addsource $sourcefolder/runtime/punkshell.ico } if {$rtname ne "-"} { - set building_runtime $buildfolder/build_$runtime_fullname ;#working copy of runtime executable - (possibly with kit/zipfs/cookfs etc attached!) - $vfs_event targetset_addsource $building_runtime + set baking_runtime $bakefolder/build_$runtime_fullname ;#working copy of runtime executable - (possibly with kit/zipfs/cookfs etc attached!) + $vfs_event targetset_addsource $baking_runtime set raw_runtime "" ;#building runtime with vfs (zip,kit,cookfs etc stripped) } else { - set building_runtime "-" ;#REVIEW + set baking_runtime "-" ;#REVIEW set raw_runtime "-" } # -- ---------- @@ -8541,18 +8581,18 @@ foreach vfstail $vfs_tails { $vfs_event targetset_started # -- --- --- --- --- --- - if {[file exists $buildfolder/$vfsname.new]} { - puts stderr "deleting existing $buildfolder/$vfsname.new" - file delete $buildfolder/$vfsname.new + if {[file exists $bakefolder/$vfsname.new]} { + puts stderr "deleting existing $bakefolder/$vfsname.new" + file delete $bakefolder/$vfsname.new } package require fileutil package require fileutil::traverse package require control - #keep this a simple name - bin/punk script calls into src/_build/exename.vfs/main.tcl + #keep this a simple name - bin/punk script calls into src/_bake/exename.vfs/main.tcl #(G-127: non-default-target kits keep the simple name under their kits// tier) - set targetvfs $kit_builddir/$targetkit.vfs + set targetvfs $kit_bakedir/$targetkit.vfs file delete -force $targetvfs set extraction_done 0 @@ -8623,7 +8663,7 @@ foreach vfstail $vfs_tails { #zipfs mkimg replaces the entire zipped vfs in the runtime - so we need the original data to be part of our targetvfs. puts stdout "Attempting to extract zip vfs data from $runtime_fullname" file mkdir $targetvfs - set raw_runtime $buildfolder/raw_$runtime_fullname + set raw_runtime $bakefolder/raw_$runtime_fullname if {[info commands ::tcl::zipfs::mount] ne ""} { #the driving tcl has zipfs @@ -8631,13 +8671,13 @@ foreach vfstail $vfs_tails { if {![file exists $rtmountpoint]} { if {[catch { - tcl::zipfs::mount $building_runtime rtmounts/$runtime_fullname + tcl::zipfs::mount $baking_runtime rtmounts/$runtime_fullname } errM]} { - puts stderr "Failed to mount $building_runtime using standard api. Err:$errM\n trying reverse args on tcl::zipfs::mount..." + puts stderr "Failed to mount $baking_runtime using standard api. Err:$errM\n trying reverse args on tcl::zipfs::mount..." if {[catch { - tcl::zipfs::mount rtmounts/$runtime_fullname $building_runtime + tcl::zipfs::mount rtmounts/$runtime_fullname $baking_runtime } errM]} { - puts stderr "ALSO Failed to mount $building_runtime using reverse args to api. Err:$errM - no mountable zipfs on runtime?" + puts stderr "ALSO Failed to mount $baking_runtime using reverse args to api. Err:$errM - no mountable zipfs on runtime?" } } } @@ -8656,7 +8696,7 @@ foreach vfstail $vfs_tails { if {$baseoffset != 0} { #tcl was able to determine the compressed-data offset #either because runtime is a basic catted exe+zip, or Tcl fixed 'zipfs info' - set fdrt [open $building_runtime r] + set fdrt [open $baking_runtime r] chan configure $fdrt -translation binary set exedata [read $fdrt $baseoffset] ;#may include stored password and ending header // REVIEW - strip it? close $fdrt @@ -8665,21 +8705,21 @@ foreach vfstail $vfs_tails { puts -nonewline $fdraw $exedata close $fdraw } else { - #presumably the supplied building_runtime has had its offsets adjusted so that it all appears within offsets off the zip. (file relative offsets) + #presumably the supplied baking_runtime has had its offsets adjusted so that it all appears within offsets off the zip. (file relative offsets) #due to zipfs info bug - zipfs now can't tell us the offset of the compressed data. #we need to use a similarly assumptive method as tclZipfs.c uses to determine the start of the compressed contents package require punk::zip #we don't technically need to extract the raw exe for 'zip' - as zipfs mkimg can work on the combined file (ignores zip) # - but for consistency we want raw_runtime to be emitted in the filesystem. file delete $raw_runtime - punk::zip::extract_preamble $building_runtime $raw_runtime + punk::zip::extract_preamble $baking_runtime $raw_runtime } } else { - #the input building_runtime wasn't mountable as a zip - so presumably a plain executable + #the input baking_runtime wasn't mountable as a zip - so presumably a plain executable #runtime executable possibly with kit/cookfs etc attached? #If not - init.tcl probably won't be found? should we even proceed ?? puts stderr "[punkboot::sgr 31]WARNING the runtime was not mountable as a zip - which means tcl_library was not extracted - the executable may not work with zipfs attached![punkboot::sgr]" - file copy -force $building_runtime $raw_runtime + file copy -force $baking_runtime $raw_runtime } } else { #The driving tcl we are calling with doesn't have zipfs - can't mount. @@ -8687,7 +8727,7 @@ foreach vfstail $vfs_tails { #so this path needs no zipfs, no vfs::zip and no tcllib. package require punk::zip puts stdout "tcl shell '[info nameofexecutable]' being used to build doesn't have zipfs - reading the runtime's attached archive with punk::zip" - set extractedzipfolder $buildfolder/extracted_$runtime_fullname + set extractedzipfolder $bakefolder/extracted_$runtime_fullname file delete $raw_runtime file delete -force $extractedzipfolder if {![catch { @@ -8696,8 +8736,8 @@ foreach vfstail $vfs_tails { #derived base offset: a runtime whose offsets are file-relative #splits into a .zip no plain zip reader accepts, and reading the #whole file sidesteps that intermediate entirely. - punk::zip::extract_preamble $building_runtime $raw_runtime - punk::zip::unzip -return none -- $building_runtime $extractedzipfolder + punk::zip::extract_preamble $baking_runtime $raw_runtime + punk::zip::unzip -return none -- $baking_runtime $extractedzipfolder } extracterr]} { set extraction_done 1 set extract_kit_type $extract_kit_try @@ -8733,7 +8773,7 @@ foreach vfstail $vfs_tails { #unlike cookit's //cookit:/ it doesn't show up in file volumes #set rtmountpoint //cookfstemp:/rtmounts/$runtime_fullname ;#not writable with 'file mkdir' which doesn't seem to handle intermediate nonexistant path set rtmountpoint //cookfstemp:/$runtime_fullname - cookfs::Mount $building_runtime $rtmountpoint + cookfs::Mount $baking_runtime $rtmountpoint if {[file exists $rtmountpoint]} { #copy from mounted runtime's vfs to the filesystem vfs merge_over $rtmountpoint $targetvfs @@ -8754,37 +8794,37 @@ foreach vfstail $vfs_tails { continue ;#to next extraction attempt } - set raw_runtime $buildfolder/raw_$runtime_fullname + set raw_runtime $bakefolder/raw_$runtime_fullname #for a kit, we shouldn't need to extract the existing vfs from the runtime. # - the sdx merge process should be able to merge our .vfs folder with the existing contents. #2025 - in practice this doesn't always seem to be the case? Review - could have been cwd issue? - puts stdout "Attempting to split kitfile using: $::sdxpath mksplit $building_runtime" + puts stdout "Attempting to split kitfile using: $::sdxpath mksplit $baking_runtime" set prev_cwd [pwd] - cd [file dirname $building_runtime] ;#make sure SDX is called with the same working dir as the files we're working on. - if {[catch {exec {*}$::sdxpath mksplit $building_runtime} mksplitresult]} { + cd [file dirname $baking_runtime] ;#make sure SDX is called with the same working dir as the files we're working on. + if {[catch {exec {*}$::sdxpath mksplit $baking_runtime} mksplitresult]} { #executable doesn't have kit vfs attached - puts stderr "No kit data extracted from $building_runtime" - file copy -force $building_runtime $raw_runtime + puts stderr "No kit data extracted from $baking_runtime" + file copy -force $baking_runtime $raw_runtime } else { puts stdout "mksplitresult: $mksplitresult" - if {![file exists [file rootname $building_runtime].tail]} { - error "mksplit didn't produce file at [file rootname $building_runtime].tail" + if {![file exists [file rootname $baking_runtime].tail]} { + error "mksplit didn't produce file at [file rootname $baking_runtime].tail" } - file delete -force [file rootname $building_runtime].vfs ;#ensure target for unwrap doesn't exist - #set kit_bare_runtime [file rootname $building_runtime].head - set building_runtime [file rootname $building_runtime].head - exec {*}$::sdxpath unwrap [file rootname $building_runtime].tail ;#extracts to folder named [file rootname $building_runtime].vfs e.g build_tclkit9.0.2-win64-dyn.vfs + file delete -force [file rootname $baking_runtime].vfs ;#ensure target for unwrap doesn't exist + #set kit_bare_runtime [file rootname $baking_runtime].head + set baking_runtime [file rootname $baking_runtime].head + exec {*}$::sdxpath unwrap [file rootname $baking_runtime].tail ;#extracts to folder named [file rootname $baking_runtime].vfs e.g build_tclkit9.0.2-win64-dyn.vfs #file rename to existing target dir would copy folder into target dir if {![file exists $targetvfs]} { #delay after 1000 - file rename [file rootname $building_runtime].vfs $targetvfs + file rename [file rootname $baking_runtime].vfs $targetvfs } else { - merge_over [file rootname $building_runtime].vfs $targetvfs + merge_over [file rootname $baking_runtime].vfs $targetvfs } set extraction_done 1 set extract_kit_type $extract_kit_try - file copy -force $building_runtime $raw_runtime + file copy -force $baking_runtime $raw_runtime } cd $prev_cwd @@ -8795,12 +8835,12 @@ foreach vfstail $vfs_tails { set extraction_tried "$target_kit_type[expr {[llength $source_kit_caps] ? " + runtime caps $source_kit_caps" : ""}]" if {!$extraction_done} { #TODO: if not extracted - use a default tcl_library for patchlevel and platform? - #Recapped BUILD-WARNING (not just an inline note): this line would + #Recapped BAKE-WARNING (not just an inline note): this line would #otherwise scroll away behind thousands of merge lines. It is a warning #rather than the failure itself because a .vfs that supplies its own tcl #library needs no extraction - the G-125 gate below decides, on the #merged tree, whether this kit can initialise. - ::punkboot::print_build_warnings [list "No extraction done from runtime $runtime_fullname (tried: $extraction_tried) - kit $targetkit gets no tcl library from the runtime, so it will FAIL the boot-precondition gate unless src/vfs/$vfstail supplies one"] + ::punkboot::print_bake_warnings [list "No extraction done from runtime $runtime_fullname (tried: $extraction_tried) - kit $targetkit gets no tcl library from the runtime, so it will FAIL the boot-precondition gate unless src/vfs/$vfstail supplies one"] file mkdir $targetvfs } @@ -8830,7 +8870,7 @@ foreach vfstail $vfs_tails { puts stderr "--------------------------------------------" #G-030 prompt policy: only an interactive 'y' can force building a mismatched #kit - non-interactive runs (and -confirm 0) skip this kit and continue. - set _build_anyway 0 + set _bake_anyway 0 if {!$::punkboot::opt_confirm} { puts stderr "skipping kit $targetkit (source/target kit type mismatch; -confirm 0 policy is to skip)" } elseif {![::punkboot::lib::stdin_is_interactive]} { @@ -8838,10 +8878,10 @@ foreach vfstail $vfs_tails { } else { puts stdout "Continue to try to build $targetkit from $rtname anyway? y|n" if {[string tolower [string trim [gets stdin]]] eq "y"} { - set _build_anyway 1 + set _bake_anyway 1 } } - if {!$_build_anyway} { + if {!$_bake_anyway} { #skip to next kit continue } @@ -8873,7 +8913,7 @@ foreach vfstail $vfs_tails { puts stdout " per-platform payload (G-127): selecting _targets/$rt_target into the merged image for kit $targetkit" merge_over $_pstaging/$rt_target $targetvfs } else { - ::punkboot::print_build_warnings [list "per-platform payload (G-127): kit $targetkit (target $rt_target) - the merged vfs has a _targets/ staging tree but no _targets/$rt_target subtree, so this kit gets NO per-platform payload (check the %platform% declarations in src/vfs/$vfstail.toml against the kit's mapvfs target)"] + ::punkboot::print_bake_warnings [list "per-platform payload (G-127): kit $targetkit (target $rt_target) - the merged vfs has a _targets/ staging tree but no _targets/$rt_target subtree, so this kit gets NO per-platform payload (check the %platform% declarations in src/vfs/$vfstail.toml against the kit's mapvfs target)"] } file delete -force $_pstaging } @@ -8903,7 +8943,7 @@ foreach vfstail $vfs_tails { if {[llength $archscan_mismatches] > $shown} { lappend archwarnings "payload/target arch mismatch in kit $targetkit (target $rt_target): [expr {[llength $archscan_mismatches] - $shown}] further mismatching binary libraries not listed above ([llength $archscan_mismatches] mismatches total, [dict get $archscan scanned] binary libraries scanned)" } - ::punkboot::print_build_warnings $archwarnings + ::punkboot::print_bake_warnings $archwarnings unset archwarnings archscan_mismatches shown } else { puts stdout " payload binary-arch scan for kit $targetkit (target $rt_target): OK - [dict get $archscan scanned] binary libraries scanned ([dict get $archscan matched] match target, [dict get $archscan exempt] exempt under platform subdirs, [dict get $archscan unknown] unclassifiable)" @@ -8944,7 +8984,7 @@ foreach vfstail $vfs_tails { #the assemblers below consume wrap_runtime - the stamped per-kit copy #of the payload-free raw prefix when embedding happened, the untouched #raw prefix otherwise. Runtime store originals are never modified. - lassign [::punkboot::kit_icon_process $targetkit $rt_target $rtname $target_kit_type $sourcefolder $vfstail $raw_runtime $kit_builddir] wrap_runtime kiticon_sidecar + lassign [::punkboot::kit_icon_process $targetkit $rt_target $rtname $target_kit_type $sourcefolder $vfstail $raw_runtime $kit_bakedir] wrap_runtime kiticon_sidecar set wrapvfs $targetvfs switch -- $target_kit_type { @@ -8975,14 +9015,14 @@ foreach vfstail $vfs_tails { } if {[info commands ::tcl::zipfs::mkimg] ne ""} { #note - as at 2024-08 - there is some discussion about the interface to mkimg - it is considered unstable (may change to -option value syntax) - puts stderr "calling: tcl::zipfs::mkimg $buildfolder/$vfsname.new $wrapvfs $wrapvfs \"\" $wrap_runtime" - tcl::zipfs::mkimg $buildfolder/$vfsname.new $wrapvfs $wrapvfs "" $wrap_runtime + puts stderr "calling: tcl::zipfs::mkimg $bakefolder/$vfsname.new $wrapvfs $wrapvfs \"\" $wrap_runtime" + tcl::zipfs::mkimg $bakefolder/$vfsname.new $wrapvfs $wrapvfs "" $wrap_runtime } else { #G-122: the driving tcl has no zipfs (8.6) - assemble the same #kind of image by concatenation. The result mounts on any #zipfs-capable runtime (archive-start-relative offsets). puts stderr "WARNING: tcl shell '[info nameofexecutable]' has no zipfs - assembling zip kit $targetkit by concatenation (raw runtime + mkzip)" - ::punkboot::assemble_zipcat_image $wrap_runtime $wrapvfs $buildfolder/$vfsname.new $buildfolder/$vfsname.zip + ::punkboot::assemble_zipcat_image $wrap_runtime $wrapvfs $bakefolder/$vfsname.new $bakefolder/$vfsname.zip } } result ]} { set failmsg "zipfs mkimg failed with msg: $result" @@ -9019,7 +9059,7 @@ foreach vfstail $vfs_tails { } #'archive' based zip offsets - editable in 7z,peazip - ::punkboot::assemble_zipcat_image $wrap_runtime $wrapvfs $buildfolder/$vfsname.new $buildfolder/$vfsname.zip + ::punkboot::assemble_zipcat_image $wrap_runtime $wrapvfs $bakefolder/$vfsname.new $bakefolder/$vfsname.zip } result ]} { set failmsg "creating zipcat image failed with msg: $result" puts stderr "creating image (zipcat) $targetkit failed" @@ -9047,7 +9087,7 @@ foreach vfstail $vfs_tails { continue } else { if {[catch { - #we still have the $building_runtime mounted + #we still have the $baking_runtime mounted if {[catch { merge_over $targetvfs $rtmountpoint } errM]} { @@ -9063,14 +9103,14 @@ foreach vfstail $vfs_tails { #copy the version that is mounted in this runtime to vfsname.new if {[catch { - file copy -force $building_runtime $buildfolder/$vfsname.new - catch {exec chmod +w $buildfolder/$vfsname.new} + file copy -force $baking_runtime $bakefolder/$vfsname.new + catch {exec chmod +w $bakefolder/$vfsname.new} } errM]} { - puts stderr "$target_kit_type 'file copy -force $building_runtime $buildfolder/$vfsname.new' failed\n$errM" + puts stderr "$target_kit_type 'file copy -force $baking_runtime $bakefolder/$vfsname.new' failed\n$errM" error $errM } } result]} { - puts stderr "Writing vfs data and opying cookfs file $building_runtime to $buildfolder/$vfsname.new failed\n $result" + puts stderr "Writing vfs data and opying cookfs file $baking_runtime to $bakefolder/$vfsname.new failed\n $result" lappend failed_kits [list kit $targetkit reason copy_failed] $vfs_event targetset_end FAILED $vfs_event destroy @@ -9088,21 +9128,21 @@ foreach vfstail $vfs_tails { kit { set verbose "" #set verbose "-verbose" - #assert: building_runtime has been replaced with $kit_bare_runtime + #assert: baking_runtime has been replaced with $kit_bare_runtime set prev_cwd [pwd] - cd [file dirname $building_runtime] ;#make sure SDX is called with the same working dir as the files we're working on. + cd [file dirname $baking_runtime] ;#make sure SDX is called with the same working dir as the files we're working on. if {[catch { if {$rtname ne "-"} { - exec {*}$::sdxpath wrap $buildfolder/$vfsname.new -vfs $wrapvfs -runtime $wrap_runtime {*}$verbose + exec {*}$::sdxpath wrap $bakefolder/$vfsname.new -vfs $wrapvfs -runtime $wrap_runtime {*}$verbose } else { - exec {*}$::sdxpath wrap $buildfolder/$vfsname.new -vfs $wrapvfs {*}$verbose + exec {*}$::sdxpath wrap $bakefolder/$vfsname.new -vfs $wrapvfs {*}$verbose } } result]} { if {$rtname ne "-"} { - set sdxmsg "$::sdxpath wrap $buildfolder/$vfsname.new -vfs $wrapvfs -runtime $wrap_runtime {*}$verbose failed with msg: $result" + set sdxmsg "$::sdxpath wrap $bakefolder/$vfsname.new -vfs $wrapvfs -runtime $wrap_runtime {*}$verbose failed with msg: $result" } else { - set sdxmsg "$::sdxpath wrap $buildfolder/$vfsname.new -vfs $wrapvfs {*}$verbose failed with msg: $result" + set sdxmsg "$::sdxpath wrap $bakefolder/$vfsname.new -vfs $wrapvfs {*}$verbose failed with msg: $result" } puts stderr "$::sdxpath wrap $targetkit failed" lappend failed_kits [list kit $targetkit reason $sdxmsg] @@ -9122,9 +9162,9 @@ foreach vfstail $vfs_tails { } - if {![file exists $buildfolder/$vfsname.new]} { - puts stderr "|err> make.tcl build didn't seem to produce output at $buildfolder/$vfsname.new" - lappend failed_kits [list kit $targetkit reason "build failed to produce output at $buildfolder/$vfsname.new"] + if {![file exists $bakefolder/$vfsname.new]} { + puts stderr "|err> make.tcl build didn't seem to produce output at $bakefolder/$vfsname.new" + lappend failed_kits [list kit $targetkit reason "build failed to produce output at $bakefolder/$vfsname.new"] $vfs_event targetset_end FAILED $vfs_event destroy $vfs_installer destroy @@ -9244,13 +9284,13 @@ foreach vfstail $vfs_tails { } } - if {[file exists $kit_builddir/$targetkit]} { - puts stderr "deleting existing $kit_builddir/$targetkit" + if {[file exists $kit_bakedir/$targetkit]} { + puts stderr "deleting existing $kit_bakedir/$targetkit" if {[catch { - file delete $kit_builddir/$targetkit + file delete $kit_bakedir/$targetkit } msg]} { - puts stderr "Failed to delete $kit_builddir/$targetkit" - lappend failed_kits [list kit $targetkit reason "could not delete buildfolder kit at $kit_builddir/$targetkit"] + puts stderr "Failed to delete $kit_bakedir/$targetkit" + lappend failed_kits [list kit $targetkit reason "could not delete bakefolder kit at $kit_bakedir/$targetkit"] $vfs_event targetset_end FAILED $vfs_event destroy $vfs_installer destroy @@ -9260,23 +9300,23 @@ foreach vfstail $vfs_tails { #WINDOWS filesystem 'tunnelling' (file replacement within 15secs) could cause targetkit to copy ctime & shortname metadata from previous file! #This is probably harmless - but worth being aware of. - file rename $buildfolder/$vfsname.new $kit_builddir/$targetkit + file rename $bakefolder/$vfsname.new $kit_bakedir/$targetkit # -- --- --- --- --- --- $vfs_event targetset_end OK #G-134 post-assembly offset-style pin: the pipeline emits #ARCHIVE-relative zip payloads by construction - this probe makes #that a checked contract. Advisory per the G-133 posture: a - #file-relative image earns a recapped BUILD-WARNING (the G-128 + #file-relative image earns a recapped BAKE-WARNING (the G-128 #stamper would refuse it by default) and the kit still builds and #deploys; plain/none (no attached zip - the metakit kit shape) and #unreadable results are silence. One EOCD scan + CD walk per #REBUILT kit only. - lassign [::punkboot::get_kit_offsetstyle_report $kit_builddir/$targetkit] offprobe_available offprobe + lassign [::punkboot::get_kit_offsetstyle_report $kit_bakedir/$targetkit] offprobe_available offprobe if {!$offprobe_available} { puts stderr "NOTE: kit offset-style pin unavailable (punkboot::utils kit_offsetstyle_report not loadable from bootsupport) - continuing without it" } elseif {[dict get $offprobe offsetstyle] eq "file"} { - ::punkboot::print_build_warnings [list "kit $targetkit assembled with a FILE-relative zip payload (G-134 pin: the pipeline emits archive-relative by construction; the G-128 stamper refuses file-relative by default) - investigate this kit's assembly path"] + ::punkboot::print_bake_warnings [list "kit $targetkit assembled with a FILE-relative zip payload (G-134 pin: the pipeline emits archive-relative by construction; the G-128 stamper refuses file-relative by default) - investigate this kit's assembly path"] } #G-133 post-build smoke-require probe. Only an actual 'package require' @@ -9292,12 +9332,12 @@ foreach vfstail $vfs_tails { puts stdout " smoke-require skipped for kit $targetkit: cross-target ($rt_target) - the artifact is not executable on this $::punkboot::host_platform host" } else { puts stdout " smoke-require probe for kit $targetkit (packages: $kit_smokerequires) - executing freshly built artifact via its tclsh subcommand" - ::punkboot::kit_smoke_require_probe $kit_builddir/$targetkit $targetkit $kit_smokerequires + ::punkboot::kit_smoke_require_probe $kit_bakedir/$targetkit $targetkit $kit_smokerequires } } } else { - set skipped_vfs_build 1 + set skipped_vfs_bake 1 puts stderr "." puts stdout "Skipping build for vfs $vfstail with runtime $rtname - no change detected" lappend skipped_kits [list kit $targetkit reason "no change detected"] @@ -9317,14 +9357,14 @@ foreach vfstail $vfs_tails { # -- ---------- set bin_installer [punkcheck::installtrack new "make.tcl" $deployment_folder/.punkcheck] - $bin_installer set_source_target $buildfolder $deployment_folder + $bin_installer set_source_target $bakefolder $deployment_folder set bin_event [$bin_installer start_event {-make-step final_kit_install}] $bin_event targetset_init INSTALL $deployment_folder/$targetkit - #todo - move final deployment step outside of the build vfs loop? (final deployment can fail and then isn't rerun even though _build and deployed versions differ, unless .vfs modified again) + #todo - move final deployment step outside of the bake vfs loop? (final deployment can fail and then isn't rerun even though _bake and deployed versions differ, unless .vfs modified again) #set last_completion [$bin_event targetset_last_complete] $bin_event targetset_addsource $deployment_folder/$targetkit ;#add target as a source of metadata for change detection - $bin_event targetset_addsource $kit_builddir/$targetkit + $bin_event targetset_addsource $kit_bakedir/$targetkit $bin_event targetset_started # -- ---------- @@ -9347,14 +9387,14 @@ foreach vfstail $vfs_tails { } puts stdout "copying.." - puts stdout "$kit_builddir/$targetkit" + puts stdout "$kit_bakedir/$targetkit" puts stdout "to:" puts stdout "$deployment_folder/$targetkit" after 300 - file copy $kit_builddir/$targetkit $deployment_folder/$targetkit + file copy $kit_bakedir/$targetkit $deployment_folder/$targetkit #G-057: the kit resource sidecar ships with the kit - if {[file isfile $kit_builddir/$targetkit.resources.toml]} { - file copy -force $kit_builddir/$targetkit.resources.toml $deployment_folder/$targetkit.resources.toml + if {[file isfile $kit_bakedir/$targetkit.resources.toml]} { + file copy -force $kit_bakedir/$targetkit.resources.toml $deployment_folder/$targetkit.resources.toml } lappend installed_kits $kit_relpath # -- ---------- @@ -9367,7 +9407,7 @@ foreach vfstail $vfs_tails { #G-057: keep the deployed resource sidecar current even when the kit #itself is unchanged (the record can be newer than the kit rebuild - #e.g the sidecar feature arriving, or a host-capability change) - if {[::punkboot::kiticon::copy_ifchanged $kit_builddir/$targetkit.resources.toml $deployment_folder/$targetkit.resources.toml] eq "copied"} { + if {[::punkboot::kiticon::copy_ifchanged $kit_bakedir/$targetkit.resources.toml $deployment_folder/$targetkit.resources.toml] eq "copied"} { puts stdout " kit icon (G-057): refreshed deployed sidecar $deployment_folder/$targetkit.resources.toml" } lappend skipped_kit_installs [list kit $targetkit reason "no change detected"] diff --git a/src/modules/AGENTS.md b/src/modules/AGENTS.md index 28711680..56eb249f 100644 --- a/src/modules/AGENTS.md +++ b/src/modules/AGENTS.md @@ -16,8 +16,8 @@ Source of truth for all editable Punk project modules. This is where agents shou - Module filenames use the literal suffix `-999999.0a1.0.tm`. - Corresponding `-buildversion.txt` files hold the real version number. - The exception is `punk::libunknown`, which is manually versioned: the real `major.minor.patch` version lives in the filename (e.g `libunknown-.tm`) and there is no buildversion.txt. The same bump rules apply as for buildversion-tracked modules (see "Versioning And Releases"); the mechanics differ — see the manual-versioning bullet there. (`punk::mix::base` was converted from manual to the magic-version scheme 2026-07-21.) -- `#modpod-*` directories contain internal files packed into `.tm` archives during build; do not flatten or edit them without understanding the modpod format. -- `_build/` directory holds build intermediates and should not be manually edited. +- `#modpod-*` directories contain internal files packed into `.tm` archives during the mint; do not flatten or edit them without understanding the modpod format. +- `_mint/` directory (renamed from `_build/` under G-155) holds mint staging intermediates and should not be manually edited; stale `_build/` copies may remain in old checkouts. - Always declare dependencies explicitly using `package require ` near file tops. - Prefer fully qualified namespaces when referencing external packages, such as `package require tcl::zlib` or `package require TclOO`. - Organize custom modules as namespaces mirroring directory structure, such as `namespace eval punk::` or deeper paths like `punk::lib::util::`. @@ -43,7 +43,7 @@ Source of truth for all editable Punk project modules. This is where agents shou - Prefer Unix-style LF line endings for `.tm` source files in this tree. - If the same proc exists in both `src/modules/` and `src/modules_tcl/`, prefer `src/modules/` unless version-specific behavior is relevant or only the version-specific file is active. - Use `deck module.new ` or `punk::mix::commandset::module::new` to scaffold new modules. -- Run `tclsh src/make.tcl modules` to build modules, or `tclsh src/make.tcl bakehouse` for a full build from a clean checkout (the deprecated `project` alias still maps). +- Run `tclsh src/make.tcl modules` to mint modules, or `tclsh src/make.tcl bakehouse` for a full consumer run from a clean checkout. - When adding a new proc to a `.tm` file, add a PUNKARGS `argdoc` block immediately before it — even if the proc parses arguments manually and the PUNKARGS is documentation-only. "User-facing" includes any proc in an exported namespace, not just shell commands. Developer-facing utility procs (e.g `punk::lib::*`) are not exempt. ### Formatting And Layout @@ -357,5 +357,5 @@ Before writing or generating punk::args definitions, know the mechanisms punk::a - `punk/` — Core punk namespace modules (see punk/AGENTS.md) - `opunk/` — Alternative punk namespace, voo-based classes (opunk::str, opunk::console) (see opunk/AGENTS.md) -- `punkcheck/` — Build/check system (punkcheck + punkcheck::cli) +- `punkcheck/` — Install/provenance-check system (punkcheck + punkcheck::cli) - `test/` — Installed-module test packages (see test/AGENTS.md) diff --git a/src/modules/punk/mix/base-999999.0a1.0.tm b/src/modules/punk/mix/base-999999.0a1.0.tm index aab7a735..f9879afe 100644 --- a/src/modules/punk/mix/base-999999.0a1.0.tm +++ b/src/modules/punk/mix/base-999999.0a1.0.tm @@ -344,7 +344,7 @@ namespace eval punk::mix::base { } #we can return module paths even if the project isn't yet under revision control set src_subs [glob -nocomplain -dir [file join $candidate src] -type d -tail *] - set antipatterns [list *.vfs vendor* lib _build doc embedded runtime bootsupport] + set antipatterns [list *.vfs vendor* lib _build _mint _bake doc embedded runtime bootsupport] set tm_folders [list] foreach sub $src_subs { set is_ok 1 @@ -411,17 +411,23 @@ namespace eval punk::mix::base { return [string map {:: /} $nsq] } - proc get_build_workdir {path} { + proc get_bake_workdir {path} { set repo_info [punk::repo::find_repos $path] set base [lindex [dict get $repo_info project] 0] if {![string length $base]} { - error "get_build_workdir unable to determine project base for path '$path'" + error "get_bake_workdir unable to determine project base for path '$path'" } if {![file exists $base/src] || ![file writable $base/src]} { - error "get_build_workdir unable to access $base/src" + error "get_bake_workdir unable to access $base/src" } - file mkdir $base/src/_build - return $base/src/_build + file mkdir $base/src/_bake + return $base/src/_bake + } + #legacy name (pre-G-155 stage vocabulary; workdir was src/_build) - old make.tcl copies in + #generated projects may still call this. Delegates to the renamed resolver; retirement is a + #G-156 decision. + proc get_build_workdir {path} { + return [get_bake_workdir $path] } @@ -963,86 +969,12 @@ namespace eval punk::mix::base { return [dict create $storedpath $keyvals] } - #calculate the runtime checksum and vfs checksums - proc get_all_vfs_build_cksums {path {cksum_opts {}}} { - set buildfolder [get_build_workdir $path] - set cksum_base_folder [file dirname $buildfolder] ;#this is the /src folder - a reasonable base for our vfs cksums - set dict_cksums [dict create] - - set buildrelpath [punk::repo::path_strip_alreadynormalized_prefixdepth $buildfolder $cksum_base_folder] - set vfs_tail_list [glob -nocomplain -dir $cksum_base_folder -type d -tails *.vfs] - - foreach vfstail $vfs_tail_list { - set vname [file rootname $vfstail] - dict set dict_cksums $vfstail [list cksum ""] - dict set dict_cksums [file join $buildrelpath $vname.exe] [list cksum ""] - } - - #buildruntime.exe obsolete.. - puts stderr "warning obsolete? get_all_vfs_build_cksums 'buildruntime.exe'???" - set fullpath_buildruntime $buildfolder/buildruntime.exe - - set ckinfo_buildruntime [cksum_path $fullpath_buildruntime] - set ck [dict get $ckinfo_buildruntime cksum] - - - set relpath [file join $buildrelpath "buildruntime.exe"] - dict set dict_cksums $relpath [list cksum $ck opts $cksum_opts] - - set dict_cksums [fill_relativecksums_from_base_and_relativepathdict $cksum_base_folder $dict_cksums] - - return $dict_cksums - } - - proc get_vfs_build_cksums_stored {vfsfolder} { - set vfscontainer [file dirname $vfsfolder] - set buildfolder $vfscontainer/_build - set vfs [file tail $vfsfolder] - set vname [file rootname $vfs] - set dict_vfs [list $vname.vfs "" $vname.exe "" buildruntime.exe ""] - set ckfile $buildfolder/$vname.cksums - if {[file exists $ckfile]} { - set data [punk::mix::util::fcat -translation binary $ckfile] - foreach ln [split $data \n] { - if {[string trim $ln] eq ""} {continue} - lassign $ln path cksum - dict set dict_vfs $path $cksum - } - } - return $dict_vfs - } - proc get_all_build_cksums_stored {path} { - set buildfolder [get_build_workdir $path] - - set vfscontainer [file dirname $buildfolder] - set vfslist [glob -nocomplain -dir $vfscontainer -type d -tail *.vfs] - set dict_cksums [dict create] - foreach vfs $vfslist { - set vname [file rootname $vfs] - set dict_vfs [get_vfs_build_cksums_stored $vfscontainer/$vfs] - - dict set dict_cksums $vname $dict_vfs - } - return $dict_cksums - } - - proc store_vfs_build_cksums {vfsfolder} { - if {![file isdirectory $vfsfolder]} { - error "Unable to find supplied vfsfolder: $vfsfolder" - } - set vfscontainer [file dirname $vfsfolder] - set buildfolder $vfscontainer/_build - set dict_vfs [get_vfs_build_cksums $vfsfolder] - set data "" - dict for {path cksum} $dict_vfs { - append data "$path $cksum" \n - } - set fd [open $buildfolder/$vname.cksums w] - chan configure $fd -translation binary - puts $fd $data - close $fd - return $dict_vfs - } + #The legacy vfs-cksums quartet (get_all_vfs_build_cksums, get_vfs_build_cksums_stored, + #get_all_build_cksums_stored, store_vfs_build_cksums) was RETIRED under G-155: repo-wide + #caller search found none, store_vfs_build_cksums called an undefined get_vfs_build_cksums + #(and an unset vname) so it can never have executed, and punkcheck records own the + #change-detection role the cksums files aimed at. Historical copies remain in older + #snapshots (src/vfs/*.vfs, mkzipfix.vfs). diff --git a/src/modules/punk/mix/base-buildversion.txt b/src/modules/punk/mix/base-buildversion.txt index b9e800bd..84659759 100644 --- a/src/modules/punk/mix/base-buildversion.txt +++ b/src/modules/punk/mix/base-buildversion.txt @@ -1,5 +1,6 @@ -0.1.2 +0.2.0 #First line must be a semantic version number #all other lines are ignored. +#0.2.0 - G-155 stage vocabulary: get_build_workdir renamed get_bake_workdir returning src/_bake; old name kept as a delegating alias for stale make.tcl copies (retirement is a G-156 decision); _mint/_bake added to find_source_module_paths antipatterns; RETIRED the never-called vfs-cksums quartet get_all_vfs_build_cksums/get_vfs_build_cksums_stored/get_all_build_cksums_stored/store_vfs_build_cksums (zero callers repo-wide; store_ called an undefined proc + unset var so it could never have executed - dead-code removal treated as non-breaking) #0.1.2 - fix: cksum_path hung forever on files on non-native (vfs-mounted e.g //zipfs:/) filesystems - the tcllib -file digest modes read via fileevent+vwait and vfs channels never deliver fileevents. Files on non-native filesystems are now slurped and digested in data mode (new cksum_data_command per algorithm incl new cksum_adler32_data/cksum_crc_data helpers; exec-based sha3 returns an unsupported_algorithm_for_vfs_path error for vfs paths). Needed for punkcheck::install from module-carried //zipfs:/ layout payloads (G-087 stage 3). #0.1.1 - fix: get_template_basefolders no-handler warning used 'put' instead of 'puts'; missing-handler path now warns and returns an empty dict instead of erroring on an unset variable diff --git a/src/modules/punk/mix/cli-999999.0a1.0.tm b/src/modules/punk/mix/cli-999999.0a1.0.tm index d33e8eb7..6e59bb2c 100644 --- a/src/modules/punk/mix/cli-999999.0a1.0.tm +++ b/src/modules/punk/mix/cli-999999.0a1.0.tm @@ -169,11 +169,11 @@ namespace eval punk::mix::cli { set lc_this_exe [string tolower [info nameofexecutable]] set lc_proj_bin [string tolower $project_base/bin] - set lc_build_bin [string tolower $project_base/src/_build] + set lc_bake_bin [string tolower $project_base/src/_bake] if {"project" in $args} { set is_own_exe 0 - if {[string match "${lc_proj_bin}*" $lc_this_exe] || [string match "${lc_build_bin}" $lc_this_exe]} { + if {[string match "${lc_proj_bin}*" $lc_this_exe] || [string match "${lc_bake_bin}" $lc_this_exe]} { set is_own_exe 1 puts stderr "WARNING - running make using executable that may be created by the project being built" set answer [util::askuser "Do you want to proceed using this executable? (build will probably stop when it is unable to update the executable) Y|N"] @@ -346,7 +346,7 @@ namespace eval punk::mix::cli { set opt_errorprefix [dict get $opts -errorprefix] # -- --- --- --- --- --- --- --- --- --- --- --- --- --- validate_name_not_empty_or_spaced $projectname -errorprefix $opt_errorprefix - set reserved_words [list etc lib bin modules src doc vendorlib vendormodules embedded runtime _aside _build] + set reserved_words [list etc lib bin modules src doc vendorlib vendormodules embedded runtime _aside _build _mint _bake] if {$projectname in $reserved_words } { error "$opt_errorprefix '$projectname' cannot be one of reserved_words: $reserved_words" } @@ -707,7 +707,7 @@ namespace eval punk::mix::cli { } proc build_modules_from_source_to_base {srcdir basedir args} { - set antidir [list "#*" "_build" "_aside" ".git" ".fossil*"] ;#exact or glob patterns for folders (at any level) we don't want to search in or copy. + set antidir [list "#*" "_build" "_mint" "_bake" "_aside" ".git" ".fossil*"] ;#exact or glob patterns for folders (at any level) we don't want to search in or copy. set defaults [list {*}{ -installer punk::mix::cli::build_modules_from_source_to_base -call-depth-internal 0 @@ -742,14 +742,13 @@ namespace eval punk::mix::cli { if {[file tail [file dirname $srcdir]] ne "src"} { puts stderr "ERROR build_modules_from_source_to_base can only be called with a srcdir that is a subfolder of your 'src' directory" puts stderr "The .tm modules are namespaced based on their directory depth - so we need to start at the root" - puts stderr "To build a subtree of your modules - use an appropriate src/modules folder and pass in the -subdirlist." - puts stderr "e.g if your modules are based at /x/src/modules2 and you wish to build only the .tm files at /x/src/modules2/skunkworks/lib" + puts stderr "To mint a subtree of your modules - use an appropriate src/modules folder and pass in the -subdirlist." + puts stderr "e.g if your modules are based at /x/src/modules2 and you wish to mint only the .tm files at /x/src/modules2/skunkworks/lib" puts stderr "Use: >build_modules_from_source_to_base /x/src/modules2 /x/modules2 -subdirlist {skunkworks lib}" exit 2 } set srcdirname [file tail $srcdir] - set build [file dirname $srcdir]/_build/$srcdirname ;#relative to *original* srcdir - not current_source_dir if {[llength $subdirlist] == 0} { set target_module_dir $basedir set current_source_dir $srcdir @@ -859,8 +858,8 @@ namespace eval punk::mix::cli { set module_build_version $tmfile_versionsegment } - set buildfolder $current_source_dir/_build - file mkdir $buildfolder + set mintfolder $current_source_dir/_mint + file mkdir $mintfolder # -- --- set config [dict create {*}{ -glob * @@ -870,13 +869,13 @@ namespace eval punk::mix::cli { # -max-depth -1 for no limit set build_installername pods_in_$current_source_dir - set build_installer [punkcheck::installtrack new $build_installername $buildfolder/.punkcheck] - #set build_installer [punkcheck::installtrack new $build_installername $buildfolder/.punkcheck stderr] ;#with debugchannel - $build_installer set_source_target $current_source_dir/$modpath $buildfolder + set build_installer [punkcheck::installtrack new $build_installername $mintfolder/.punkcheck] + #set build_installer [punkcheck::installtrack new $build_installername $mintfolder/.punkcheck stderr] ;#with debugchannel + $build_installer set_source_target $current_source_dir/$modpath $mintfolder set build_event [$build_installer start_event $config] # -- --- - set podtree_copy $buildfolder/#modpod-$basename-$module_build_version - set modulefile $buildfolder/$basename-$module_build_version.tm + set podtree_copy $mintfolder/#modpod-$basename-$module_build_version + set modulefile $mintfolder/$basename-$module_build_version.tm #todo - use modpod version as a source for change detection #package require modpod @@ -894,12 +893,12 @@ namespace eval punk::mix::cli { if {$did_skip} {set did_skip 0; puts -nonewline stdout \n} set delete_failed 0 - if {[file exists $buildfolder/]} { - puts stderr "deleting existing _build copy at $podtree_copy" + if {[file exists $mintfolder/]} { + puts stderr "deleting existing _mint copy at $podtree_copy" if {[catch { file delete -force $podtree_copy } errMsg]} { - puts stderr "[punk::ansi::a+ red]deletion of _build copy at $podtree_copy failed: $errMsg[punk::ansi::a]" + puts stderr "[punk::ansi::a+ red]deletion of _mint copy at $podtree_copy failed: $errMsg[punk::ansi::a]" set delete_failed 1 } } @@ -911,9 +910,9 @@ namespace eval punk::mix::cli { flush stdout file copy $current_source_dir/$modpath $podtree_copy if {$tmfile_versionsegment eq $magicversion} { - set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm + set tmfile $mintfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm if {[file exists $tmfile]} { - set newname $buildfolder/#modpod-$basename-$module_build_version/$basename-$module_build_version.tm + set newname $mintfolder/#modpod-$basename-$module_build_version/$basename-$module_build_version.tm file rename $tmfile $newname set tmfile $newname } @@ -927,20 +926,20 @@ namespace eval punk::mix::cli { #delete and regenerate zip and modpod stubbed zip set notes [list] if {[catch { - file delete $buildfolder/$basename-$module_build_version.zip + file delete $mintfolder/$basename-$module_build_version.zip } err] } { set had_error 1 lappend notes "zip_delete_failed" } if {[catch { - file delete $buildfolder/$basename-$module_build_version.tm + file delete $mintfolder/$basename-$module_build_version.tm } err]} { set had_error 1 lappend notes "tm_delete_failed" } #create ordinary zip file without using external executable package require punk::zip - set zipfile $buildfolder/$basename-$module_build_version.zip ;#ordinary zip file (deflate) + set zipfile $mintfolder/$basename-$module_build_version.zip ;#ordinary zip file (deflate) #zipfs mkzip does exactly what we need anyway in this case #unfortunately it's not available in all Tclsh versions we might be running.. @@ -949,7 +948,7 @@ namespace eval punk::mix::cli { #(Therefore no timestamps) #zip reading utils generally intuit their existence and display them - but often an editor can't add comments to them set wd [pwd] - cd $buildfolder + cd $mintfolder puts "zipfs mkzip $zipfile #modpod-$basename-$module_build_version" set mkzip_failed [catch {zipfs mkzip $zipfile #modpod-$basename-$module_build_version} errMkzip] cd $wd @@ -963,14 +962,14 @@ namespace eval punk::mix::cli { #archive variant; modpod stubs read both shapes). puts stderr "zipfs mkzip failed under Tcl [info patchlevel] ($errMkzip) - falling back to punk::zip::mkzip (known pre-c971e6c7c4 Tcl 8.7 zipfs dotfile defect - core tkt 7d5f1c13089d463e7796)" catch {file delete -- $zipfile} ;#a failed zipfs mkzip can leave a partial target zip - punk::zip::mkzip refuses to overwrite - punk::zip::mkzip -base $buildfolder -directory $buildfolder/#modpod-$basename-$module_build_version -- $zipfile * + punk::zip::mkzip -base $mintfolder -directory $mintfolder/#modpod-$basename-$module_build_version -- $zipfile * } } else { - #use -base $buildfolder so that -directory is included in the archive - the modpod stub relies on this - and extraction would be potentially messy otherwise + #use -base $mintfolder so that -directory is included in the archive - the modpod stub relies on this - and extraction would be potentially messy otherwise #put in an archive-level comment to aid in debugging #punk - punk::zip::mkzip -base $buildfolder -directory $buildfolder/#modpod-$basename-$module_build_version -- $zipfile * + punk::zip::mkzip -base $mintfolder -directory $mintfolder/#modpod-$basename-$module_build_version -- $zipfile * #punk::zip::mkzip stores permissions - (unix style) - which zipfs mkzip doesn't #Directory ident in zipfs relies on folders ending with trailing slash - if missing, it misidentifies dirs as files. #(ie it can't use permissions/attributes alone to determine directory vs file) @@ -1078,8 +1077,8 @@ namespace eval punk::mix::cli { set module_build_version $tmfile_versionsegment } - set buildfolder $current_source_dir/_build - file mkdir $buildfolder + set mintfolder $current_source_dir/_mint + file mkdir $mintfolder # -- --- set config [dict create {*}{ -glob * @@ -1089,12 +1088,12 @@ namespace eval punk::mix::cli { # -max-depth -1 for no limit set build_installername tarjars_in_$current_source_dir - set build_installer [punkcheck::installtrack new $build_installername $buildfolder/.punkcheck] - $build_installer set_source_target $current_source_dir/$modpath $buildfolder + set build_installer [punkcheck::installtrack new $build_installername $mintfolder/.punkcheck] + $build_installer set_source_target $current_source_dir/$modpath $mintfolder set build_event [$build_installer start_event $config] # -- --- - set podtree_copy $buildfolder/#tarjar-$basename-$module_build_version - set modulefile $buildfolder/$basename-$module_build_version.tm + set podtree_copy $mintfolder/#tarjar-$basename-$module_build_version + set modulefile $mintfolder/$basename-$module_build_version.tm $build_event targetset_init INSTALL $podtree_copy @@ -1110,12 +1109,12 @@ namespace eval punk::mix::cli { if {$did_skip} {set did_skip 0; puts -nonewline stdout \n} set delete_failed 0 - if {[file exists $buildfolder/]} { - puts stderr "deleting existing _build copy at $podtree_copy" + if {[file exists $mintfolder/]} { + puts stderr "deleting existing _mint copy at $podtree_copy" if {[catch { file delete -force $podtree_copy } errMsg]} { - puts stderr "[punk::ansi::a+ red]deletion of _build copy at $podtree_copy failed: $errMsg[punk::ansi::a]" + puts stderr "[punk::ansi::a+ red]deletion of _mint copy at $podtree_copy failed: $errMsg[punk::ansi::a]" set delete_failed 1 } } @@ -1126,7 +1125,7 @@ namespace eval punk::mix::cli { puts stdout "$podtree_copy" file copy $current_source_dir/$modpath $podtree_copy if {$tmfile_versionsegment eq $magicversion} { - set tmfile $buildfolder/#tarjar-$basename-$module_build_version/#tarjar-loadscript-$basename.tcl + set tmfile $mintfolder/#tarjar-$basename-$module_build_version/#tarjar-loadscript-$basename.tcl #we don't need to modify version or name of the loadscript if {![file exists $tmfile]} { set had_error 1 @@ -1150,16 +1149,16 @@ namespace eval punk::mix::cli { #delete and regenerate .tm set notes [list] if {[catch { - file delete $buildfolder/$basename-$module_build_version.tm + file delete $mintfolder/$basename-$module_build_version.tm } err]} { set had_error 1 lappend notes "tm_delete_failed" } #create ordinary tar file without using external executable package require tar ;#tcllib - set tarfile $buildfolder/$basename-$module_build_version.tm ;#ordinary tar file (no compression - store) + set tarfile $mintfolder/$basename-$module_build_version.tm ;#ordinary tar file (no compression - store) set wd [pwd] - cd $buildfolder + cd $mintfolder puts "tar::create $tarfile #tarjar-$basename-$module_build_version" if {[catch { tar::create $tarfile #tarjar-$basename-$module_build_version @@ -1269,23 +1268,23 @@ namespace eval punk::mix::cli { #} else { #} - ##REVIEW - should be in same structure/depth as $target_module_dir in _build? + ##REVIEW - should be in same structure/depth as $target_module_dir in _mint? ##TODO - #set buildfolder $current_sourcedir/_build - #file mkdir $buildfolder + #set mintfolder $current_sourcedir/_mint + #file mkdir $mintfolder - #set tmfile $buildfolder/$basename-$module_build_version.tm - #file delete -force $buildfolder/#tarjar-$basename-$module_build_version + #set tmfile $mintfolder/$basename-$module_build_version.tm + #file delete -force $mintfolder/#tarjar-$basename-$module_build_version #file delete -force $tmfile - #file copy -force $current_source_dir/#tarjar-$basename-$magicversion $buildfolder/#tarjar-$basename-$module_build_version + #file copy -force $current_source_dir/#tarjar-$basename-$magicversion $mintfolder/#tarjar-$basename-$module_build_version ## ##bsdtar doesn't seem to work.. or I haven't worked out the right options? - ##exec tar -cvf $buildfolder/$basename-$module_build_version.tm $buildfolder/#tarjar-$basename-$module_build_version + ##exec tar -cvf $mintfolder/$basename-$module_build_version.tm $mintfolder/#tarjar-$basename-$module_build_version #package require tar - #tar::create $tmfile $buildfolder/#tarjar-$basename-$module_build_version + #tar::create $tmfile $mintfolder/#tarjar-$basename-$module_build_version #if {![file exists $tmfile]} { # puts stdout "ERROR: failed to build tarjar file $tmfile" # exit 4 diff --git a/src/modules/punk/mix/cli-buildversion.txt b/src/modules/punk/mix/cli-buildversion.txt index 2d88d947..d70afc95 100644 --- a/src/modules/punk/mix/cli-buildversion.txt +++ b/src/modules/punk/mix/cli-buildversion.txt @@ -1,6 +1,7 @@ -0.5.2 +0.6.0 #First line must be a semantic version number #all other lines are ignored. +#0.6.0 - G-155 stage vocabulary: modpod/tarjar mint staging moved /_build -> /_mint (mintfolder var; _mint/_bake added to antidir + reserved_words, old _build stays tolerated); running-from-workdir check follows src/_build -> src/_bake; build_modules_from_source_to_base KEEPS its name (punkcheck -installer identity - G-156 owns any rename); mint-verb error text; removed a dead never-read 'build' path assignment #0.5.2 - modpod zip build: zipfs mkzip failure now falls back to punk::zip::mkzip (the established zipfs-less path) with a stderr note naming the interp and upstream ticket. Motivation: Tcl 8.7 builds predating core fix c971e6c7c4 (tkt 7d5f1c13089d463e7796 'zipfs mkzip broken on Windows dotfiles') die with 'non-unique path name' on dot-prefixed entries - hit by the templates modpod's layout .fossil-custom payloads (present since G-087 stage 3) when built under 8.7a6 #0.5.1 - comment-only: removed commented-out legacy punkcheck proc-pipeline call sites (installfile_begin/started/finished/skipped, start_installer_event) alongside their live OO equivalents - the legacy procs are retired to error shims in punkcheck 0.5.0 (G-094); no behaviour change #0.5.0 - added lib::prune_superseded_target_modules and lib::prune_sourcevanished_targets; build_modules_from_source_to_base now prunes punkcheck-recorded superseded module versions from target dirs (recorded as punkcheck DELETE events) and records virtual module_name/module_version sources on installs (punkcheck 0.3.0 targetset_addsource_virtual); requires punk::mix::util explicitly diff --git a/src/modules/punkboot/utils-999999.0a1.0.tm b/src/modules/punkboot/utils-999999.0a1.0.tm index 1073b1d5..2965fe67 100644 --- a/src/modules/punkboot/utils-999999.0a1.0.tm +++ b/src/modules/punkboot/utils-999999.0a1.0.tm @@ -749,7 +749,7 @@ namespace eval punkboot::utils { punkshell bake pipeline emits ARCHIVE-relative payloads by construction; this probe makes that a checked contract - a 'file' result is the pipeline-regression signal make.tcl - surfaces as a recapped BUILD-WARNING (advisory: the kit still + surfaces as a recapped BAKE-WARNING (advisory: the kit still builds and deploys). 'plain' (the file is a bare zip), 'none' (no zip attached - e.g the metakit kit shape, or any non-zip file) and 'unreadable' are silence, not warnings: the pin diff --git a/src/modules/punkboot/utils-buildversion.txt b/src/modules/punkboot/utils-buildversion.txt index 02323dd1..05175e34 100644 --- a/src/modules/punkboot/utils-buildversion.txt +++ b/src/modules/punkboot/utils-buildversion.txt @@ -1,6 +1,7 @@ -0.6.0 +0.6.1 #First line must be a semantic version number #all other lines are ignored. +#0.6.1 - doc-only: kit_offsetstyle_report argdoc names the recapped tag BAKE-WARNING (G-155 stage vocabulary; tag renamed from BUILD-WARNING in make.tcl) #0.6.0 - added kit_offsetstyle_report (advisory zip offset-style probe of an assembled kit image via punk::zip::archive_info; backs make.tcl's G-134 archive-relative output pin) #0.5.0 - added binary_arch_classify (PE/ELF/Mach-O header classifier, honest unknowns), platform_expected_binary, platform_discriminated_segment and vfs_binary_arch_report (advisory payload/target binary-arch scan of a merged .vfs tree with platform-subdir exemption; backs make.tcl's G-133 payload/target consistency checks) #0.4.0 - vfs_boot_library_report recognises a third tcl-library convention: tcl./ at the vfs root, used by runtimes whose archive mounts at the executable's own path rather than //zipfs:/app (the androwish/undroidwish zipfs backport for 8.6). Such a runtime was being refused as unbootable. 'checked' gains the new location. diff --git a/src/runtime/AGENTS.md b/src/runtime/AGENTS.md index ea0d9f6d..1b395cbf 100644 --- a/src/runtime/AGENTS.md +++ b/src/runtime/AGENTS.md @@ -1,8 +1,8 @@ -# src/runtime — Build Runtimes and VFS Configuration +# src/runtime — Kit Runtimes and VFS Configuration ## Purpose -Houses the `mapvfs.toml` kit mapping (VFS payloads paired with platform runtimes into named kit outputs), the `libpackages.toml` lib-tier artifact declarations, plus support files consumed during binary builds. +Houses the `mapvfs.toml` kit mapping (VFS payloads paired with platform runtimes into named kit outputs), the `libpackages.toml` lib-tier artifact declarations, plus support files consumed during kit bakes. ## Ownership @@ -11,9 +11,9 @@ Houses the `mapvfs.toml` kit mapping (VFS payloads paired with platform runtimes ## Local Contracts -- `mapvfs.toml` (G-024, tomlish-parsed) defines which `src/vfs/*.vfs` folders combine with which runtime binaries (stored under `bin/runtime//`) into which named kit outputs. The file's own header comment is the user-facing format spec; keep the two in step. `[kit.]` tables carry `runtime`, `vfs`, `type` (kit|zip|zipcat|cookit|cookfs), optional `target`, `smokerequire`, `group`, `bake_default`; `[group.]` tables name kit groupings (selectable in `bake`/`bakelist` as `@`; `bake_default = false` excludes members from full bakes while leaving them bakeable by name/group); `[scheme.]` tables are generative (G-023 `versioned` scheme: `-` + `-dev` + release-gated plain `` derived from `punkproject.toml` at parse time - the plain name is created when absent and never overwritten by a normal bake). Validation is strict and entry-named: unknown keys/types/schemes, conflicting targets and parse failures are fatal; a full bake refuses a default entry whose vfs folder is missing, and skips (recapped `BUILD-WARNING`) entries whose runtime file is absent from its store tier. Consumers read the parsed model (`::punkboot::lib::mapvfs_*`), never the file format. The pre-G-024 `mapvfs.config` line format remains readable as a DEPRECATED fallback (un-migrated generated projects; toml wins when both exist, legacy parses with a NOTE); the `PUNK_MAPVFS_CONFIG` env var points the reader at an alternate file (characterization-test seam). -- **Smoke-require packages (`smokerequire` key, 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. -- **Target platform (`target` key, G-122).** A kit entry may name the canonical punkshell platform its runtime is for (`help platforms` lists the names). It decides which `bin/runtime//` 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 sharing a runtime may repeat it but must not disagree (a conflict, or a name that is not an `-` 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 `[kit.punkshell902]` entry (target `linux-x86_64`, suffixless artifact). +- `mapvfs.toml` (G-024, tomlish-parsed) defines which `src/vfs/*.vfs` folders combine with which runtime binaries (stored under `bin/runtime//`) into which named kit outputs. The file's own header comment is the user-facing format spec; keep the two in step. `[kit.]` tables carry `runtime`, `vfs`, `type` (kit|zip|zipcat|cookit|cookfs), optional `target`, `smokerequire`, `group`, `bake_default`; `[group.]` tables name kit groupings (selectable in `bake`/`bakelist` as `@`; `bake_default = false` excludes members from full bakes while leaving them bakeable by name/group); `[scheme.]` tables are generative (G-023 `versioned` scheme: `-` + `-dev` + release-gated plain `` derived from `punkproject.toml` at parse time - the plain name is created when absent and never overwritten by a normal bake). Validation is strict and entry-named: unknown keys/types/schemes, conflicting targets and parse failures are fatal; a full bake refuses a default entry whose vfs folder is missing, and skips (recapped `BAKE-WARNING`) entries whose runtime file is absent from its store tier. Consumers read the parsed model (`::punkboot::lib::mapvfs_*`), never the file format. The pre-G-024 `mapvfs.config` line format remains readable as a DEPRECATED fallback (un-migrated generated projects; toml wins when both exist, legacy parses with a NOTE); the `PUNK_MAPVFS_CONFIG` env var points the reader at an alternate file (characterization-test seam). +- **Smoke-require packages (`smokerequire` key, 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 `BAKE-WARNING`s; cross-target kits skip with a stated reason; undeclared kits run nothing new. +- **Target platform (`target` key, G-122).** A kit entry may name the canonical punkshell platform its runtime is for (`help platforms` lists the names). It decides which `bin/runtime//` tier the runtime is read from (macosx-* collapsing to the universal `macosx` folder), whether the runtime file and the baked kit carry `.exe`, and whether the pre-deploy process sweep applies. It is a property of the RUNTIME: entries sharing a runtime may repeat it but must not disagree (a conflict, or a name that is not an `-` platform-dir name, is a fatal config error). Omitted means the bake 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 `[kit.punkshell902]` entry (target `linux-x86_64`, suffixless artifact). - Per-.vfs payload declarations (`src/vfs/.vfs.toml`, G-115) are the sibling declaration surface for what goes INSIDE a `.vfs` folder - format and precedence in `src/vfs/README.md`. The former per-package `vendorlib_vfs.toml` here was migrated into those files 2026-07-31 and retired (a leftover copy is ignored with a warning). - Runtime executables are placed in `bin/runtime//` 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 `.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. @@ -22,7 +22,7 @@ Houses the `mapvfs.toml` kit mapping (VFS payloads paired with platform runtimes ## Work Guidance -- When adding a new platform: create the runtime directory under `bin/runtime//`, add a VFS under `src/vfs/`, and add a `[kit.]` entry to `mapvfs.toml` - declaring the target platform on the entry when it is not the build host's default. +- When adding a new platform: create the runtime directory under `bin/runtime//`, add a VFS under `src/vfs/`, and add a `[kit.]` entry to `mapvfs.toml` - declaring the target platform on the entry when it is not the bake host's default. - Do not commit large binary runtimes to version control unless specifically required. ## Verification diff --git a/src/tests/modules/AGENTS.md b/src/tests/modules/AGENTS.md index ca168964..2059b302 100644 --- a/src/tests/modules/AGENTS.md +++ b/src/tests/modules/AGENTS.md @@ -38,7 +38,7 @@ Unit tests for editable source modules under `src/modules/`, `src/modules_tcl8/` ## Child DOX Index - `opunk/console/` — ::opunk::Console backend subclass tests (`testsuites/console/backends.test`, G-001): virtual dispatch of subclass overrides through base-class calls and punk::console::console_spec_resolve (both unchanged), TestConsole determinism + probe-free at_eof, SshConsole capability/eof + the flagship size-via-ANSI-query-over-socket case (a scripted remote terminal answers CSI 6n), TkConsole widget size/eof (gated behind env PUNK_TEST_TK=1 - Tk in the shared testinterp has side effects; also verifiable standalone under a tk-capable kit e.g `punk91 src