#!/usr/bin/env bash # A script writes only under its own repository (git rev-parse --show-toplevel of its own path), the downloads folder # and the scratch dirs. It never builds a target path from another worktree's name, from a list of worktrees or from a # walk over $HOME/Projects. Ruled 6 October 2026: five worktrees held 0.3.14's site rows as uncommitted edits to tracked # files after the pre-push hook's site build fetched the live downloads index and rewrote its snapshot in whatever tree # the push ran from (site/build.mjs now writes the snapshot only on SITE_DOWNLOADS_REFRESH=1 or in CI). Runs in CI and # locally; --self-test shows it firing. set -euo pipefail cd "$(git rev-parse --show-toplevel)" # a path built from a worktree list or a Projects walk: `git worktree list` piped into a loop with a write, or # $HOME/Projects, ~/Projects, /Users/*/Projects used in a path (comments and docs excluded; strings in tests excluded) PAT='(\$HOME|~|/Users/[a-z]+)/Projects/igneum-wt-|(\$HOME|~|/Users/[a-z]+)/Projects/(\*|igneum\*|igneum-wt-\*)|git worktree list[^|]*\|[^#]*(cp|mv|tee|>|writeFileSync|install )' # the shared checkout as an absolute default (/Users//Projects/igneum/...) is the lesser class: a read of a binary # or a script there, overridable by an environment variable. Listed as a warning; the row of 6 October 2026 moves each # to an env-only default (no fallback path) and this pattern then joins PAT. WARN='/Users/[a-z]+/Projects/igneum/' check_file() { local f="$1" bad=0 while IFS= read -r line; do local code="${line%%#*}" [[ "$code" =~ ^[[:space:]]*(//|\*|/\*) ]] && continue [[ "$code" =~ $PAT ]] || continue echo "foreign-tree: $f builds a path into another worktree or a Projects walk: ${line:0:140}"; bad=1 done < "$f" return $bad } if [ "${1:-}" = "--self-test" ]; then t="$(mktemp -d)"; trap 'rm -rf "$t"' EXIT printf 'cp out.json "$HOME/Projects/igneum-wt-other/site/downloads.json"\nfor d in ~/Projects/igneum*/; do echo "$d"; done\n' > "$t/bad.sh" printf 'for w in $(git worktree list | cut -d" " -f1); do cp x "$w/site/x"; done\n' > "$t/bad2.sh" printf 'ROOT="$(git rev-parse --show-toplevel)"; cp out.json "$ROOT/site/downloads.json"\n# ~/Projects/igneum is fine in a comment\n' > "$t/good.sh" check_file "$t/bad.sh" && { echo "self-test failed: bad.sh passed"; exit 1; } check_file "$t/bad2.sh" && { echo "self-test failed: bad2.sh passed"; exit 1; } check_file "$t/good.sh" || { echo "self-test failed: good.sh flagged"; exit 1; } echo "self-test passed: a Projects path fails, a worktree-list loop with a write fails, an own-toplevel write passes"; exit 0 fi fail=0 # `|| true`: with pipefail a file without a warning hit fails this pipeline, and set -e then ends the script silently with # exit 1 (bash 3.2 on the Mac; the two CI runs right after this check landed on 6 October 2026 died the same way) while IFS= read -r f; do grep -nE "$WARN" "$f" | grep -vE '^[0-9]+:\s*(#|//)' | sed "s|^|foreign-tree (warning, env-only default owed): $f:|" | cut -c1-200 || true; done < <(git ls-files 'tools/**' 'packaging/**' 'infra/**' 'relay/**' | grep -E '\.(sh|mjs|js|py|ps1)$' | grep -v '^tools/ci/no-foreign-tree-writes.sh$') while IFS= read -r f; do check_file "$f" || fail=1; done < <(git ls-files 'tools/**' 'packaging/**' 'site/*.mjs' 'infra/**' 'relay/**' | grep -E '\.(sh|mjs|js|py|ps1)$' | grep -v '^tools/ci/no-foreign-tree-writes.sh$') [ "$fail" = 0 ] && echo "foreign-tree: every script writes under its own toplevel" exit $fail