Browse Source
Index entry + detail file goals/G-171-bake-writes-land-untracked.md; goals_lint clean (81 live, 90 archived). Drafted at user direction from the 2026-08-06 consumer-machine incident: a stale untracked bin/punkzip.exe (pre-2.4.0) received the v2.4.0 -b flag, swallowed it as the archive-name positional (misdirected 90MB src/-b archive), the kit-container step failed and the died bake stranded half-replaced tracked src/vfs trees - the failure class this goal removes by construction. Contract: routine bake/bakehouse/vfslibs phases write only to VCS-ignored locations (declared payloads materialize into ignored staging; merge-time layering enacts drop-in-wins identically on records-free fresh clones); deliberate tracked-tree writes remain available only as explicit materialize/tidy commands whose output is an ordinary reviewable VCS change, with docs steering to declarations by default. Acceptance keys on a kill-probe (clean tree in, clean tree out at arbitrary kill points), phase write-target self-checks, and a 'bake -hold' inspection point whose completion must equal a single uninterrupted bake - staged assembly reused only under digest-confirmed currency (machinery shared with G-162), held staging machine-owned (inspection sanctioned, hand-edits redone, never shipped). Related: G-004 (write-side complement), G-157, G-162, G-065, G-141, G-147, G-006; deliberately revises archived G-115's operative-assembly-area stance and generalizes archived G-127's staging pattern. Claude-Session: https://claude.ai/code/session_01EukjNTv2r5msFgHzWgaCdS Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.commaster
2 changed files with 128 additions and 0 deletions
@ -0,0 +1,124 @@
|
||||
# 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. |
||||
|
||||
## Context |
||||
|
||||
The kit merge already runs entirely in ignored staging (src/_bake). The only step |
||||
writing tracked paths is payload materialization: G-115's declarations (achieved |
||||
2026-07-31 - see goals/archive/G-115-declarative-vfs-composition.md) automate filling |
||||
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 |
||||
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. |
||||
(2) Two precedence regimes coexist: in-folder materialization preserves drop-ins, |
||||
while _targets staging (G-127, achieved - see |
||||
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. |
||||
|
||||
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 |
||||
-b flag, wrote a misdirected 90MB archive to src/-b, the kit-container step failed, |
||||
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. |
||||
|
||||
## Approach |
||||
|
||||
1. Generalize the G-127 staging pattern: ALL declared payload entries (not just |
||||
%platform% forms) materialize into ignored staging; the tracked .vfs folder is |
||||
never a materialization target of any routine phase. |
||||
2. Unify precedence at merge time: staging merged first, authored .vfs merged over |
||||
it (drop-in wins), supersedes/replace expressed as merge-time masks; record the |
||||
deliberate flip of the current _targets-over-.vfs order; document in |
||||
src/vfs/README.md; characterize. |
||||
3. Explicit commands own tracked-tree writes: a tidy command retiring superseded |
||||
committed files (report-then-act), and a materialize command that deliberately |
||||
lands a fetched/built package into a .vfs folder as drop-in content for the |
||||
developer/builder persona (user direction 2026-08-06) - both producing ordinary |
||||
reviewable VCS changes, with help text steering to declarations by default. |
||||
4. Defense in depth: the phases enumerate write destinations and abort before |
||||
touching any tracked path. |
||||
5. Kill-probe characterization: clean tree in, clean tree out, at arbitrary kill |
||||
points. |
||||
6. Optional interim hardening (independent value if migration is staged): |
||||
temp-sibling + atomic-swap for the current in-folder materialization, removing |
||||
the stranded-mid-replace mode before the full move lands. |
||||
7. Hold point: 'bake -hold' stops after assembly (post payload-staging + merge + |
||||
per-target selection, pre container/deploy) with the resolved per-kit images |
||||
in staging for inspection; a subsequent plain bake completes. Deliberate holds |
||||
and interrupted bakes unify: any completing run re-verifies staged assembly |
||||
against per-kit input digests (the G-162 machinery, write-side) and reuses |
||||
only what is confirmed current. Held staging is machine-owned - inspection is |
||||
sanctioned, hand-edits are not, and a digest mismatch means redo, not ship. |
||||
bakelist surfaces held state alongside its freshness verdicts. The |
||||
project-version gate applies to both invocations. |
||||
8. DOX revision: src/vfs/AGENTS.md + README.md - the authored .vfs remains the |
||||
drop-in surface; the resolved view is src/_bake (optionally a resolved-view |
||||
report); revise the "operative assembly area" language accordingly. |
||||
9. Coordinate with G-162: digest inputs become authored .vfs + staging (or |
||||
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. |
||||
|
||||
## Alternatives considered |
||||
|
||||
- Generalized per-kit ignore lines (punkdeclare pattern for every kit) - workable |
||||
interim, rejected as endpoint: machine writes still land inside tracked folders, |
||||
ignore bookkeeping grows per kit, authored-vs-machine mixing persists, and |
||||
supersedes still mutates tracked files from inside bake. |
||||
- Hardening only (step 6 atomic swap) - rejected as endpoint: shrinks the window |
||||
but any bake bug can still mutate tracked files; the class survives. |
||||
- 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. |
||||
|
||||
## Notes |
||||
|
||||
- Related: G-004 - parent hygiene arc; write-side complement: bake stops being the |
||||
maintainer of committed payload copies, so G-004's per-package removals decouple |
||||
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). |
||||
- 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). |
||||
- Related: G-065 - declarative vendoring is the source-side sibling surface; its |
||||
sync command is the same explicit-command pattern, and its audit's |
||||
undeclared-drop-in reporting complements an authored-only .vfs. |
||||
- Related: G-141 - consumption-driven libfetch selection reads the same |
||||
*.vfs.toml declarations; unaffected by the write-location move. |
||||
- Related: G-147 - fetch-side sibling from the same 2026-08-06 evidence |
||||
(content-keyed tier tree currency). |
||||
- Related: G-006 - consent posture untouched: this goal moves write locations |
||||
only; every network-consent gate stays as-is. |
||||
- Related (archived): G-115 (achieved 2026-07-31 - see |
||||
goals/archive/G-115-declarative-vfs-composition.md) - the declarative surface |
||||
consumed here; this goal deliberately revises its "folder remains the operative |
||||
assembly area" stance: the authored folder stays the drop-in surface, |
||||
machine-written content leaves it. |
||||
- Related (archived): G-127 (achieved - see |
||||
goals/archive/G-127-crosstarget-vfs-bake.md) - the ignored-staging + merge |
||||
mechanism generalized here, and the origin of the second precedence regime this |
||||
goal unifies. |
||||
- Related (archived): G-155 (achieved 2026-08-02, archived) - the _bake/_mint |
||||
stage-workdir vocabulary this staging extends. |
||||
- Tool-level fixes from the 2026-08-06 incident (punk::zip accelerator version |
||||
handshake before emitting v2.4.0-only flags; punkzip strict rejection of unknown |
||||
dash-flags) harden the trigger and are deliberately outside this contract - this |
||||
goal removes the blast radius, not the trigger. |
||||
- Overlap survey 2026-08-06 (goals_xref paths over src/vfs, src/make.tcl, |
||||
src/_bake, bin/packages): related in substance - G-004, G-141, G-065, G-162, |
||||
plus policy/evidence siblings G-157, G-147, G-006 added conceptually; surveyed |
||||
and judged not related in substance: G-089, G-114, G-131 (boot/_config surface), |
||||
G-019 (payload content trimming), G-020 (Scope names a lib_tcl9 path only), |
||||
G-116 (tcltls payload constituent - its removal stays G-004-era work). |
||||
Loading…
Reference in new issue