# G-125 A kit that cannot boot is not deployed Status: proposed Scope: src/make.tcl (kit extraction outcome handling, deploy step gating, the no-extraction BUILD-WARNING as the current behaviour being replaced); src/tests/shell/testsuites/punkexe/ (characterization of the gate); src/AGENTS.md (bake failure-mode documentation) Goal: a bake that could not lift a runtime's own payload (its tcl_library) into the kit fails that kit instead of building and deploying an artifact that cannot boot - so the worst outcome of a missing extraction capability is a red kit, never a silently replaced working executable. Acceptance: when extraction from the source runtime yields nothing and the kit's .vfs does not itself supply a bootable tcl library, the kit is recorded in FAILED KITS with a reason naming the cause and NEITHER src/_build nor bin receives a new artifact - the previously deployed kit is left untouched, verified by mtime and byte comparison across such a run; a kit whose .vfs legitimately supplies its own tcl library still builds and deploys, so the gate tests for the boot precondition rather than for the extraction step having run; the check is cheap enough to run on every kit and executes no artifact; the condition and its remedy are documented in src/AGENTS.md; existing punkexe suites pass unchanged and the gate itself is characterized. ## Context The kit machinery already knows when it failed to extract anything from a source runtime. Under G-122 (achieved - see goals/archive/G-122-host-target-platform-split.md) that notice was promoted from an inline stderr block to a recapped `BUILD-WARNING:` naming the kit and what was tried - but the build still proceeds, assembles an artifact, DELETES the deployed kit and copies the new one over it. The pre-deploy process sweep will even close running instances of the kit first. Field-observed 2026-07-26: an msys2-hosted bake of `punk91` produced a 49,501,792-byte `bin/punk91.exe` that failed at startup with application-specific initialization failed: Cannot find a usable init.tcl because the host's tclsh had no tcllib and therefore could not extract the runtime's own zip. The previously working kit had already been replaced by then. G-124 removes the particular cause, but not the class: a runtime with no attached payload at all, an extraction that fails for any other reason, or a future container type reaches the same state, and the build's response is still "warn and deploy". The existing precedent in the same code path is `vfs_startup_script_warning`, which warns about a missing `main.tcl` and continues - deliberately, because a kit without a startup script is legal. A kit without a resolvable tcl library is not in the same category: it cannot initialise at all. ## Approach - Gate on the BOOT PRECONDITION, not on the extraction step having run. Some .vfs folders legitimately supply their own tcl library (the merged `targetvfs` is what matters), so the check inspects the assembled tree rather than the extraction outcome - a runtime that needed no extraction must keep building. - Fail the kit the same way every other failure in that loop does (append to `failed_kits` with a reason, end the punkcheck event FAILED) BEFORE the artifact is renamed into place, so neither `src/_build/` nor `bin/` is touched and the punkcheck records stay consistent with what is on disk. - Keep it cheap and non-executing: a structural check of the merged vfs, no artifact launch, so it can run for every kit on every bake. - The recapped BUILD-WARNING wording changes from "will not initialise unless the vfs supplies one" to a failure reason, since the gate now enforces what the warning described. ## Alternatives considered - Keep warning and deploying, on the grounds that the developer sees the recap - rejected: the recap arrives after the deployed kit has already been replaced, and the failure surfaces later as an unexplained broken shell. A build tool should not make a working executable worse. - Boot the freshly built artifact as the check - rejected: it cannot work for cross-target kits (G-122 makes those routine), costs a process launch per kit, and a kit that boots into an interactive shell is awkward to probe safely. - Emit to `src/_build` but refuse only the deploy - rejected as a half-measure that leaves a punkcheck record claiming a good build product; a later run would consider it current. ## Notes - Related: G-124 - removes the most common cause (no zip reader on a tcllib-less tclsh). This gate is independent of it and remains valuable afterwards. - Related: G-122 (achieved) - promoted the no-extraction notice to a recapped BUILD-WARNING and recorded the field incident that motivates this goal; see goals/archive/G-122-host-target-platform-split.md. - Related: G-101 - a new 8.6 container type is exactly the situation where an extraction path can silently produce nothing; the gate is what keeps that honest. - Related: G-028 - sibling failure-reporting surface in the same deploy step (that goal names the process holding a target the build cannot replace; this one refuses to replace a target with something unbootable). - Overlap survey also considered G-057 (icon embedding rides the same wrap steps) and G-115 (declarative .vfs composition decides what the vfs supplies) - neither is a dependency: this gate reads whatever the merged tree contains, however it was composed.