harness: gitignore tmp/ + add promotion check to /save and /scc

- .gitignore: ignore root tmp/ (temp/ and .claude/tmp/ were already ignored;
  root tmp/ was not, which is how scratch got committed and needed cleanup).
- New .claude/scripts/tmp-promotion-check.sh: advisory, read-only, never blocks.
  Scans the gitignored scratch dirs (tmp/, temp/, .claude/tmp/) and flags files
  worth graduating (scripts, substantial docs, session-log-referenced) before
  they're lost to cleanup. Silent when scratch is empty.
- /save (Phase 4) and /scc (new step 2) run the check before sync.sh, pointing
  at .claude/TEMP_GRADUATION.md for the graduate-vs-delete decision.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-12 06:26:20 -07:00
parent c3282f8cf2
commit f495b08f42
4 changed files with 85 additions and 3 deletions

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
# Purpose: Advisory pre-save/commit check. The scratch dirs (tmp/, temp/, .claude/tmp/)
# are gitignored, so anything in them is INVISIBLE to git and will be lost on
# cleanup. Before a /save or /scc, surface what's sitting there and flag the
# files worth GRADUATING to a permanent home (per .claude/TEMP_GRADUATION.md).
# Usage: bash .claude/scripts/tmp-promotion-check.sh
# Behavior: read-only, never blocks. Always exits 0. Prints nothing when scratch is empty.
# Origin: added 2026-06-12 (wired into /save + /scc). See feedback in TEMP_GRADUATION.md.
set -u
ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
cd "$ROOT" || exit 0
SCRATCH_DIRS=(tmp temp .claude/tmp)
# Collect files across the scratch dirs (skip the dirs themselves; ignore .gitkeep).
mapfile -t FILES < <(
for d in "${SCRATCH_DIRS[@]}"; do
[ -d "$d" ] || continue
find "$d" -type f ! -name '.gitkeep' 2>/dev/null
done
)
[ "${#FILES[@]}" -eq 0 ] && exit 0 # nothing in scratch — stay silent
echo "[INFO] Promotion check: ${#FILES[@]} file(s) in scratch dirs (gitignored — NOT committed)."
echo " Graduate anything worth keeping before it's lost. Guide: .claude/TEMP_GRADUATION.md"
candidates=0
for f in "${FILES[@]}"; do
base="$(basename "$f")"
reason=""
# Script-like files: reusable automation worth a permanent home.
case "$base" in
*.py|*.sh|*.ps1|*.psm1|*.js|*.rb|*.pl) reason="script" ;;
esac
# Substantial docs (audit reports, dossiers) — size threshold ~4 KB.
if [ -z "$reason" ]; then
case "$base" in
*.md|*.csv)
sz=$(wc -c < "$f" 2>/dev/null || echo 0)
[ "${sz:-0}" -ge 4096 ] && reason="doc ($((sz/1024))KB)"
;;
esac
fi
# Referenced in a session log → clearly load-bearing.
if grep -rqlF "$f" session-logs/ clients/ projects/ 2>/dev/null; then
reason="${reason:+$reason, }referenced"
fi
if [ -n "$reason" ]; then
echo " [GRADUATE?] $f ($reason)"
candidates=$((candidates + 1))
fi
done
if [ "$candidates" -eq 0 ]; then
echo " No graduation candidates (looks like pure scratch — safe to leave or delete)."
else
echo " -> $candidates candidate(s). Move with: git mv <file> <scripts/|clients/<x>/reports/|projects/<p>/tools/>"
fi
exit 0