diff --git a/GOALS.md b/GOALS.md index c02c7dd8..1ffc18cb 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-134 [proposed] Baked kits pinned archive-relative: advisory offset-style probe on assembled kit images +Scope: src/make.tcl (post-assembly offset-style probe at the G-133 advisory-check seam, recapped reporting); src/modules/punkboot/utils-999999.0a1.0.tm (probe predicate beside the G-133 scan helpers, guarded require; bootsupport copies via established sync channels); src/tests/modules/punkboot/utils/ + src/tests/shell/testsuites/punkexe/ (characterization); src/AGENTS.md (what the pin does and does not guarantee) +Detail: goals/G-134-baked-kits-pinned-archive-relative.md diff --git a/goals/G-128-portable-pe-resource-stamping.md b/goals/G-128-portable-pe-resource-stamping.md index 14a2f989..ee6b1340 100644 --- a/goals/G-128-portable-pe-resource-stamping.md +++ b/goals/G-128-portable-pe-resource-stamping.md @@ -3,7 +3,7 @@ Status: proposed Scope: src/tools/punkres/ (vendored zig source - tool name settled in the work - with provenance and licence records); src/make.tcl (mechanism selection at the G-057 seam, sharing G-126's tool build step); bin/tools/zig* (pinned toolchain as consumed); bin/punkres.exe (untracked build output); src/tests/ (characterization - icon replaced, payload intact, idempotent, overlay-unsafe refusal); TEMP_REFERENCE/tcl-sfe (read-only reference for the resource structures) Goal: punkshell can stamp windows resources into a FINISHED kit executable from any build host - no twapi, no windows host, no disturbing the appended vfs payload - so a cross-target win32 kit is not condemned to its runtime's icon, and resource stamping becomes a post-hoc operation on a built artifact rather than something wired into the middle of the kit wrap. G-057's mechanism seam selects this implementation when it is present and keeps its twapi path otherwise. -Acceptance: the vendored tool, built by the same make.tcl tool step G-126 establishes, replaces RT_ICON/RT_GROUP_ICON in a pre-built PE that already carries an appended zip overlay, for the kit shapes we build (kit, zip, zipcat per mapvfs.config): the new icon is confirmed by reading the resources back with the tool ITSELF (so verification does not require a windows host or twapi) and cross-checked once on windows with twapi::extract_resources; the stamped kit still boots to a working punk shell reading its payload; re-stamping converges with no resource accumulation; it works where .rsrc is NOT the last section - the shape our own runtimes have (tclsfe-x64/punk91: .text .rdata .data .pdata .rsrc .reloc; suite-built tclsh9.0.5-punk: .text .rdata .buildid .data .pdata .tls .rsrc .reloc) - by appending a section and repointing the resource data directory rather than growing .rsrc in place; the appended payload survives the file-offset shift this causes, which is safe for an ARCHIVE-relative zip and not for a file-relative one, so a file-relative payload is REFUSED naming that reason rather than silently corrupted; one end-to-end run from a NON-WINDOWS host produces a stamped win32 kit whose icon a windows machine confirms (recorded here: which host); G-057's seam selects the tool when present and falls back to its twapi path otherwise, with a parity check showing both mechanisms yield equivalent resource content from the same input, and zig stays optional - with no tool built, G-057 behaves exactly as it does without this goal; the tool's distribution is settled and recorded - buildable from the vendored source with the pinned toolchain AND publishable as a punkbin artifact through the G-123/G-006 channels, so a no-toolchain user has a route that does not depend on the committed twapi; the tool's structure handling is written so the parked RT_VERSION stamping needs no second tool; licensing and upstream provenance of the vendored tree are recorded per G-063 and G-026. +Acceptance: the vendored tool, built by the same make.tcl tool step G-126 establishes, replaces RT_ICON/RT_GROUP_ICON in a pre-built PE that already carries an appended zip overlay, for the kit shapes we build (kit, zip, zipcat per mapvfs.config): the new icon is confirmed by reading the resources back with the tool ITSELF (so verification does not require a windows host or twapi) and cross-checked once on windows with twapi::extract_resources; the stamped kit still boots to a working punk shell reading its payload; re-stamping converges with no resource accumulation; it works where .rsrc is NOT the last section - the shape our own runtimes have (tclsfe-x64/punk91: .text .rdata .data .pdata .rsrc .reloc; suite-built tclsh9.0.5-punk: .text .rdata .buildid .data .pdata .tls .rsrc .reloc) - by appending a section and repointing the resource data directory rather than growing .rsrc in place; the appended payload survives the file-offset shift this causes, which is safe for an ARCHIVE-relative zip and not for a file-relative one; a file-relative payload is REFUSED BY DEFAULT with an error naming the reason and the rewrap remedy, but an explicit consent flag (tool CLI and the G-057 seam, never an interactive prompt in non-interactive runs) stamps it by shifting the overlay AND rewriting every central-directory local-header offset plus the EOCD directory offset by the shift delta - deliberately PRESERVING the file-relative convention, with a notification that the format is non-standard - verified by re-reading the stamped artifact (offsetstyle still file, members crc-verified); zip64 and multi-disk archives are refused even with consent; one end-to-end run from a NON-WINDOWS host produces a stamped win32 kit whose icon a windows machine confirms (recorded here: which host); G-057's seam selects the tool when present and falls back to its twapi path otherwise, with a parity check showing both mechanisms yield equivalent resource content from the same input, and zig stays optional - with no tool built, G-057 behaves exactly as it does without this goal; the tool's distribution is settled and recorded - buildable from the vendored source with the pinned toolchain AND publishable as a punkbin artifact through the G-123/G-006 channels, so a no-toolchain user has a route that does not depend on the committed twapi; the tool's structure handling is written so the parked RT_VERSION stamping needs no second tool; licensing and upstream provenance of the vendored tree are recorded per G-063 and G-026. ## Context @@ -100,3 +100,19 @@ the parked RT_VERSION stamping wants, since the project version is known late. G-057's Notes already require those to be reconciled into one story. - Related: G-028 - a locked kit exe blocks a resource update exactly as it blocks deploy. - Related: G-063 / G-026 - licence and provenance recording for the vendored tree. +- Recorded 2026-07-27 (user decision): a file-relative payload is no longer a straight + refusal - default refuse with a consent-flag preserve, per the amended Acceptance. + Rationale: the format works and serves naive zip-tooling/SFX-repair interop and + external zip pipelines that treat recorded offsets as file positions. The consented + path costs one central-directory offset fix-up pass (the shift delta added to every + local-header offset and to the EOCD directory offset) - no decompression, member data + untouched; a zip digital-signature record carries no offsets and survives. In-place + CONVERSION between conventions falls out of the same machinery with the delta + direction reversed - parked, not part of this goal. +- Stamping invalidates any Authenticode signature regardless of zip convention: the + certificate table is located via the PE security directory (a file offset) and the + image hash covers the appended payload - sign AFTER stamping; the sign-last rule is + orthogonal to the archive/file-relative question. +- Related: G-134 - pins make.tcl's own kit outputs archive-relative (advisory probe), + so a default-refusal case reaching the stamper reads as a provenance signal (the + artifact did not come through the bake pipeline), not a pipeline regression. diff --git a/goals/G-134-baked-kits-pinned-archive-relative.md b/goals/G-134-baked-kits-pinned-archive-relative.md new file mode 100644 index 00000000..b5f127ff --- /dev/null +++ b/goals/G-134-baked-kits-pinned-archive-relative.md @@ -0,0 +1,71 @@ +# G-134 Baked kits pinned archive-relative: advisory offset-style probe on assembled kit images + +Status: proposed +Scope: src/make.tcl (post-assembly offset-style probe at the G-133 advisory-check seam, recapped reporting); src/modules/punkboot/utils-999999.0a1.0.tm (probe predicate beside the G-133 scan helpers, guarded require; bootsupport copies via established sync channels); src/tests/modules/punkboot/utils/ + src/tests/shell/testsuites/punkexe/ (characterization); src/AGENTS.md (what the pin does and does not guarantee) +Goal: every kit image make.tcl assembles is verified to carry an ARCHIVE-relative zip payload - probed with punk::zip::archive_info post-assembly - so the bake pipeline's archive-relative output property becomes a checked contract rather than a by-construction accident, and any future assembly path (new kit type, modpod or accelerator change) that emits file-relative offsets surfaces at bake time instead of when G-128's stamper refuses punkshell's own kits. +Acceptance: each assembled kit image is probed with punk::zip::archive_info and a recapped BUILD-WARNING naming the kit is emitted when offsetstyle is file (advisory per the G-133 posture - the kit still builds and deploys, unlike the G-125 hard gate); plain and none results (no zip attached - the metakit kit shape G-131 targets) are silence, not warnings: the pin covers zip offset convention, not the presence of a zip; today's bakes produce no warning (G-124's measured baseline: every built kit archive-relative); the probe predicate lives in punkboot::utils beside the G-133 scan helpers, called through the same guarded require so a stale bootsupport snapshot degrades it to a NOTE, and tclsh src/make.tcl check reports its ACTIVE/UNAVAILABLE state; characterization pins the warning on a file-relative kit fixture and silence on the archive-relative kit set; scope is make.tcl's own assembly paths only - punk::zip::mkzip -offsettype file and modpod's equivalent REMAIN available for deliberate manual creation of file-relative artifacts (user decision 2026-07-27: the format works and serves naive zip-tooling/SFX-repair interop, it is simply not what our pipeline emits), and external zip-repair tools' file-relative output remains tolerated on input by the G-124 reader and normalized away by any re-bake. + +## Context + +Archive-relative output has been by-construction, never contractual: it falls out of +mkzip's `-offsettype archive` default and modern zipfs mkimg, and G-124 measured it +across the store 2026-07-26 (15 archive-relative runtimes plus every built kit; the +single file-relative artifact is `tclsh90b4_piperepl.exe`, the historical mkimg +convention). Input artifacts may legitimately be file-relative - 3rd-party zipfs kits, +external zip-repair output - and the merge normalizes them because the payload is +always rebuilt from extracted members. But nothing fails loudly if a future assembly +path regresses the output convention; the first symptom would be G-128's stamper +refusing punkshell's own kits. This goal pins the property at the seam G-133 +established for advisory payload checks. + +Decided 2026-07-27 alongside G-128's consented file-relative preserve amendment: the +file-relative format is supported everywhere it can arrive (the reader tolerates it, +the stamper preserves it with consent, the writers can emit it on request) - this pin +asserts only what OUR pipeline emits by default. + +## Approach + +- One probe at the post-assembly seam beside G-133's binary-arch scan: + `punk::zip::archive_info` on the finished image; BUILD-WARNING unless offsetstyle is + `archive`, recapped at end of run. Per-kit cost is one EOCD scan + central-directory + walk, only when the kit rebuilds (G-124 measured ~735ms for an 841-member archive - + the same order as G-133's arch scan). +- Advisory, matching G-133: warnings never block build or deploy. +- No new instrument: G-124's archive_info is the whole probe; the punkboot::utils + predicate wraps it so it unit-tests without a bake. + +## Alternatives considered + +- Hard gate (G-125-style kit failure) - rejected (user decision 2026-07-27): the + property holds by construction today and make.tcl has no deliberate file-relative + path; a hard gate would fire only on a regression already loud in tests and would + block any future deliberate per-kit opt-out. G-125's gate exists for user-facing + undeployable kits; this is a developer-facing convention notice. +- Documentation-only pin in src/AGENTS.md - rejected as enforcement-free: prose does + not fire when the regression lands. + +## Notes + +- Related: G-124 (achieved 2026-07-26 - see goals/archive/G-124-punkzip-reader.md) - + supplies the probe (archive_info: offsetstyle archive|file|plain|none plus + dataoffset) and the store survey that is this pin's baseline. +- Related: G-133 (achieved 2026-07-27 - see + goals/archive/G-133-bake-payload-consistency-checks.md) - the advisory-check seam, + recapped BUILD-WARNING convention, guarded-require degradation and `make.tcl check` + reporting this probe follows. +- Related: G-125 - the hard-gate contrast recorded under Alternatives. +- Related: G-128 - the consumer that motivated the pin: its stamper refuses + file-relative payloads by default (consent-flag preserve per the 2026-07-27 + amendment); without this pin a pipeline regression surfaces there first, on our own + kits. +- Related: G-122 (achieved - see goals/archive/G-122-host-target-platform-split.md) / + G-127 - the zipfs-less and cross-target assembly paths under the probe; both assemble + via mkzip/mkimg archive-relative defaults today. +- Related: G-131 - metakit-shape kits carry no zip; the probe's `none` result is + silence, not a warning. +- Overlap survey 2026-07-27: `goals_xref paths src/make.tcl src/bootsupport src/tests` + - no live goals intersect src/make.tcl or src/tests; src/bootsupport produced weak + lexical hits only (G-004, G-024, G-026, G-132 - bootsupport path mentions, no + semantic overlap with an offset-style probe). `goals_xref report` reviewed: no + unlinked pair concerns an output offset-convention check. The G-124/G-133 anchors are + archived; the relations above are from reading.