Extends the proposed goal with Approach 11 + matching Goal/Scope/Acceptance
clauses and a Context assembly finding (2026-08-08): zip-kit bake EXTRACTS
the runtime's attached vfs into the per-kit merge tree, so runtime batteries
are structurally maskable - but supersedes/replace run in the VFSPAYLOAD
phase before extraction and never reach them, so a bi-runtime kit with a
lower-versioned payload battery ships both copies and highest-wins picks the
runtime's. The amendment: mapvfs.toml kit-entry runtime_excludes applied at
merge time after extraction - the payload version wins by absence of
competition. Guardrails (boot-critical refusal, smokerequire proof),
provenance (mask = declared config, punkkit-stamp runtime_masks key,
no-volatile-fields safe; runtime's own record never edited), zip-lane first.
Alternatives recorded: require-time pinning via the managed ::package
override, runtime-variant proliferation. goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
# G-171 Routine builds never write tracked paths - explicit commands own VCS-visible changes
# G-171 Routine builds never write tracked paths - explicit commands own VCS-visible changes
Status: proposed
Status: proposed
Scope: src/make.tcl (bake/bakehouse/vfslibs - VFSPAYLOAD + PACKAGES phases, kit assembly, new explicit materialize/tidy commands); src/make.tcl sync_layouts phase (the mint-side tracked-path write) with its targets src/project_layouts/ and src/modules/punk/mix/#modpod-templates-999999.0a1.0/templates/project_layouts/ plus the workflow_text TERMINOLOGY/DIAGRAM 1b stage-verb assignment; src/vfs/ (payload declarations, _targets staging generalization, README.md + AGENTS.md precedence spec); src/_bake (assembly staging); bin/packages (lib-tier consumption); .gitignore + .fossil-settings/ignore-glob (staging ignore coverage); src/tests/shell/testsuites/punkexe/ (kill-probe + precedence characterization)
Scope: src/make.tcl (bake/bakehouse/vfslibs - VFSPAYLOAD + PACKAGES phases, kit assembly, new explicit materialize/tidy commands); src/make.tcl sync_layouts phase (the mint-side tracked-path write) with its targets src/project_layouts/ and src/modules/punk/mix/#modpod-templates-999999.0a1.0/templates/project_layouts/ plus the workflow_text TERMINOLOGY/DIAGRAM 1b stage-verb assignment; src/vfs/ (payload declarations, _targets staging generalization, README.md + AGENTS.md precedence spec); src/_bake (assembly staging); bin/packages (lib-tier consumption); .gitignore + .fossil-settings/ignore-glob (staging ignore coverage); src/tests/shell/testsuites/punkexe/ (kill-probe + precedence characterization); src/runtime/mapvfs.toml (kit-entry runtime-content mask declarations - 2026-08-08 amendment)
Goal: routine build operations (mint, bake/bakehouse/vfslibs and every phase they run) write only to VCS-ignored locations - declared payloads materialize into ignored staging and merge-time layering enacts drop-in-wins precedence identically on every machine - so an interrupted, buggy, or stale-tool bake cannot modify, delete, or shadow tracked files and git/fossil status stays truthful during and after any build; deliberate writes into tracked trees (materializing a fetched/built package into a .vfs folder as drop-in content, retiring superseded committed files, refreshing the thin-layout store) remain available only as explicit separately-invoked commands whose output is an ordinary reviewable VCS change, with help and docs steering to the declaration-based route by default.
Goal: routine build operations (mint, bake/bakehouse/vfslibs and every phase they run) write only to VCS-ignored locations - declared payloads materialize into ignored staging and merge-time layering enacts drop-in-wins precedence identically on every machine - so an interrupted, buggy, or stale-tool bake cannot modify, delete, or shadow tracked files and git/fossil status stays truthful during and after any build; deliberate writes into tracked trees (materializing a fetched/built package into a .vfs folder as drop-in content, retiring superseded committed files, refreshing the thin-layout store) remain available only as explicit separately-invoked commands whose output is an ordinary reviewable VCS change, with help and docs steering to the declaration-based route by default; the same merge-time mask mechanism additionally gives a kit a DECLARED way to exclude runtime-extracted content, so a payload-supplied battery version can ship as the sole indexed candidate instead of losing highest-wins resolution to the runtime's copy (2026-08-08 amendment).
Acceptance: from a clean tree, a full bake/bakehouse run - including runs killed at arbitrary mid-run points (kill-probe characterization) - leaves git status and fossil changes reporting nothing outside ignore-covered paths; the VFSPAYLOAD/PACKAGES phases self-check their write destinations and abort before writing any tracked path; a hand-dropped file shadowing a declared payload entry survives assembly with drop-in-wins precedence on a records-free fresh clone (characterized, with the unified regime including _targets documented in src/vfs/README.md); the explicit materialize/tidy command(s) exist and are documented as the sole sanctioned tracked-tree write path, and no bake/bakehouse phase invokes them; a bake -hold run stops after assembly leaving the resolved per-kit images inspectable in staging, and a subsequent plain bake completes to kits identical to a single uninterrupted bake - staged assembly is reused only under digest-confirmed input currency, and stale or hand-modified held state is redone, never shipped; the thin-layout sync writes no tracked path from a mint or bakehouse run - refreshing the layout store and its modpod payload is an explicitly-invoked command producing an ordinary reviewable VCS change, the mint commands detect and report a stale store instead of silently refreshing it (the modules mint packs the tracked modpod tree as it stands), and make.tcl's stage vocabulary names the movement - the layout store documented as the third VCS-tracked consumption tree beside src/bootsupport and src/vfs/_vfscommon.vfs.
Acceptance: from a clean tree, a full bake/bakehouse run - including runs killed at arbitrary mid-run points (kill-probe characterization) - leaves git status and fossil changes reporting nothing outside ignore-covered paths; the VFSPAYLOAD/PACKAGES phases self-check their write destinations and abort before writing any tracked path; a hand-dropped file shadowing a declared payload entry survives assembly with drop-in-wins precedence on a records-free fresh clone (characterized, with the unified regime including _targets documented in src/vfs/README.md); the explicit materialize/tidy command(s) exist and are documented as the sole sanctioned tracked-tree write path, and no bake/bakehouse phase invokes them; a bake -hold run stops after assembly leaving the resolved per-kit images inspectable in staging, and a subsequent plain bake completes to kits identical to a single uninterrupted bake - staged assembly is reused only under digest-confirmed input currency, and stale or hand-modified held state is redone, never shipped; the thin-layout sync writes no tracked path from a mint or bakehouse run - refreshing the layout store and its modpod payload is an explicitly-invoked command producing an ordinary reviewable VCS change, the mint commands detect and report a stale store instead of silently refreshing it (the modules mint packs the tracked modpod tree as it stands), and make.tcl's stage vocabulary names the movement - the layout store documented as the third VCS-tracked consumption tree beside src/bootsupport and src/vfs/_vfscommon.vfs; a kit declaring a runtime-content mask (mapvfs.toml kit-entry runtime_excludes) bakes to an image where the masked runtime paths are absent and the payload-supplied version is the sole indexed candidate (smokerequire proves resolution at the declared version inside the built artifact), punkkit-stamp.toml records the masked paths, boot-critical paths (tcl_library, boot core) are refused at declaration parse, kits declaring no mask assemble byte-identical to pre-mask bakes, and non-zip kit types declaring masks abort with a stated reason.
## Context
## Context
@ -60,6 +60,26 @@ templates-0.2.0.tm carries the same run's make.tcl, so there is no one-run lag)
and under this goal it moves with the rest into the explicit command, leaving the
and under this goal it moves with the rest into the explicit command, leaving the
mint to pack the tracked modpod tree as it stands.
mint to pack the tracked modpod tree as it stands.
Assembly finding 2026-08-08 (surfaced by the punk-kit-on-bi-runtime version
question; motivates the runtime-content mask amendment). Zip-kit assembly
EXTRACTS the runtime's attached vfs into the per-kit merge tree - the zip
extraction comment in make.tcl states why: image assembly replaces the entire
attached archive, "so we need the original data to be part of our targetvfs".
A bi runtime's batteries therefore pass through the bake as ordinary
merge-tree files and are structurally maskable - yet no declared vocabulary
reaches them: supersedes/replace run in the VFSPAYLOAD phase against payload
trees BEFORE per-kit extraction, so a kit pairing a bi runtime with a
lower-versioned payload battery ships BOTH copies and Tcl's highest-wins
resolution picks the runtime's (the doctrine recorded in mapvfs.toml's own
comments). User direction 2026-08-08: bi kits may carry conservative battery
versions while punk kits advance - which needs "ship lower and have it win"
as a declared kit property, not a side effect of what happens to be indexed.
The merge-time mask mechanism of Approach 2 is the natural home: one mask
vocabulary over both the payload layering and the runtime-extracted tree
(Approach 11). Cookfs/cookit types edit the payload inside the mounted
runtime - no extract-merge moment - so the mask is zip-lane first and other
types abort with a stated reason.
## Approach
## Approach
1. Generalize the G-127 staging pattern: ALL declared payload entries (not just
1. Generalize the G-127 staging pattern: ALL declared payload entries (not just
@ -110,6 +130,26 @@ mint to pack the tracked modpod tree as it stands.
generated from) - DIAGRAM 1b marks the store->modpod copy as mint input
generated from) - DIAGRAM 1b marks the store->modpod copy as mint input
preparation rather than layout update, and the bakehouse help's "does NOT run
preparation rather than layout update, and the bakehouse help's "does NOT run
the promotion gates" claim becomes true.
the promotion gates" claim becomes true.
11. Runtime-content masks (2026-08-08 amendment; see the Assembly finding in
Context): the Approach 2 mask vocabulary generalizes to the
runtime-extracted portion of the per-kit merge. A kit entry in
src/runtime/mapvfs.toml declares exclusions (e.g.
runtime_excludes = ["lib/tcllib2.0"]) applied at merge time AFTER
extraction, so a payload-supplied lower version becomes the sole indexed
candidate and wins by absence of competition rather than by fighting