# G-027 Pull-based infrastructure updates for punkshell-derived projects Status: proposed Scope: src/modules/punk/mix/commandset/project-999999.0a1.0.tm (project.new push path), src/modules/punkcheck-999999.0a1.0.tm (install provenance records), src/make.tcl (derived-project pull entrypoint) Goal: a project generated from a punkshell layout can pull infrastructure updates (make.tcl/build.tcl, bootsupport modules and libs, layout template payloads) from its originating punkshell project by running one command inside the derived project - replacing the current push model (`dev project.new -force 1 -update 1` run from punkshell) - with install provenance robust to derived-project workdir moves (not local relative paths alone), VCS-state awareness on both ends, and a recorded decision on pulling from remote sources. Acceptance: one documented command run inside a derived project updates its punkshell-derived infrastructure from the source punkshell project; the update still works after the derived project's working directory has been moved (proven by moving a scratch derived project and pulling); VCS integration on both ends: the pull applies the G-026 clean-checkout policy to the punkshell source, and reports (or refuses per option) when target files it would overwrite carry uncommitted local modifications in the derived project's git/fossil checkout; .punkcheck records remain the provenance basis (updates are recorded and unchanged targets skipped, as with existing punkcheck-tracked installs); the push flow keeps working until explicitly retired; the remote-pull question (updating from a remote punkshell repository rather than a local checkout) has a recorded design decision - implemented, or deferred with rationale in the detail file. ## Context Projects initialised via `dev project.new` (punk::mix::commandset::project::new) receive a snapshot of punkshell's layout system: make.tcl/build.tcl, bootsupport modules and libs, template payloads. That snapshot then drifts. The current remedy is a push from punkshell: re-running `dev project.new -force 1 -update 1` against the derived project. A pull - one command run inside the derived project - is the more natural shape: the derived project knows when it wants updating, and its owner is the right party to review what changes. Motivating incident (2026-07-06, tomlish project): a make.tcl vintage 2025-04 carried a bootsupport-update step that itself depended on a stale bundled fileutil::traverse (Tcl 8.x-only constraint, broken under 9.0.3), so the tool that should fix the drift was disabled by the drift; bootsupport/lib still had the obsolete per-platform layout; include_modules.config files were empty template stubs. Recovery required manual cross-project copying - exactly the push-shaped work this goal eliminates. A drifted derived project must be recoverable by a pull whose own machinery does not depend on the freshness of the drifted parts (the pull entrypoint should be small/self-contained enough to work from a stale project, or delivered as its first step). ## Current mechanism and its limits - .punkcheck records in the derived project record where targets were installed from (installer/source paths) - "roughly the right shape": provenance-driven, change-detected, skippable when unchanged. - Limits: - Source references are local relative paths - resolution breaks or silently mislocates if the derived project (or punkshell checkout) moves. - No VCS awareness: nothing checks whether the punkshell source is dirty (G-026 territory) or whether the pull would clobber uncommitted local modifications in the derived project. - Push-only initiation, from the punkshell side. ## Approach - A pull entrypoint in the derived project (make.tcl subcommand or a small standalone bootstrap that does not depend on the possibly-stale local infrastructure). - Provenance robust to moves: record the origin punkshell project by something more durable than a relative path - candidates: fossil project-code / git remote or commit identity, plus a locally-resolvable path hint refreshed on each pull; `dev projects.work` discovery (G-016/G-017) can re-locate a moved punkshell checkout by name/id when the stored path fails. - VCS integration on both ends: - Source side: G-026 clean-checkout policy shared, not reimplemented. - Target side: before overwriting, classify each target file - unmodified since last punkcheck install (safe), locally modified but committed (report/confirm), uncommitted local changes (refuse or explicit override). - Remote pulls: decide whether updates may come directly from a remote punkshell repository (fossil clone/sync or git fetch of a punkshell repo, or the G-006 artifact-download channel) rather than a local checkout. Considerations: provenance/verification of remote content, version pinning (pull a tagged punkshell release vs trunk), and interaction with the consent-gating principle of G-006. May be recorded as deferred with rationale. ## Documentation and goals ownership (design input, 2026-07-07) What a pull may touch splits by ownership, not by file type: - **Layout-owned docs**: most of the DOX tree documents the layout machinery itself (src/AGENTS.md build workflow, src/bootsupport/AGENTS.md contracts, src/tests/AGENTS.md harness usage, src/modules/AGENTS.md authoring conventions). Documentation whose subject is pulled infrastructure has the same provenance as that infrastructure and rides the same update channel - ordinary payload files under the target-side classification above (punkcheck-unmodified -> update; locally modified -> leave and report, optionally delivering the new version aside or as a diff for hand-merging). The tomlish src/tests port demonstrated the premise: punkshell's src/tests/AGENTS.md applied nearly verbatim to the derived project. - **Project-owned skeletons**: the root AGENTS.md (project identity, repo-wide notes, preferences, child index) and the GOALS framework (GOALS.md, goals/AGENTS.md, and an empty GOALS-archive.md so the maintenance rules' archive reference resolves from day one) are installed once at generation as thin skeletons and never pulled. Keeping the root template thin - rails, index, purpose placeholder - minimises the file agents customise most, and with it the diverged-so-frozen surface. - **Commit conventions are part of the seed**: the VCS-neutral commit conventions (Co-Authored-By/AI-attribution ban + Assisted-by trailer; see root AGENTS.md "Commit Conventions (any VCS)") propagate into the generated root AGENTS.md as seeded defaults the subproject developer may change. Generated projects start fossil-only but may adopt git, so the seeded text must stay VCS-neutral. - **Divergence-reducing convention**: layout-owned docs carry a marker line ("layout-owned; updated by pull when unmodified - record project-specific rules in the nearest project-owned doc instead") so DOX's update-the-closest-doc habit doesn't silently accrete project content into pull-managed files. - **Transitive chains**: since pulls come from the parent project (not the root punkshell), an intermediate project's deliberate modifications to layout-owned docs become the baseline its own derived projects inherit - a feature, not a conflict. ## Alternatives considered - Keeping push-only and just fixing its path robustness - rejected as the end state: the updater lives on the wrong side of the relationship; the derived project's owner should initiate and review. Push retained during transition. - Making derived projects git/fossil-track punkshell as an upstream remote and merge - rejected: derived projects are independent repos with their own history; infrastructure files are a curated payload, not a branch to merge. ## Notes - Related: G-012 (inert template payloads and the make.tcl template-refresh step feed what a pull delivers), G-016/G-017 (project discovery for re-locating a moved origin), G-026 (clean-checkout policy on the source), G-005/G-006 (remote artifact channels if remote pull proceeds). - The 2025-04 tomlish checkin "update bootsupport and make.tcl from punkshell" and the 2026-07-06 manual recovery are the concrete push-model precedents to test the pull against: a scratch project seeded at an old layout vintage should be fully recoverable by one pull. - G-062 (archived) recorded a follow-on relevant here: seeding LICENSE.txt into generated project layouts and pulling it into derived projects (deliberately excluded from G-062's acceptance) - see goals/archive/G-062-project-license-file.md.