From 7a37e36362f7193a68be3f5f3546ad9c484103b8 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Mon, 27 Jul 2026 12:57:32 +1000 Subject: [PATCH] G-133 drafted (user-approved): bake payload/target consistency checks Candidate goal from the G-129 aftermath (user-observed 32-bit kit breakage): an advisory binary-architecture scan over the merged tree at the G-125 gate seam (platform-subdir aware, covers cross-target kits) plus a per-kit post-bake smoke-require probe through the artifact's own tclsh subcommand (plain package require - the only observer of version-preference shadowing). Overlap survey named G-024/G-131/G-127/G-028/G-130/G-123, non-overlap G-115, precedent G-125/G-129. Advisory-vs-gate for smoke failures recorded as the open decision at activation. Claude-Session: https://claude.ai/code/session_01UEgomWq6kA6c4A8GswqqGW Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com --- GOALS.md | 4 + .../G-133-bake-payload-consistency-checks.md | 76 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 goals/G-133-bake-payload-consistency-checks.md diff --git a/GOALS.md b/GOALS.md index c02c7dd8..dc463b49 100644 --- a/GOALS.md +++ b/GOALS.md @@ -414,3 +414,7 @@ Detail: goals/G-131-boot-payload-autodetection.md ### G-132 [proposed] Draft the Tcl-on-windows errno catch-all report for manual submission Scope: TEMP_REFERENCE/tcl-windows-errno-catchall-TICKET-DRAFT.md (submission-ready ticket text - STAGING ONLY, unversioned, and the agent does not submit it); this detail file (the tracked record: finding, verbatim reproducer, the submitted URL once the user files it, and the upstream disposition); src/bootsupport/AGENTS.md and src/make.tcl (the existing workaround and its warning - dated, not removed, if upstream fixes it) Detail: goals/G-132-tcl-windows-errno-catchall-report.md + +### G-133 [proposed] Bakes verify payload/target consistency: smoke-requires probe + advisory binary-arch scan +Scope: src/make.tcl (post-merge advisory arch scan at the G-125 gate seam; post-bake smoke-require step for host-runnable kits; recapped reporting); src/modules/punkboot/utils-999999.0a1.0.tm (binary-arch classifier + payload scan predicate beside vfs_boot_library_report); src/runtime/mapvfs.config (per-kit smoke-require declaration - interim line format, schema home moves with G-024); src/tests/modules/punkboot/utils/ (classifier fixtures); src/tests/shell/testsuites/punkexe/ (reporting characterization); src/AGENTS.md + bin/AGENTS.md (what is and is not guaranteed) +Detail: goals/G-133-bake-payload-consistency-checks.md diff --git a/goals/G-133-bake-payload-consistency-checks.md b/goals/G-133-bake-payload-consistency-checks.md new file mode 100644 index 00000000..624fd03b --- /dev/null +++ b/goals/G-133-bake-payload-consistency-checks.md @@ -0,0 +1,76 @@ +# G-133 Bakes verify payload/target consistency + +Status: proposed +Scope: src/make.tcl (post-merge advisory arch scan at the G-125 gate seam; post-bake smoke-require step for host-runnable kits; recapped reporting); src/modules/punkboot/utils-999999.0a1.0.tm (binary-arch classifier + payload scan predicate beside vfs_boot_library_report); src/runtime/mapvfs.config (per-kit smoke-require declaration - interim line format, schema home moves with G-024); src/tests/modules/punkboot/utils/ (classifier fixtures); src/tests/shell/testsuites/punkexe/ (reporting characterization); src/AGENTS.md + bin/AGENTS.md (what is and is not guaranteed) +Goal: a bake tells the developer, before anyone runs the kit, when a kit's payload cannot deliver what it visibly carries: every kit including cross-target gets a structural check that binary libraries match the kit's declared target unless they sit under a platform-discriminated subdir, and host-runnable kits prove a declared package set actually resolves and loads inside the built artifact via plain package require - so resolution-order defects (a higher-versioned wrong-arch copy shadowing a working one) are caught, not just missing files. +Acceptance: a merged payload carrying a wrong-arch binary outside any platform-discriminated subdir produces a recapped BUILD-WARNING naming file, found architecture and kit target, with the 2026-07-27 punkluck86 case (x64 thread dll under plain lib_tcl8/ in a win32-ix86 kit) reproduced as a fixture; multi-arch platform-subdir packages (iocp-2.0.2's win32-ix86 + win32-x86_64 pair) and recognised vendor spellings (blend2d-style win-x64) produce no warning; the scan is structural, non-executing, runs for cross-target kits and its measured per-kit cost is recorded as negligible; a kit entry may declare smoke-require packages, and for host-runnable kits the freshly built artifact is executed via its tclsh subcommand with each declared package plain-required - failures are recapped naming kit, package and the actual error, the Thread version-shadowing case is caught by construction, cross-target kits skip with a stated reason, and undeclared kits run nothing new; the classifier is unit-tested over PE i386/x64/arm64 fixtures and platform-subdir layouts with non-PE formats classified or honestly unknown; and src/AGENTS.md + bin/AGENTS.md state what the checks do not guarantee (statics, pure-tcl packages with binary deps, and version-preference outcomes are visible only to the smoke probe). + +## Context + +Motivating failures, both measured 2026-07-27 on the G-129 verification kits when they +still wrapped full 64-bit payloads (user-observed first as "basic shell functionality is +broken"): + +- punkluck86 (32-bit LUCK 8.6.10 runtime): the payload's x64 Thread 2.8.12 outversioned + the runtime's own working 32-bit 2.8.5, so plain `package require Thread` selected the + unloadable copy and the repl's tsv/codethread machinery died. Forcing + `package require -exact Thread 2.8.5` loaded fine - the backport's zipfs dll loading + works, and the failure was purely wrong-arch version shadowing. No structural check can + see this class: the working file exists, and only actual resolution order exposes it. +- punk91ix86 (32-bit tcl-sfe 9.1b0): `package require udp` failed against an x64-only + tcludp dll. Both failures surfaced as the same unhelpful + "couldn't load from current filesystem". + +The G-125 boot-precondition gate deliberately checks BOOTABILITY (a tcl library in the +merged tree) and nothing more; nothing between it and the user exercises whether the +payload's packages can actually load in the built artifact. The minimal-payload repoint +(punk8min.vfs/punk9min.vfs, 0.28.1) removed today's instances but not the class: any +future payload/target pairing can regress the same way, silently. + +## Approach + +- TWO mechanisms because each sees what the other cannot. The smoke probe uses plain + `package require` inside the real artifact, so it observes actual resolution order - + the only way to catch version-preference shadowing - but requires a host-runnable kit. + The structural scan cannot see resolution or statics, but it is non-executing and so + covers cross-target kits (the linux entry included). +- Arch scan: classify each binary library in the merged tree by header (PE Machine field + - a two-byte read at e_lfanew+4: i386/x64/arm64; ELF/Mach-O classified or honestly + unknown) against the kit's declared target. Binaries under a platform-discriminated + subdir are exempt: canonical punkshell platform-dir names plus a small recognised + vendor-spelling list (the tree already carries iocp-2.0.2's win32-ix86/win32-x86_64 + pair and blend2d's win-x64). Advisory BUILD-WARNING, never a gate - multi-arch payloads + are legitimate and vendor spellings make false certainty unavoidable. +- Smoke step: per-kit declaration; the freshly assembled artifact is executed via its own + tclsh subcommand (exits cleanly even on runtimes whose full repl teardown is fragile - + the punkluck86 exit-segfault observation). Drafted ADVISORY (recapped failures); + whether it should FAIL the kit like the G-125 gate is an open decision at activation. +- The classifier/scan predicate lives in punkboot::utils beside vfs_boot_library_report, + called through the same guarded require (G-125 precedent) so it is unit-testable + without a bake and a stale bootsupport snapshot degrades it to a note. + +## Notes + +- Related: G-024 - the toml conversion is the eventual home for per-kit/group + smoke-require declarations and the verification-set grouping recorded there; this goal + lands an interim declaration in the current line format. +- Related: G-131 - its kit_type_mismatch rework reads the same runtime_caps/probe + surface; the two failure reports should read as one vocabulary. +- Related: G-127 - the smoke step's host-runnable gating parallels that goal's + cross-target output-location concerns; whichever lands second adopts the other's + target-addressing. +- Related: G-028 - sibling failure-reporting surface in the same bake loop. +- Related: G-130 - first-party 32-bit runtimes/packages will change what the win32-ix86 + verification kits may carry; the scan's platform-subdir exemption is what lets + multi-arch payloads grow without warnings. +- Related: G-123 - a published third-party runtime tier consumes this guarantee (a kit + that passed its smoke-requires is what publication would cite). +- Deliberate non-overlap: G-115 - declarative .vfs composition decides what a payload + contains; this goal reads whatever the merged tree contains, however composed (the + same stance archived G-125 took). +- Precedent/motivation: G-125 (achieved - see + goals/archive/G-125-unbootable-kit-deploy-gate.md) gates bootability at the same seam; + G-129 (achieved - see goals/archive/G-129-kitboot-mountpoint-derivation.md) produced + the two win32-ix86 verification kits whose payload/arch failures motivated this goal. +- Open decision at activation: smoke-require failures advisory (as drafted) vs + kit-failing gate.