3.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) Acceptance: as in root GOALS.md index (canonical).
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(andtcl::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 requireinside 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 requirecalls) 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 requirelines - 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).