README.md
src/vfs - kit payload folders and per-.vfs payload declarations
Each <name>.vfs folder is the payload of a configured kit output (kit mapping:
src/runtime/mapvfs.toml), merged with the auto-generated _vfscommon.vfs overlay at bake
time. Folder ownership and payload rules: src/vfs/AGENTS.md.
Per-.vfs payload declarations (G-115)
A .vfs folder's payload can be DECLARED in a sibling toml file and materialized by the
build - while the folder remains the operative assembly area: dropping files in by hand
needs no declaration, and materialization never clobbers what it did not itself install.
- Declaration file:
src/vfs/<name>.vfs.toml(sibling ofsrc/vfs/<name>.vfs/, so the declaration itself is never part of the kit payload). - Processed by
tclsh src/make.tcl vfslibs, and automatically as a phase ofmake.tcl bake/bakehouse(a selective bake narrows to the selected kits' folders). - A
.vfswith NO declaration file is untouched - pure drop-in mode, exactly as before.
Entry format
[payload.<entryname>]
source = "vendorlib_tcl9/win32-x86_64/tcludp1.0.13" # folder path, resolved per source_root
source_root = "src" # optional: 'src' (default) or 'packages'
target = "lib_tcl9" # optional: folder INSIDE the .vfs (default: the .vfs root)
supersedes = ["udp1.0.12"] # optional: legacy sibling folders removed from target first
replace = true # optional: clean-slate the SAME-NAMED target folder first
source_root = "src"resolves againstsrc/- vendor trees (vendorlib*,vendormodules*), suite build products, any folder under src.source_root = "packages"resolves against<projectroot>/bin/packages- the untracked, consent-gated punkbin lib tier populated bytclsh src/make.tcl libfetch(artifact declarations + sha1 verification:src/runtime/libpackages.toml). This is how declared BINARY content arrives on a clean tree without being committed (G-004 direction).- The source folder is installed AS
<vfs>/<target>/<source-tail>/. targetmust be a relative path inside the.vfsfolder (no..).- Unknown keys, missing sources, or an unparseable file fail the build naming the entry.
Per-platform entries (G-127)
A source containing %platform% declares ONE payload selected per consuming kit
TARGET - the platform set is derived from the kit mapping (src/runtime/mapvfs.toml:
every kit output pairing this vfs, whatever its bake_default), never declared a second
time in the payload file:
[payload.tcllibc]
source_root = "packages"
source = "%platform%/tcl9/tcllibc" # resolved once per consuming kit target
target = "lib_tcl9"
- Each platform's copy materializes under
_targets/<platform>/<target>/inside the.vfsfolder - VCS-ignored staging (both VCS), regenerable from the declaration. - At bake time the kit's merged image gets ONLY its own target's subtree: the staging
tree is selected (
_targets/<kit target>/overlaid onto the image root) and dropped, upstream of the payload arch scan and the G-125 boot gate. supersedes/replaceapply within each platform's staging subtree;targetmust not itself contain%platform%(the staging prefix is implicit).- A
%platform%entry on a vfs no kit mapping consumes has no platform set to derive - it warns and is skipped. A missing per-platform source fails the build naming the entry and platform, exactly like any missing source. - Stale staging for a target no longer in the mapping is left in place (drop-in-wins
posture) - it never reaches an image; delete
_targets/<platform>/by hand to tidy.
Precedence (drop-in wins)
Materialization is punkcheck-tracked (records in src/vfs/.punkcheck, outside kit
payloads) using -overwrite synced-targets:
- Files the mechanism never declared are never touched (undeclared drop-ins survive re-materialization by construction).
- A file at a declared path is only overwritten when punkcheck's records show the mechanism itself installed it AND it is unmodified since. A pre-existing foreign copy (no install record) or a hand-modified installed copy is PRESERVED and reported ("changed file(s) NOT overwritten" note; per-file punkcheck skip lines).
- The declared, explicit exceptions:
supersedesremoves the named legacy sibling folders, andreplace = trueclean-slates the same-named package folder before install. Usereplace, or remove the files, to hand a collided path back to the declaration.
Relationship to the former vendorlib_vfs.toml
The per-package src/runtime/vendorlib_vfs.toml surface (G-037/G-139: [install.<name>]
entries with cross-kit target lists) was migrated into these per-.vfs files 2026-07-31 and
retired: per-kit files keep each kit's composition readable in one place, give new kits a
copy-a-sibling starting point, and are the surface later goals consume (G-141 derivation,
G-127 per-target payloads). A leftover vendorlib_vfs.toml is ignored with a warning.
Rationale and decision record: goals/G-115-declarative-vfs-composition.md (archived to
goals/archive/ once the goal flips).
Demonstration kit
punkdeclare.vfs + punkdeclare.vfs.toml demonstrate the mechanism end-to-end: the
folder in VCS carries only the boot fauxlink; its whole binary payload (tcludp from the
vendor tree, tcllibc from the packages tier) materializes from the declaration, and the
kit's smoke-require (udp, tcllibc - see [kit.punkdeclare] in mapvfs.toml) proves the
payload resolves inside the built artifact. tclsh src/make.tcl bake -confirm 0 punkdeclare
builds it (bake_default=false keeps it out of full bakes). The materialized
punkdeclare.vfs/lib_tcl9/ tree is deliberately NOT committed (ignored in both VCS) -
reproducing it from the declaration is the point.