# G-024 mapvfs.config converted to toml (tomlish-parsed) with succinct scheme declarations Status: achieved 2026-07-31 Scope: src/runtime/mapvfs.config (replaced/deprecated); src/make.tcl (parsing); src/bootsupport/modules/tomlish-*.tm (parser dependency) Goal: the runtime-to-vfs-to-executable build mapping moves from the custom line format of src/runtime/mapvfs.config to a toml file parsed with the tomlish package - still supporting explicit per-executable mappings (runtime, vfs folder, output name, kit type) while also expressing generative schemes like the G-023 versioned naming in a single succinct declaration. Acceptance: a mapvfs toml file parsed via tomlish (no ad-hoc toml parsing) drives the build: every mapping currently active in mapvfs.config is expressible and at least one existing target builds identically from the toml; the G-023 versioned/dev/release-gated output scheme is declared in one entry that expands to its outputs without enumerating versions; malformed or unresolvable entries fail the build with a clear message naming the entry; the legacy .config format is either fully migrated (old parser removed) or explicitly deprecated with documented precedence between the two files. ## Context src/runtime/mapvfs.config maps runtime binaries and .vfs folders to named executables in a custom line format: one line per runtime, being the runtime filename followed by kit-configuration lists of 1-3 elements ({vfsfolder ?outputname? ?kittype?}, kittype in kit|zip|zipcat, `-` as runtime for runtime-less .kit builds, no-entry runtimes matching same-named .vfs folders implicitly). make.tcl parses it inline (~2795-2845). The format works but is idiosyncratic (comment/blank handling, positional defaults), is parsed ad hoc, and has no way to express a *scheme* - every output is one literal mapping, which conflicts with G-023 where output names derive from the project version at build time. tomlish is the project's toml parser (vendored at src/vendormodules and src/bootsupport/modules - the bootsupport copy matters since make.tcl is build tooling), so the replacement format is toml parsed via tomlish, consistent with the G-014 direction of toml + tomlish for declared configuration. ## Approach - A mapvfs toml file in src/runtime/ carrying two kinds of declarations: - **Explicit mappings** - the current capability, one entry per output: runtime, vfs folder, output name (defaulting from the vfs name), kit type. Everything active in mapvfs.config today must be expressible. - **Scheme declarations** - generative entries expanded by make.tcl, first consumer being the G-023 versioned scheme: one entry per Tcl generation declaring runtime + vfs + scheme=versioned (or similar) that expands to punkN---

.exe, punkN-dev.exe and the release-gated punkN.exe without enumerating versions. - Validation with entry-level error reporting: a malformed or unresolvable entry (missing runtime file, missing vfs folder, unknown kit type/scheme) fails the build naming the offending entry - matching the current warnings but structured. - Legacy handling is a decision to record here: either full migration (convert the file, delete the old parser) or a deprecation window (toml wins when present, .config honoured with a deprecation warning). Full migration is preferred - the file is small and repo-internal - unless project_layouts templates complicate it (layout copies of make.tcl/mapvfs.config sync via G-012 territory; note in completion report, do not hand-sync layouts). ## Alternatives considered - Keeping the custom line format and extending it with scheme syntax - rejected: doubles down on an ad-hoc parser exactly where the project is standardising on toml + tomlish. - Tcl-script config (source-able dict) - rejected for the same reason as in G-014: toml is the declared configuration format, editable without Tcl knowledge. ## Notes - The commented-out historical entries in mapvfs.config (broken-runtime notes, test cases) are documentation of past pitfalls - carry the useful ones into toml comments or this file rather than losing them. - Design direction from the developer, recorded 2026-07-27: the toml move is where NAMED GROUPINGS of entries should be considered, since toml gives the structure the current line format cannot. The prompt for it was verification kits - two third-party 32-bit runtimes were added to the win32-ix86 tier to verify G-129's boot-mount derivation (achieved 2026-07-27 - see goals/archive/G-129-kitboot-mountpoint-derivation.md; the entries are punkluck86 + punk91ix86), and they want to sit as active entries while being obviously a verification set rather than shipped products. Grouping would also give `make.tcl bake` and `bakelist` a name to select on beyond per-kit names (the G-121 selective-bake surface takes kit names today), and would give the commented-out historical entries above somewhere honest to live. - Related: G-023 (first scheme consumer), G-014 (toml+tomlish direction and the tomlish punk::args-documentation precondition - that precondition gates punk::config consumption; build-tooling use here can proceed with tomlish as-is), G-012 (layout template refresh, if layout copies of runtime config are affected). - G-037 (archived) named this file as the natural home for per-kit vendorlib payload declarations, and recorded that vendorlib and kit vfs trees have drifted in BOTH directions (vendorlib newer for udp, older for twapi) so any sync declaration needs explicit direction/authority semantics, not "copy newer over older" - see goals/archive/G-037-vendorlib-vfs-propagation.md. - G-115 relationship (recorded 2026-07-24 after overlap review; neither file previously referenced the other): G-115 declares .vfs payload composition in toml - per the G-037 note above, that is the payload-declaration half of this same config space, while this goal owns the runtime-to-vfs-to-executable mapping and schemes. Design the two as sibling grammars in one toml family (shared conventions, not two dialects); G-115's vendorlib_vfs.toml fold/supersede decision should cite this goal's scheme format. - G-121 (archived) delivered the shared parsed-mapping reader (::punkboot::lib::mapvfs_parse + mapvfs_kit_outputs): the bake kit machinery, bakelist and the bake/bakelist argdoc kit-name choices all consume the model, never the file format - this goal's toml conversion swaps the reader implementation underneath that surface, and bakelist is where its per-entry validation errors surface (runtime/vfs missing rows) - see goals/archive/G-121-bakelist-selective-bake.md - Related (activation overlap survey 2026-07-31, goals_xref score): G-127 - pairing one vfs definition with several targets is this format's cross-target consumer (its Scope names the mapping surface); G-131 - if container becomes a bake-time choice, a mapvfs entry naming a kit type stops implying a particular runtime (simplification landing on this format); G-137 - reads punkproject.toml fields at the same bake seam the versioned scheme reads the project version from. ## Progress ACHIEVED 2026-07-31 (activated and implemented same day; punkshell 0.38.0). Delivered: - src/runtime/mapvfs.toml (tomlish-parsed; file header = user-facing spec) with \[kit.\] / \[group.\] / \[scheme.\] tables. All 12 active mapvfs.config mappings migrated (entry order preserved so per-vfs runtime order and bakelist rows are unchanged); useful historical comments carried into the toml; mapvfs.config deleted from punkshell AND the project-0.1 layout template (converted to mapvfs.toml there). - Reader family in make.tcl under the unchanged G-121 model surface: mapvfs_locate (toml > legacy > toml-name default; PUNK_MAPVFS_CONFIG env override - the characterization seam G-123's increment-5 notes asked for), mapvfs_parse dispatching on extension, mapvfs_parse_toml (strict), mapvfs_parse_config (DEPRECATED fallback kept for un-migrated trees, parses with a NOTE; documented precedence: toml wins when both exist - the acceptance's deprecation arm, chosen because layout-generated projects out in the world still carry mapvfs.config, exactly the complication the Approach recorded). Shared toml helpers (toml_untag, toml_file_to_dict) hoisted to punkboot::lib (the two inline toml_untag definitions in the vfslibs/libfetch phases removed). - Model additions: format, groups, missing_detail, per-entry attrs (entry label, group, bake_default, scheme, scheme_role) riding as a 6th vfs_spec element (mapvfs_spec_attrs accessor; legacy tuples unchanged). Consumer dedupe fix: several toml entries may share one runtime on one vfs - mapvfs_kit_outputs and the kit-loop runtimes list now enumerate each distinct runtime's spec set once (the multiplication was latent in the legacy format too, unreachable with one-line-per-runtime configs). - Validation: fatal entry-named configerrors (unknown key/type/scheme, missing required keys, bad/conflicting targets, duplicate output names, tomlish/parse failures, unreadable project version for a scheme) - bake exits 3 before any machinery. Unresolvable-on-disk split DECIDED: missing vfs folder = fatal per entry (vfs folders are repo content, so absence means a wrong declaration); missing runtime FILE = entry-named recapped BUILD-WARNING + skip (runtime stores are ENVIRONMENT - legitimately part-populated on fresh clones, runtimes arrive via the consent-gated fetch tiers; hard-failing would brick clean-checkout bakes, and the live tree already carries a tolerated instance: punkmagic's tclsh90magic absent from the win32-x86_64 store). - Groups (the Notes' named-groupings direction): verify-ix86 (G-129 kits), declare-demo (G-115 demo kit), versioned; @ selection in bake/bakelist (mapvfs_match_outputs), group/default/scheme notes columns + per-kit detail lines in bakelist, groups listed in unknown-name errors and the argdoc choices. - G-023 versioned scheme: \[scheme.punk8\] + \[scheme.punk9\] declared in the shipped file (group versioned, bake_default=false pending G-023 activation - full bakes unchanged); expansion at parse time from punkproject.toml \[project\] version to -, -dev and release-gated records that join the model (bakelist/bake selection per the archived G-121 note). Release gating implemented in the kit loop: plain name created when absent, otherwise skipped with a message naming G-023's explicit release step (bin/punk9.exe, a 2024-11 artifact, correctly survives as the initially-created copy). Verification (win32-x86_64 host, tclsh90 9.0.3 runner + Tcl 8.6 tclsh driving make.tcl): - Model parity: bakelist rows from the legacy file (via PUNK_MAPVFS_CONFIG) vs mapvfs.toml IDENTICAL for the whole default set (kit/type/runtime/vfs/deployed columns). - Existing-target build identity: punkluck86 force-rebuilt under BOTH formats - byte-identical 1.73MB runtime+stamp prefix, identical 2993-member extracted payloads (zero content diffs). Byte-identity of the whole artifact is not a pipeline property (consecutive same-config rebuilds differ in zip timestamp metadata at the same offset - pre-existing, format-independent). Smoke Thread OK in the rebuilt kit. - Scheme end-to-end: punk9-dev baked and deployed by name from the expansion; punk9 release-gated skip demonstrated; after the 0.37.0->0.38.0 project bump the expanded rows track the new version with no config edit (the no-enumeration property live). - make.tcl workflow (both modes, width-checked), help bake (@group choices render), check (declared smoke list incl. punkdeclare) all verified; architecture_lint clean. - Tests: src/tests/shell/testsuites/punkexe suite 98 tests, 0 failures (runtests -include-paths shell/testsuites/punkexe/***) including 5 new G-024 characterizations in maketclbakelist.test (@group filter; via the PUNK_MAPVFS_CONFIG seam: scheme expansion shape, entry-named unknown-key error, bake exit-3 on unknown scheme, legacy deprecation NOTE) and updated pins in maketclplatform.test / maketclpayloadcheck.test. Remaining manual items: none for this goal. Follow-through pointers: G-023 activation flips the versioned group's bake_default (and owns the explicit release step + plain-name refresh policy); other live goals' Scope lines naming src/runtime/mapvfs.config or vendorlib_vfs.toml (G-101, G-127, G-131, G-141) are contract text left untouched - proposed rewordings flagged in the completion report for user approval. - G-133 (archived) landed the interim per-kit smoke-require declaration as a 5th mapvfs.config entry element (list of packages the built kit must plain-require); the toml conversion is its designated schema home, alongside the verification-set grouping already recorded here - see goals/archive/G-133-bake-payload-consistency-checks.md.