Browse Source

G-171: fold in the mint-side thin-layout sync + the stage-verb gap it exposed

Investigation prompted by the 0.56.2 BAKE SUMMARY work, whose 'make.tcl modules'
run silently refreshed the tracked layout copies: does the mint terminology cover
that write? It does not, and the write is G-171's own class on the mint side.

Finding. make.tcl's sync_layouts phase (modules/libs/packages/bakehouse) performs
two different movements fused in one block. (a) It copies src/make.tcl,
src/build.tcl, the root .gitignore and the bootsupport manifests into the tracked
src/project_layouts store; (b) it copies that store into the templates modpod
source tree. Neither is mint by make.tcl's own G-155 definition - nothing is
version-stamped and nothing lands in the projectroot modules*/lib*/ trees.
(a)'s target IS a VCS-tracked consumption tree - the store 'dev project.new'
generates from - so it has promotion's shape, and release-sequence step (9)
already commits it beside the two promotion targets. Of the three such trees only
this one has no named command, no gate and no TERMINOLOGY entry: 'sync' appears
there purely as a MECHANISM word, so the movement it performs was never assigned
a stage and inherited mint by accident of which subcommands call it. (b) is the
one genuinely mint-internal half - input preparation ordered deliberately before
the source-modules mint that packs #modpod-* trees (verified: a modules run's
freshly packed templates-0.2.0.tm carries the same run's make.tcl, so there is no
one-run lag).

Contract changes (user-approved wording, proposal-first per GOALS.md):
- Goal: subject widened to (mint, bake/bakehouse/vfslibs ...); the deliberate-
  writes clause now covers tracked TREES incl. refreshing the thin-layout store.
- Scope (both tiers, mirror verified identical): new element naming the
  sync_layouts phase, its two targets and the workflow_text TERMINOLOGY/DIAGRAM 1b
  stage-verb assignment.
- Acceptance: new clause - the sync writes no tracked path from a mint or
  bakehouse run, refreshing store + modpod payload is an explicitly-invoked
  command, the mint commands report a stale store instead of silently refreshing
  it, and the vocabulary names the layout store as the third consumption tree.

Non-contract: Context gains a fourth structural problem (incl. the bakehouse help
claiming it does NOT run the promotion gates while writing a tracked consumption
tree) plus the vocabulary finding; Approach gains step 10 (explicit command +
stale_bootsupport-shaped check + the TERMINOLOGY/DIAGRAM/help corrections).

Back-pointer sweep (goals_xref reported 14 goals G-171 references without one):
added 'Related: G-171' to the eight it lists as genuinely related - G-004, G-006,
G-065, G-141, G-147, G-156, G-157, G-162 - each worded from that goal's own side.
Deliberately NOT added to G-089, G-114, G-131, G-019, G-020, G-116: G-171's own
overlap survey records those as judged not related in substance, so a back-pointer
would assert a relationship the survey ruled out. They remain the only flagged
pairs, which is the intended state.

G-171 stays 'proposed' - activation is the user's call.

Verified: goals_lint clean (81 active, 90 archived); GOALS.md and detail-file
Scope lines byte-identical; goals_xref score G-171 now surfaces G-156 at 1.28 on
the two newly-added paths (the overlap the new Related line records, invisible
before the fold).

Claude-Session: https://claude.ai/code/session_017yWCebiNUVFtTrMA9GvsYd
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
master
Julian Noble 3 days ago
parent
commit
9678f710d4
  1. 2
      GOALS.md
  2. 1
      goals/G-004-no-committed-binaries.md
  3. 2
      goals/G-006-prebuilt-artifact-download.md
  4. 4
      goals/G-065-declarative-vendoring.md
  5. 2
      goals/G-141-libfetch-target-selection.md
  6. 2
      goals/G-147-libfetch-revision-check.md
  7. 4
      goals/G-156-alpha-window-identifier-alignment.md
  8. 3
      goals/G-157-exeless-kits-materialized.md
  9. 3
      goals/G-162-bakelist-kit-freshness.md
  10. 57
      goals/G-171-bake-writes-land-untracked.md

2
GOALS.md

@ -403,6 +403,6 @@ Scope: src/modules/punk/args-999999.0a1.0.tm (form selection/candidacy availabil
Detail: goals/G-167-punkargs-version-delta-availability.md
### G-171 [proposed] Routine builds never write tracked paths - explicit commands own VCS-visible changes
Scope: src/make.tcl (bake/bakehouse/vfslibs - VFSPAYLOAD + PACKAGES phases, kit assembly, new explicit materialize/tidy commands); 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)
Detail: goals/G-171-bake-writes-land-untracked.md

1
goals/G-004-no-committed-binaries.md

@ -93,3 +93,4 @@ A standing repo-wide rule in root `AGENTS.md` (User Preferences) already directs
- No persisted prior chat on this topic was found in project sessions; the motivation is the user's stated ultimate aim.
- G-138 (archived 2026-07-30) landed the punkbin lib tier that lets built library binaries leave the tracked tree: suite-built tcllib/tcllibc as immutable generation-tagged zips with embedded provenance records (see goals/archive/G-138-punkbin-library-artifact-tier.md).
- G-139 (archived 2026-07-30) DELIVERED the first major payoff of this goal: src/vendorlib_tcl8/win32-x86_64/tcllib1.21 and src/vendorlib_tcl9/win32-x86_64/tcllib2.0 are REMOVED from the tracked tree, replaced by the consent-gated fetch (make.tcl libfetch -> bin/packages tier -> lib_tcl<N> + kit vfs declarations), with kits validated and shipping verifiable embedded provenance - see goals/archive/G-139-punkbin-library-consumption.md. The remaining vendored binary trees (Img, itcl, sqlite, tdbc, twapi, ...) are this goal's outstanding scope; the tcllib pattern (publish tier + declared fetch + supersedes/replace switchover + runtests bracket) is the template.
- Related: G-171 - write-side complement: it removes bake as the maintainer of committed payload copies, so this goal's per-package removals decouple from bake behaviour. No dependency either way.

2
goals/G-006-prebuilt-artifact-download.md

@ -77,3 +77,5 @@ This goal is parallel to and independent of G-005. A user with zig uses G-005; a
sha1 verification against server sha1sums. This goal's mechanism, when
landed, should absorb/replace that interim flag rather than add a second -
see goals/archive/G-139-punkbin-library-consumption.md.
- Related: G-171 - moves build write locations only; every consent gate this goal
defines stays exactly as-is.

4
goals/G-065-declarative-vendoring.md

@ -118,3 +118,7 @@ remains the punkshell format (G-024 direction).
dirs only (git tracks no files there; the project-0.1 layout ships
bootsupport without them), so retiring the sketch's [libs] platform
sections retires the committed footprint.
- Related: G-171 - payload-side sibling: its explicit materialize/tidy and
layout-sync commands follow the same explicit-command pattern as this goal's sync
command, and this goal's undeclared-drop-in audit reporting complements the
authored-only .vfs it leaves behind.

2
goals/G-141-libfetch-target-selection.md

@ -130,3 +130,5 @@ has no equivalent of "materialize what this checkout needs".
goals/archive/G-101-tcl86-kit-container-strategy.md; G-077 achieved
2026-08-04 - goals/archive/G-077-punkexe-dash-e-oneliner.md). Non-path relations
G-006/G-065/G-004/G-123/G-027 from the libfetch reference sweep.
- Related: G-171 - reads the same *.vfs.toml consumption declarations from the write
side; this goal's target selection is unaffected by that write-location move.

2
goals/G-147-libfetch-revision-check.md

@ -42,3 +42,5 @@ edit stays manual. Consent keying is inherited unchanged from the fetch path
(sibling-path adjacency only; G-101 since achieved 2026-08-02 -
goals/archive/G-101-tcl86-kit-container-strategy.md); G-142 relation from the libfetch
coordination clause in its contract; no contract-level conflicts found.
- Related: G-171 - write-side sibling drawn from the same 2026-08-06 incident
evidence (the stale-tool / stale-tier currency class).

4
goals/G-156-alpha-window-identifier-alignment.md

@ -148,3 +148,7 @@ Archived-goal references in this file: G-112 achieved 2026-07-25
(goals/archive/G-087-thin-project-layouts.md); G-094 + G-095 achieved 2026-07-21
(goals/archive/G-094-punkcheck-single-lifecycle.md,
goals/archive/G-095-punkcheck-concurrent-writer-safety.md).
- Related: G-171 - takes ownership of the sync channels this goal re-seeds renamed
identities through (src/project_layouts + the templates modpod tree), moving them
out of the mint commands into an explicitly-invoked command; whichever lands
first, the other consumes the changed ownership of that channel.

3
goals/G-157-exeless-kits-materialized.md

@ -142,3 +142,6 @@ prerogative).
path siblings only), G-105/G-130 (buildsuite target dimension),
G-047/G-086/G-114/G-156 and G-031 (achieved 2026-08-02, since archived)
(layout-store neighbours).
- Related: G-171 - shares the working-modes-stay-first-class posture, and moves the
store->modpod sync (whose exclusion list this goal edits for bin/sdx.kit) out of
the mint commands into an explicitly-invoked command.

3
goals/G-162-bakelist-kit-freshness.md

@ -67,3 +67,6 @@ once per vfs and shared across kits).
Judged non-overlapping for this goal's mechanism: G-005/G-006/G-141
(runtime provisioning) and G-065 (declarative vendoring - a producer of payload
changes this goal would report, no mechanism overlap).
- Related: G-171 - its staging move changes this goal's digest input set (authored
.vfs + staging rather than the in-folder tree), and the per-kit digest machinery
is shared with its hold/resume seam.

57
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/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 (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 .vfs folders (materializing a fetched/built package as drop-in content, retiring superseded committed files) 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.
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.
## Context
@ -13,7 +13,7 @@ writing tracked paths is payload materialization: G-115's declarations (achieved
the same .vfs folders that were previously hand-assembled, so machine writes land in
tracked space as an evolutionary artifact, not an architectural necessity.
Three structural problems follow. (1) Drop-in-wins is enacted in place via punkcheck
Four structural problems follow. (1) Drop-in-wins is enacted in place via punkcheck
records that are machine-local and VCS-ignored, so the authored-vs-installed
distinction does not travel between machines - replace=true exists to wipe rather
than reason, which is exactly the operation that strands trees when a bake dies.
@ -23,6 +23,14 @@ goals/archive/G-127-crosstarget-vfs-bake.md) merges OVER the per-kit .vfs.
(3) Any bake failure mid-materialization leaves tracked files modified/deleted -
uninterpretable for a non-developer, and the reason three separate mid-bake-status
traps are recorded in project memory.
(4) The MINT side carries the same class: the sync_layouts phase of
modules/libs/packages/bakehouse copies src/make.tcl, src/build.tcl, the root
.gitignore and the bootsupport manifests into the tracked layout store, then the
store into the templates modpod source tree - tracked writes issued by a routine
build and owned by no explicit command. On a clean checkout they are no-ops, which
is why the class went unnoticed; with -dirty-abort 0 a bakehouse mutates tracked
layout files from uncommitted source, while its own help states it does NOT run
the promotion gates because "payload promotion is a confirm-gated, committed act".
Incident evidence 2026-08-06: on a consumer-shaped machine (reset --hard + pull +
fetch + bake), a stale untracked bin/punkzip.exe (pre-2.4.0) received the v2.4.0
@ -31,6 +39,27 @@ and the died bake stranded half-replaced tracked trees across the declared kits
a wall of git modifications/deletions with no user-facing recovery story. Under
this goal that whole class strands only ignored staging: recovery = rerun.
Vocabulary finding 2026-08-06 (surfaced by the BAKE SUMMARY work, whose mint run
synced the layout copies and prompted the question "does the mint terminology cover
this?"). make.tcl's stage verbs (G-155, achieved 2026-08-02 - see
goals/archive/G-155-mint-stage-vocabulary.md) define mint as version-stamping
magic-version sources into the projectroot modules*/lib*/ trees, and promote as
propagation into a VCS-tracked consumption tree. The layout sync stamps nothing and
lands nowhere near modules*/lib*/, so it is not mint by make.tcl's own definition;
its target IS a tracked consumption tree - the src/project_layouts/ store that
'dev project.new' generates from (G-087, achieved - see
goals/archive/G-087-thin-project-layouts.md) - so it has promotion's shape, and the
release sequence already commits it in step (9) beside the two promotion targets.
There are three such trees and only this one has no named command, no gate and no
TERMINOLOGY entry: 'sync' appears there purely as a MECHANISM word, so the movement
it performs was never assigned a stage and inherited mint by accident of which
subcommands call it. The store->modpod copy is the one genuinely mint-internal half
- input preparation ordered deliberately BEFORE the source-modules mint that packs
#modpod-* trees (verified 2026-08-06: a modules run's freshly packed
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.
## Approach
1. Generalize the G-127 staging pattern: ALL declared payload entries (not just
@ -68,6 +97,19 @@ this goal that whole class strands only ignored staging: recovery = rerun.
declarations + tier); the digest infrastructure serves both bakelist's
read-side verdicts and hold/resume's reuse decision (Approach 7); record the
decision in both files.
10. The mint-side write (Context (4)): an explicit command owns the thin-layout
sync - refreshing the layout store from src/make.tcl + src/build.tcl + the root
.gitignore + the bootsupport manifests, then the store->modpod payload - and
modules/libs/packages/bakehouse stop invoking it, detecting and REPORTING a
stale store instead (the same shape as the existing stale_bootsupport gate, so
the developer learns exactly when the step is due). make.tcl's own vocabulary
is corrected in the same work: TERMINOLOGY names the layout store as the third
VCS-tracked consumption tree beside src/bootsupport and
src/vfs/_vfscommon.vfs - widening 'promote' from what MOVES (minted packages)
to where it LANDS (a tracked tree a downstream consumer boots, ships or is
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.
## Alternatives considered
@ -88,7 +130,12 @@ this goal that whole class strands only ignored staging: recovery = rerun.
from bake behaviour. No dependency on G-004's completion.
- Related: G-157 - sibling commit-policy goal; shares the working-modes-stay-
first-class posture (uncommitted drop-ins and derived-project permissiveness
remain untouched).
remain untouched). Its Scope also edits the store->modpod sync exclusion list
(bin/sdx.kit), which this goal's explicit layout command inherits.
- Related: G-156 - its Scope re-seeds renamed identities through the same sync
channels this goal takes ownership of (src/project_layouts + the templates modpod
tree); whichever lands first, the other consumes the changed ownership of that
channel.
- Related: G-162 - input-freshness digests consume payload trees; the staging move
changes the digest input set, and the per-kit digest machinery is shared with
the hold/resume seam (Approach 7, 9).

Loading…
Cancel
Save