You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

5.4 KiB

G-019 Dependency-scan-driven module trimming for punk-based executables

Status: proposed Scope: src/make.tcl; src/modules/punk/lib-999999.0a1.0.tm (tclparser use); src/vfs/ (kit assembly); scanning module (new or existing punk module - to be determined) Goal: a package-dependency scan from an executable's entrypoint (candidate basis: the tclparser parse API - c library preferred where present, punk::lib's parity-tested pure-Tcl fallback engaging automatically otherwise, so the scan can run on any tclsh - G-070) determines the module closure the executable actually requires, so a build can ship only those modules - while 'batteries included' builds remain a supported alternative, not a casualty. Acceptance: for at least one punk-based executable target, the build can run a dependency scan from its entrypoint producing the closure of required packages/modules plus a mechanism to declare dynamically-loaded extras the scan cannot see; a trimmed kit assembled from that closure starts and passes its basic function check (e.g. repl launch or the app's smoke test) with no missing-package errors; the trimmed kit's module listing is a strict subset of the batteries-included equivalent (demonstrating real exclusion); batteries-included builds remain producible unchanged.

Context

Punk executables are currently 'batteries included' - the kit assembly ships the full module snapshot regardless of what a given executable's app actually uses. For executables built around a specific app or entrypoint, a package-dependency scan could determine the module closure genuinely required and let the build ship only that, giving smaller artifacts. Batteries-included builds remain a supported alternative (the middle and far points of the spectrum described in G-018's context section).

The candidate scanning basis is static parsing of Tcl source via the tclparser parse API (tclpro-descended; https://wiki.tcl-lang.org/page/tclparser). Its current availability shapes the work:

  • The preferred implementation is the c-only tclparser library (package require parser); punk::lib uses it opportunistically.
  • punk::lib's same-API pure-Tcl fallback is now REAL (G-070, achieved 2026-08-02 - see goals/archive/G-070-pure-tcl-tclparser.md): punk::lib::tclparser_tcl delegates to the punk::tclparser engine module, parity-tested against the c library, and punk::lib::tclparser_prefer auto-dispatches (c preferred, pure-Tcl fallback wired otherwise). Note the covered set is what punk::lib consumes (parse command/getstring/ countnewline) - 'parse expr' and the other subcommands still require the c library.
  • punk::args::moduledoc::parser documents the parse API.

Using the C library inside build tooling previously made the build depend on a native binary - intersecting the G-004/G-005/G-006 binary-provenance story (zig-built or consent-downloaded, never committed). With G-070 achieved that coupling is gone for the parse-command analysis surface: the scan can run on any tclsh, with the c library an optional performance upgrade.

Approach

  • Static scan from the executable's entrypoint/app: walk package require (and tcl::tm / source-time load constructs) through the reachable sources, resolving the transitive closure against the project's module trees.
  • Dynamic requires are the known limit: computed package names, plugin-style loading, and package require inside rarely-hit code paths cannot be proven statically. A declaration mechanism for extras (per-executable manifest of packages to include beyond the scan result) is part of the goal's acceptance, not an afterthought.
  • Scan output should be a reviewable artifact (the closure list), feeding kit assembly rather than silently filtering it - so a wrong exclusion is diagnosable from the build record.
  • Verification of a trimmed kit is behavioural (starts, passes its app's smoke check) plus structural (module listing strictly a subset of the batteries-included equivalent).

Alternatives considered

  • Runtime tracing (run the app, record package require calls) instead of static parsing - rejected as primary: coverage-dependent (only exercised paths are seen), though it could later complement the static scan for validating the declared-extras list.
  • Naive regex scan for package require lines - rejected: misses computed names it can't even flag, false-positives in strings/comments; the tclparser parse API exists precisely to do this properly.

Notes

  • Related: G-070 (achieved 2026-08-02 - see goals/archive/G-070-pure-tcl-tclparser.md) - supplies this goal's candidate scanning basis without the native-binary coupling: tclparser_tcl is now a working pure-Tcl 'parse' implementation (punk::tclparser engine, tclparser_prefer dispatch), so the scan can run inside build tooling on any tclsh.
  • Interacts with G-005/G-006 (how the c-only tclparser binary is provisioned if chosen) and G-018 (the spectrum of executable flavours).
  • G-115 relationship (recorded 2026-07-24; G-115 achieved 2026-07-31 - see goals/archive/G-115-declarative-vfs-composition.md): the scan closure plus declared dynamic extras is a payload-determination input the now-live per-.vfs declaration surface (src/vfs/.vfs.toml) can consume - a trimmed kit is then a declared kit with a generated declaration.
  • punk::lib sites already noting tclparser use/fallback: tclword_to_scriptlist and related parsing helpers (~lib 3322-3580).