#!/usr/bin/env bash # gstack-diff-scope — categorize what changed in the diff against a base branch # Usage: source <(gstack-diff-scope main) → sets SCOPE_FRONTEND=true SCOPE_BACKEND=false ... # Or: gstack-diff-scope main → prints SCOPE_*=... lines set -euo pipefail BASE="${1:-main}" # Get changed file list FILES=$(git diff "${BASE}...HEAD" --name-only 2>/dev/null || git diff "${BASE}" --name-only 2>/dev/null || echo "") if [ -z "$FILES" ]; then echo "SCOPE_FRONTEND=false" echo "SCOPE_BACKEND=false" echo "SCOPE_PROMPTS=false" echo "SCOPE_TESTS=false" echo "SCOPE_DOCS=false" echo "SCOPE_CONFIG=false" exit 0 fi FRONTEND=false BACKEND=false PROMPTS=false TESTS=false DOCS=false CONFIG=false while IFS= read -r f; do case "$f" in # Frontend: CSS, views, components, templates *.css|*.scss|*.less|*.sass|*.pcss|*.module.css|*.module.scss) FRONTEND=true ;; *.tsx|*.jsx|*.vue|*.svelte|*.astro) FRONTEND=true ;; *.erb|*.haml|*.slim|*.hbs|*.ejs) FRONTEND=true ;; *.html) FRONTEND=true ;; tailwind.config.*|postcss.config.*) FRONTEND=true ;; app/views/*|*/components/*|styles/*|css/*|app/assets/stylesheets/*) FRONTEND=true ;; # Prompts: prompt builders, system prompts, generation services *prompt_builder*|*generation_service*|*writer_service*|*designer_service*) PROMPTS=true ;; *evaluator*|*scorer*|*classifier_service*|*analyzer*) PROMPTS=true ;; *voice*.rb|*writing*.rb|*prompt*.rb|*token*.rb) PROMPTS=true ;; app/services/chat_tools/*|app/services/x_thread_tools/*) PROMPTS=true ;; config/system_prompts/*) PROMPTS=true ;; # Tests *.test.*|*.spec.*|*_test.*|*_spec.*) TESTS=true ;; test/*|tests/*|spec/*|__tests__/*|cypress/*|e2e/*) TESTS=true ;; # Docs *.md) DOCS=true ;; # Config package.json|package-lock.json|yarn.lock|bun.lockb) CONFIG=true ;; Gemfile|Gemfile.lock) CONFIG=true ;; *.yml|*.yaml) CONFIG=true ;; .github/*) CONFIG=true ;; requirements.txt|pyproject.toml|go.mod|Cargo.toml|composer.json) CONFIG=true ;; # Backend: everything else that's code (excluding views/components already matched) *.rb|*.py|*.go|*.rs|*.java|*.php|*.ex|*.exs) BACKEND=true ;; *.ts|*.js) BACKEND=true ;; # Non-component TS/JS is backend esac done <<< "$FILES" echo "SCOPE_FRONTEND=$FRONTEND" echo "SCOPE_BACKEND=$BACKEND" echo "SCOPE_PROMPTS=$PROMPTS" echo "SCOPE_TESTS=$TESTS" echo "SCOPE_DOCS=$DOCS" echo "SCOPE_CONFIG=$CONFIG"