From 9678f710d48b6dd0ee5db7fdac778b7dc0aa57ce Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Thu, 6 Aug 2026 16:49:58 +1000 Subject: [PATCH] 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 --- GOALS.md | 2 +- goals/G-004-no-committed-binaries.md | 1 + goals/G-006-prebuilt-artifact-download.md | 2 + goals/G-065-declarative-vendoring.md | 4 ++ goals/G-141-libfetch-target-selection.md | 2 + goals/G-147-libfetch-revision-check.md | 2 + ...G-156-alpha-window-identifier-alignment.md | 4 ++ goals/G-157-exeless-kits-materialized.md | 3 + goals/G-162-bakelist-kit-freshness.md | 3 + goals/G-171-bake-writes-land-untracked.md | 57 +++++++++++++++++-- 10 files changed, 74 insertions(+), 6 deletions(-) diff --git a/GOALS.md b/GOALS.md index 650656b9..0a74c1c3 100644 --- a/GOALS.md +++ b/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 diff --git a/goals/G-004-no-committed-binaries.md b/goals/G-004-no-committed-binaries.md index 63ea5a98..453a5ae3 100644 --- a/goals/G-004-no-committed-binaries.md +++ b/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 + 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. diff --git a/goals/G-006-prebuilt-artifact-download.md b/goals/G-006-prebuilt-artifact-download.md index bf916862..657e2da9 100644 --- a/goals/G-006-prebuilt-artifact-download.md +++ b/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. diff --git a/goals/G-065-declarative-vendoring.md b/goals/G-065-declarative-vendoring.md index 03a3533f..7aad5fa7 100644 --- a/goals/G-065-declarative-vendoring.md +++ b/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. diff --git a/goals/G-141-libfetch-target-selection.md b/goals/G-141-libfetch-target-selection.md index 91af927f..a3ddf9ee 100644 --- a/goals/G-141-libfetch-target-selection.md +++ b/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. diff --git a/goals/G-147-libfetch-revision-check.md b/goals/G-147-libfetch-revision-check.md index e21f97b0..9c000636 100644 --- a/goals/G-147-libfetch-revision-check.md +++ b/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). diff --git a/goals/G-156-alpha-window-identifier-alignment.md b/goals/G-156-alpha-window-identifier-alignment.md index 9c83f421..a9317018 100644 --- a/goals/G-156-alpha-window-identifier-alignment.md +++ b/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. diff --git a/goals/G-157-exeless-kits-materialized.md b/goals/G-157-exeless-kits-materialized.md index 9bb9ef09..2870f7ab 100644 --- a/goals/G-157-exeless-kits-materialized.md +++ b/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. diff --git a/goals/G-162-bakelist-kit-freshness.md b/goals/G-162-bakelist-kit-freshness.md index fdb2f28a..4694abb1 100644 --- a/goals/G-162-bakelist-kit-freshness.md +++ b/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. diff --git a/goals/G-171-bake-writes-land-untracked.md b/goals/G-171-bake-writes-land-untracked.md index 92837deb..d4c184ac 100644 --- a/goals/G-171-bake-writes-land-untracked.md +++ b/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).