Browse Source

G-171 amendment: runtime-content masks (declared kit-level battery demotion)

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
master
Julian Noble 2 days ago
parent
commit
e42587cd79
  1. 55
      goals/G-171-bake-writes-land-untracked.md

55
goals/G-171-bake-writes-land-untracked.md

@ -1,9 +1,9 @@
# G-171 Routine builds never write tracked paths - explicit commands own VCS-visible changes
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)
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.
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.
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; 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; 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
@ -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
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
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
preparation rather than layout update, and the bakehouse help's "does NOT run
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
Tcl's highest-wins selection. Guardrails: boot-critical paths
(tcl_library, punkboot core) are refused at declaration parse;
interdependent-battery hazards (e.g. tcllibc compiled against a tcllib
version) stay the declarer's responsibility with smokerequire as the
proving surface (the 2026-07-27 Thread-shadowing incident is the
cautionary precedent for silent version substitution). Provenance: a
mask is declared config - a deterministic content input, so recording
it in punkkit-stamp.toml (a runtime_masks key) is no-volatile-fields
safe; the runtime's ridden-in punkbin-artifact.toml then overstates
attached_batteries for the masked kit, and the stamp's record of the
masked paths is the honest correction - the runtime's own record is
never edited. Zip-lane first; cookfs/cookit kits declaring masks abort
with a stated reason until an in-place arm exists.
## Alternatives considered
@ -122,6 +162,15 @@ mint to pack the tracked modpod tree as it stands.
- Requiring committed payload removal first - rejected as sequencing: that is
G-004's own arc (artifact coverage per package); this goal works with committed
payloads still present and decouples their eventual removal from bake behaviour.
- Require-time version pinning instead of runtime-content masks (a declared pin
table enforced via the G-176-era managed ::package override) - workable and
kit-declarable, rejected for this goal's scope: both copies would still ship
(image weight, and the demoted copy stays findable by -exact requires), it
adds a runtime policy layer where assembly-time absence suffices, and it
belongs to the libunknown/commandstack arc if per-consumer version ranges are
ever wanted. Also rejected: runtime-variant proliferation as the only answer
(a suite-built variant per battery-version combination) - correct for
wholesale battery omission, combinatorial for per-kit version selection.
## Notes

Loading…
Cancel
Save