# 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 - currently satisfied only by the c-only tclparser library, with punk::lib's pure-Tcl fallback an unimplemented stub) 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 real implementation is the **c-only tclparser library** (`package require parser`); punk::lib uses it opportunistically. - punk::lib carries a same-API pure-Tcl fallback, `punk::lib::tclparser_tcl` (src/modules/punk/lib-999999.0a1.0.tm ~3322), which is an unimplemented stub that errors advising installation of the C library. - punk::args::moduledoc::parser documents the parse API. Using the C library inside build tooling makes 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). Completing the pure-Tcl fallback would remove that coupling at some accuracy/performance cost. The choice (or ordering - e.g. C library first, fallback later) is an implementation decision to record here. ## 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 - Interacts with G-005/G-006 (how the c-only tclparser binary is provisioned if chosen) and G-018 (the spectrum of executable flavours). - punk::lib sites already noting tclparser use/fallback: tclword_to_scriptlist and related parsing helpers (~lib 3322-3580).