14 KiB
G-099 suite_tcl86: zig buildsuite for core-8-6-branch (runtime, thread, tclvfs, core-test gate)
Status: achieved 2026-07-26 Scope: src/buildsuites/suite_tcl86/ (new: suite.tcl driver, 8.6 zig recipe + helper modules, expected_test_failures baseline); src/buildsuites/_build/ (untracked sources/outputs via existing globs); bin/tools/ (pinned zig as consumed); PUNK_FOSSIL_STORE / ~/.punkshell/fossils (hermetic clone store shared with suite_tcl90) Goal: a tracked suite_tcl86 buildsuite builds a Tcl 8.6 windows runtime from fossil core-8-6-branch sources using the pinned zig toolchain only (zig-only build policy; msys/mingw and MS toolchains remain test/validation-only), together with the core binary companions punkshell's Tcl 8 targets need - an 8.6-compatible thread branch and tclvfs - and gates the result against the 8.6 core testsuite via parsed all.tcl totals against a tracked, dispositioned expected-failure baseline, mirroring the suite_tcl90 gate mechanism. Acceptance: from the pinned zig and fetched core-8-6-branch sources (hermetic clone store, no MS toolchain) the suite produces a working tclsh86 executable and tcl86 dll with an installed lib tree the shell resolves without external Tcl installations (TCLLIBPATH/TCL_LIBRARY unset in all suite child invocations); an 8.6-compatible thread package and tclvfs build and load in that shell (versions recorded); suite.tcl test runs the 8.6 core testsuite, parses totals (exit codes not trusted), and gates against a tracked expected_test_failures baseline with every entry dispositioned with a reason - a full-run PASS deterministic across two consecutive runs is recorded in this file; an interactive-smoke record (script execution, package require checks) is captured here.
Context
Follow-on arc to G-096/G-098 (suite_tcl90, achieved 2026-07-20), per user direction 2026-07-20: "we need a similar set of goals around building for core-8-6-branch".
8.6 remains punkshell's real Tcl 8 target (punk86-class kits; 8.7 is unreleased dev convenience only). Today the 8.6 kits ride on prebuilt third-party runtimes (tclkit86bi.exe, tclkit-win64-dyn.exe) - a provenance and rebuildability gap this arc ultimately closes.
Known differences from suite_tcl90 to expect (assessments to verify at activation):
- NO zipfs in 8.6: no szip-style self-contained runtime is possible. This suite delivers exe + dll + on-disk lib tree only. Kit containment (metakit/cookfs/zipvfs candidates) is deliberately OUT of scope - see G-101.
- thread: trunk (3.x) targets Tcl 9; 8.6 pairs with the thread 2.8 branch - exact branch/tag selection to verify and pin.
- Source-tree/build differences vs the 9.0.5 recipe: 8.6's bundled zlib/libtommath arrangements differ; no tclUuid.h; manifest/rc generation to re-derive from 8.6's win/makefile.vc; TCL_BROKEN_MAINARGS-era entry-point handling differs from the mingw-unicode-entry work done for 9.0.5. Helper modules (build_zlib, build_libtommath, wrapfiletofile) reusable where the trees align - assess rather than assume.
- Test gate: a separate 8.6 expected_test_failures baseline (failure census unknown until the first full run; the 9.0.5 census does not transfer). Machine traits already dispositioned for 9.0.5 (OS username vs profile dir, admin shares) will likely reappear under their 8.6 test names.
- 8.6 has no tcl::process: runtests -jobs child handling falls back to blocking execs (documented convoy behaviour) - the core-test gate runs via suite.tcl, not runtests, so this only affects later punkshell-suite work (G-100).
- Shared scaffolding: fossil_source/clone-store/env-hygiene conventions exist in suite_tcl90/suite.tcl. Factor shared parts out only when this second consumer makes the right shape obvious - avoid premature generalization; duplication with a note is acceptable at first.
SEQUENCING (2026-07-20 discussion): drafted as proposed while suite_tcl90 matures - recommendation is to complete G-096's remaining items (TCLSH_PIPEREPL patch rebase + behaviour matrix, punk-getzig per-version fetch) and run the punk905_beta interactive trial through to promotion before activating this goal, so the shared suite scaffolding settles before it is forked. Also weigh G-102 (zig-driver hybrid bootstrap, achieved 2026-07-21 - the driver shape is now SETTLED: pipeline as zig recipe steps, zon-pinned + fossil-checkout source flows converging on one staged invocation): its natural slot was before or alongside this goal so suite_tcl86 is born onto the chosen driver shape rather than ported later.
Progress
- 2026-07-25 activation + first increment (suite born on the settled driver
shape, satisfying the G-104 contract by construction):
- suite_tcl86/ created: sources.config (source records + G-104 description/product/doc/zigpin self-description records), suite.tcl (forked from suite_tcl90 per the duplication-with-a-note posture; log/fail prefix derives from the folder name, required sources {tcl tclthread tclvfs}, recipe file build86.zig, build steps default {install}), build86.zig (deliberate pending-derivation skeleton - staging succeeds, the recipe fails with a clear G-099 message), build.zig.zon (real content-hashed pins fetched with the pinned zig 0.16.0), README.md (deliverables, selections, DERIVATION record).
- THREAD 2.8 SELECTION: thread-2-8-branch, tip checkin e14fa771ae tagged thread-2-8-13 (2.8.13, 2026-04-30); the checkout's configure.ac guards TCL_MAJOR_VERSION == 8 (pairing confirmed from source). Dev flow rides the branch; the zon pins the 2-8-13 checkin.
- 8.6 SOURCE RECORDS IN BOTH FLOWS: sources.config refs (tcl core-8-6-branch -> dir tcl86; tclthread thread-2-8-branch; tclvfs trunk - 1.4.2 era per the recorded tcl9-only forTcl9 decision) and build.zig.zon per-checkin pins (tcl 1d1d5cbd91 = 8.6.18 era, thread e14fa771ae, tclvfs 9954261983) with zig-fetch hashes.
- FIRST STAGING RUN through the G-104 surface ('make.tcl buildsuite build suite_tcl86'): checkouts staged from the shared hermetic clone store into _build/suite_tcl86 (TCL_PATCH_LEVEL "8.6.18" read from the staged tree), recipe fails at the skeleton as designed (exit status propagated through the surface). 'buildsuite list/info' show the suite with its own records.
- RECIPE DERIVATION STARTED from the staged 8.6.18 win/makefile.vc - findings recorded in suite_tcl86/README.md DERIVATION, including two Context-assessment corrections: (a) 8.6.18 DOES generate tclUuid.h (makefile.vc 797-802 - the "no tclUuid.h" note was outdated); (b) the zlib arrangement is PREBUILT zdll.lib/zlib1.dll copies (not compiled) - the zig-only recipe compiles compat/zlib statically instead (decision recorded). TCLOBJS composition, in-tree libtommath, TCL_BROKEN_MAINARGS in win/tclAppInit.c, dde 1.4.6 / registry 1.3.5 versions recorded.
- 2026-07-26 completion increment (acceptance met; all "Remains for
acceptance" items resolved):
- RECIPE AUTHORED (build86.zig): COREOBJS/PLATFORMOBJS/TOMMATHOBJS source lists + the rules.vc-derived flag classes (app/pkg/stub with static variants), static zlib compiled into both the dll and the static shell (build_zlib86 - the 11-file makefile.vc ZLIBOBJS static-build list; stock nmake links a prebuilt zdll.lib for shared builds, so no zlib1.dll ships), in-tree libtommath, tclUuid.h + tclsh.exe.manifest generated into the build cache and delivered via overlay include dirs / rc copies.
- TWO BUILD-SURFACED FINDINGS (both recorded in suite_tcl86/README.md
DERIVATION): (a) makefile.vc PRJ_DEFINES MP_FIXED_CUTOFFS is load-bearing
- TOMMATHOBJS carries no bn_cutoffs.c, so the karatsuba/toom cutoff variables are undefined at link without it; (b) TCL_BROKEN_MAINARGS (win/tcl.m4 gcc-class extra_cflags) + the console subsystem give tclAppInit.c a plain main() + GetCommandLineW re-parse - without it mingw's fallback demands WinMain.
- PRODUCTS (stock threaded-release naming - rules.vc keeps SUFX 't' on 8.6): bin/tcl86t.dll + tcl86t.lib import lib, bin/tclsh86ts.exe (static, kit-class: dde/registry compiled in via TCL_USE_STATIC_PACKAGES), bin/tclsh86t.exe (dynamic pair against the dll), lib/libtclstub86.a.
- COMPANIONS: thread 2.8.13 (lib/thread2.8.13/thread2813t.dll, TEA installed shape from the checkout's own pkgIndex.tcl.in + ttrace.tcl) and tclvfs 1.4.2 (lib/vfs1.4.2/vfs142t.dll + configured vfs.tcl/pkgIndex.tcl; the vfst TEA dll name lets Tcl's load-time name guessing derive Vfs_Init) build and load; registry 1.3.5 / dde 1.4.6 in lib/tcl8.6/{reg,dde}.
- INSTALL TREE + HERMETIC RESOLUTION PROVEN: whole library tree -> lib/tcl8.6, tm modules -> lib/tcl8/{8.5,8.6}/ (versions parsed from the library pkgIndex files: http 2.9.9, msgcat 1.6.1, tcltest 2.5.11, platform 1.1.1, platform::shell 1.1.4). Both shells report [info library] = the installed lib/tcl8.6 with TCLLIBPATH/TCL_LIBRARY unset (scrubTclEnv per built-shell run + suite.tcl process-level unset) - exe/dll-relative discovery, no external Tcl.
- CORE-TEST GATE: suite.tcl test -> zig build test-gate runs the 8.6 core testsuite under the installed static shell, parses all.tcl totals (exit codes untrusted, tools/test_gate.tcl), gates vs the tracked dispositioned baseline. Per-library gates (test-thread, test-tclvfs) added on the suite_tcl90 G-107 policy-tier pattern.
- FIRST CENSUS + baselines (2026-07-26, tclsh86ts.exe 8.6.18, machine SuperBee): core 46525 run / 2 failed (filename-16.12/16.13 - windows admin-share self-globbing machine trait, same class as suite_tcl90's baseline; the 9.0.5 fCmd 'file home' failures are absent - 'file home' is a 8.7/9.0 command); thread 142 run / 0 failed (EMPTY baseline; constraint- driven skips only); tclvfs 51 run / 2 failed (vfsUrl-1.2/2.1 - external FTP dependency on the retired ftp://ftp.tcl.tk, the same 1.4.2-era entries suite_tcl90's tclvfs note records). Baselines authored with every entry dispositioned: expected_test_failures.txt / _thread.txt / _tclvfs.txt.
- TWO-CONSECUTIVE-RUN DETERMINISTIC PASS (2026-07-26): both
suite.tcl test -steps "test-gate test-libraries"runs -> GATE PASS on all three suites, identical dispositioned failure sets (core 2, thread 0, tclvfs 2). One core test jittered pass<->skip between runs (39227/7296 vs 39226/7297; a constraint-evaluation timing effect) but the gate criterion - failed names vs baseline - was identical, so the gate is deterministic. - INTERACTIVE-SMOKE RECORD (2026-07-26, both shells, env scrubbed): script
execution (expr 6*7 = 42), [info patchlevel] = 8.6.18, [info library] =
installed lib/tcl8.6, and package require Thread 2.8.13 / vfs 1.4.2 /
registry 1.3.5 / dde 1.4.6 / http 2.9.9 / platform 1.1.1 all load; the
suite's
smokestep (tools/suite_smoke.tcl + pkg_smoke.tcl) captures the same on every build. - FIREWALL NOTE (unattended-run trap, characterized): socket.test's
unconditional constraint-probe
socket -server {} 0(no -myaddr -> wildcard 0.0.0.0 bind) triggers the one-time Windows Defender "allow app" dialog on a freshly-built exe's first listen. Once accepted for the stable installed exe path (out/bin/tclsh86ts.exe) the rule persists across re-runs and rebuilds, so runs 2+ are unattended (the two-run determinism proof needed no interaction). The remote-server socket tests themselves skip under the serverNeeded constraint (1996 skips). This is the buildsuites-direction memory's recorded "firewall dialog on new exe's first socket listen" trap.
Notes
- Activation freshness 2026-07-25: goals_xref.tcl score G-099 re-run at the proposed->active flip (gate honoured: activated only after the G-112 rename core and G-104 self-description contract landed - both achieved earlier today). Top pairs G-100/G-105/G-101/G-116/G-108 all already linked or recorded (G-108 via the archive re-bridge Related line below); remaining unlinked hits are term noise - no new relationships.
- 2026-07-21 (user): SEQUENCING CONFIRMED - G-097 (achieved 2026-07-21) then G-103 (achieved 2026-07-22 - see goals/archive/G-103-runtime-kit-family.md) precede this arc - BOTH LANDED, the arc is unblocked; the suite_tcl86 fork is taken after the kit-family assembly steps exist in suite_tcl90 so the 8.6 suite is born expressing family products (and G-101 inherits a concrete payload contract).
- G-106 (archived) recorded a verification item for this arc's twapi-less 8.6 runtimes: the powershell console-mode fallback's disableraw-via-server path (the branch runtimes without -inputmode rely on to restore cooked mode) is coded but only tcl9-verified - run the G-106 recipe against a suite-built 8.6 runtime when one exists. See goals/archive/G-106-powershell-consolemode-fallback.md (Notes).
- G-104 relationship (recorded 2026-07-24; G-104 achieved 2026-07-25 - see goals/archive/G-104-maketcl-buildsuite-surface.md): the list/info/build surface and the sources.config self-description contract (description/product/doc/zigpin records, parsed by both suite.tcl and make.tcl) are live. suite_tcl86 must be BORN satisfying the contract (its sources.config carries the records from the first commit, so it lists and describes itself with no make.tcl edits) and its builds run via 'make.tcl buildsuite build suite_tcl86 ?driver-args?'.
- G-105 relationship: G-105's cross-target parameterization (zig -target) is inherited by this suite when it lands - the suite.tcl/recipe shape should not preclude a target dimension (per-target out prefixes, no per-target tree copies).
- Related: G-108 (debug buildsuite tier) - sibling suite-arc goal, queued behind this arc per user sequencing 2026-07-25; its -dbg/tcl::test debug-variant pattern is suite_tcl90-scoped, but the recipe shape this suite derives should not preclude a future 8.6 debug tier (recorded at the G-104 archive re-bridge - the pair's former bridges were all archived goals).
- G-005 relationship: G-005 owns the zig-build-of-binary-dependencies direction for the normal project build (vendored extensions, make.tcl-integrated); this suite is the arm's-length runtime-factory shape that direction took for Tcl cores. The two zig surfaces share the pinned-zig / zig-only toolchain policy; G-116's extension-build pattern is the living edge of G-005's expansion list.