7.8 KiB
G-004 No executable binaries committed to the repository
Status: proposed Scope: repo-wide (bin/, src/vfs/, src/vendorlib/, src/vendormodules/, src/bootsupport/) Goal: the committed repository contains no executable binaries; zip-based .tm modules are allowed but not if they embed executables. Acceptance: a scan of the committed tree finds no executable binaries (shared libs, .exe, native .so/.dll/.dylib, bare ELF/Mach-O); any zip-based .tm modules present contain no embedded executables; the binary artifacts previously committed are retrievable via G-005 (build from source) or G-006 (pre-built download) so their removal does not break builds.
Context
The ultimate aim is that the committed repository contains no executable binaries. This is a hygiene and reproducibility goal: binaries in version control are opaque to review, bloat the repo, and make the build non-reproducible from source. Today the repo violates this — binary libraries are committed in the VFS folders (src/vfs/), src/vendorlib/, src/vendormodules/, and src/bootsupport/. These are present because there is currently no automated way to rebuild or retrieve them; removing them before an alternative exists would break builds on a clean checkout.
Two further motivations recorded 2026-07-22 (user framing):
- Third-party distribution eligibility: a binary-free punkshell is a candidate for distribution platforms that disallow checked-in binaries.
- The consent promise as a product commitment: punkshell guards the promise that binaries reach the user's machine over the network ONLY by explicit user action/consent unless configured otherwise (the G-006 gate and its G-067 sibling are the enforcement points). A binary-free repo makes the promise auditable: everything binary is retrieved, and every retrieval is consented.
Zip-based .tm modules are a permitted exception to the "no binaries" rule because they are module archives, not executables — but a zip-based .tm that embeds an executable (e.g. a native shared library packaged inside the module) is not permitted. The distinction is content, not file extension.
This goal is the integrating outcome of two enabling goals:
- G-005 provides the build-from-source path (zig build of Tcl9 and other dependencies).
- G-006 provides the pre-built download path with consent gating.
Both must be in place before the committed binaries can be removed without breaking builds, so G-004 sequences after both.
A standing repo-wide rule in root AGENTS.md (User Preferences) already directs agents not to commit new executable binaries, while explicitly not hassling the developer about existing vendor/vfs binaries committed pending this goal's achievement.
Approach
-
Inventory. Identify every executable binary currently committed across
bin/,src/vfs/,src/vendorlib/,src/vendormodules/, andsrc/bootsupport/. Classify each by what it is (Tcl9 shared lib, twapi, other native extension) and which goal path (G-005 build / G-006 download) will replace it. -
Verify alternatives work. Before removing any binary, confirm the corresponding G-005 build or G-006 download produces an artifact that satisfies the build. Removal without a working replacement breaks clean-checkout builds — the acceptance explicitly requires the alternative retrieval to work.
-
Remove. Delete the committed binaries from the tree. Update
.gitignore/.fossil-settings/ignore-globif needed to prevent re-addition. -
Add a scan to verification. Add a scan step (script or make.tcl target) that checks the committed tree for executable binaries and fails if any are found, so regressions are caught. The scan must recognise the zip-based
.tmexception: a.tmthat is a zip is allowed; a.tm(or any zip) containing an embedded executable is not. -
DOX update. Once achieved, the AGENTS.md "no binaries" user-preference note can be simplified from "agents must not; existing violations pending" to "agents must not; scan enforced" — but the rule itself stays.
Alternatives considered
- Delete binaries now, document manual fetch. Rejected: no automated retrieval, so every contributor hand-fetches. The intended system (G-005/G-006) exists precisely to avoid this.
- Allow committed binaries permanently. Rejected: this is the explicit ultimate aim the user stated. Not a real alternative.
- Permit zip-based .tm with embedded executables. Rejected: the user's wording is explicit — "those zip-based .tm modules that contain executables should also not be directly checked in." The content matters, not the extension.
- Fold G-005 and G-006 into this goal. Rejected: the build system and download system are each large bodies of work with their own acceptance, and they're independently useful before all binaries are removed. Bundling would make G-004 uncheckable until two large systems are built, and would grow past a one-line-safe summary.
Notes
- 2026-07-22 (user framing): achieving this goal must NOT stop binaries OPERATING in the tree - the no-checkin policy is about the COMMITTED tree only. Two working modes stay first-class forever: (a) quick local experimentation with uncommitted binaries dropped into the working tree; (b) derived projects (dev project.new) with a PERMISSIVE binary policy - generated projects may commit binaries under their own rules. Consequences for the Approach: the step-4 scan targets the committed tree (never a working-tree police); ignore rules added at removal time double as the drop-in enablement (local binaries stay conveniently uncommitted); and boot/loading machinery (auto_path platform dirs, tm roots, libunknown, modpod) must keep supporting in-tree binaries indefinitely - G-114's same-version drop-in-replacement acceptance is the tm-side expression of the same requirement. Layout seeding keeps the binary policy per-project (punkshell strict, derived projects owner-chosen).
- 2026-07-22 (user framing + assessment): EXIT PATHS for the src/vfs/*.vfs
interim exception - the .vfs binary payloads leave the committed tree via
some mix of: (i) suite-built runtime batteries (G-103, achieved 2026-07-22
- see goals/archive/G-103-runtime-kit-family.md - attached images already shrink kit .vfs payloads toward pure punkshell script payload); (ii) per-package punkbin LIBRARY artifacts (G-067 channel - buildsuite-built .tm/pkg libraries as a second punkbin artifact class) declared into kit assembly; (iii) possibly whole zipped binary-carrying .vfs archives as a THIRD punkbin artifact class. Assessment 2026-07-22 (agent, user question): prefer (i)+(ii) as the primary paths - per-package artifacts dedupe across kits, keep provenance/versioning granular, reuse the platform canon and the G-103 metadata pattern, and share one consent story; whole-.vfs archives couple unrelated components and churn on any payload change, so (iii) is recorded as an OPEN option for release-snapshot/derived-project convenience rather than the primary mechanism - decide when removal actually forces the payloads out. A declarative .vfs composition surface (toml-defined payload pulling from (i)/(ii), preserving drop-in simplicity) is the candidate glue - see the G-115 proposal (2026-07-22) if adopted.
- Depends on G-005 and G-006. Sequence G-005 ∥ G-006, then G-004.
- The scan in step 4 should distinguish "executable binary" from "zip archive" and from "zip archive containing an executable." A naive extension-based check is insufficient; content inspection (file magic, zip listing) is required.
- The AGENTS.md user-preference rule is the transition guard: it stops agents from adding new binaries during the G-005/G-006 development period while the developer's existing vendor/vfs binary commits are known and intentional.
- No persisted prior chat on this topic was found in project sessions; the motivation is the user's stated ultimate aim.