#!/bin/bash # Migrate a project from the old copy-based model to the additive extension model. # Usage: ./migrate-project.sh /path/to/project set -e FRAMEWORK_DIR="$HOME/.automaton" PROJECT_DIR="${1}" if [ -z "$PROJECT_DIR" ]; then echo "Usage: $0 /path/to/project" exit 1 fi PROJECT_AUTOMATON="$PROJECT_DIR/.automaton" if [ ! -d "$PROJECT_AUTOMATON" ]; then echo "No .automaton/ directory found at $PROJECT_AUTOMATON" echo "Nothing to migrate." exit 0 fi EXTENSIONS_DIR="$PROJECT_AUTOMATON/extensions" DELETED=() MOVED=() KEPT=() ERRORS=() # Directories in the framework that projects may have copied SCAN_DIRS=("prompts" "contracts" "scripts") # Function to diff a file with its global counterpart diff_file() { local project_file="$1" local global_file="$2" if [ ! -f "$global_file" ]; then return 2 # file doesn't exist in global fi if diff -q "$project_file" "$global_file" >/dev/null 2>&1; then return 0 # identical else return 1 # different fi } # Check root-level framework files echo "Scanning $PROJECT_AUTOMATON for stale framework files..." echo "" for dir in "${SCAN_DIRS[@]}"; do project_dir="$PROJECT_AUTOMATON/$dir" global_dir="$FRAMEWORK_DIR/$dir" if [ ! -d "$project_dir" ]; then continue fi # Find all files in the project's copy of this directory while IFS= read -r -d '' project_file; do rel_path="${project_file#$PROJECT_AUTOMATON/}" global_file="$FRAMEWORK_DIR/$rel_path" if diff_file "$project_file" "$global_file"; then # Identical to global — safe to delete rm "$project_file" DELETED+=("$rel_path") echo " DELETED $rel_path (identical to global)" elif [ $? -eq 1 ]; then # Different from global — move to extensions/ ext_path="$EXTENSIONS_DIR/$dir/$(basename "$project_file")" mkdir -p "$(dirname "$ext_path")" mv "$project_file" "$ext_path" MOVED+=("$rel_path -> extensions/$dir/$(basename "$project_file")") echo " MOVED $rel_path → extensions/$dir/$(basename "$project_file") (customized)" fi done < <(find "$project_dir" -type f -print0 2>/dev/null || true) # Remove empty directories after moving/deleting files rmdir "$project_dir" 2>/dev/null || true done # Check for other stale root-level files (templates/, references/, etc.) while IFS= read -r -d '' project_file; do rel_path="${project_file#$PROJECT_AUTOMATON/}" global_file="$FRAMEWORK_DIR/$rel_path" # Skip protected files basename_file=$(basename "$rel_path") if [ "$basename_file" = ".agent.md" ] || [ "$basename_file" = ".rules.md" ]; then KEPT+=("$rel_path") continue fi if [ ! -f "$global_file" ]; then continue # not a framework file, skip fi if diff_file "$project_file" "$global_file"; then rm "$project_file" DELETED+=("$rel_path") echo " DELETED $rel_path (identical to global)" elif [ $? -eq 1 ]; then ext_path="$EXTENSIONS_DIR/$(basename "$rel_path")" mkdir -p "$(dirname "$ext_path")" mv "$project_file" "$ext_path" MOVED+=("$rel_path -> extensions/$(basename "$rel_path")") echo " MOVED $rel_path → extensions/$(basename "$rel_path") (customized)" fi done < <(find "$PROJECT_AUTOMATON" -maxdepth 1 -type f -name "*.md" -o -name "*.sh" -print0 2>/dev/null || true) # Report echo "" echo "=== Migration Summary ===" echo " Deleted: ${#DELETED[@]} (identical to global, removed)" echo " Moved: ${#MOVED[@]} (customized, moved to extensions/)" echo " Kept: ${#KEPT[@]} (.agent.md and .rules.md preserved)" if [ ${#ERRORS[@]} -gt 0 ]; then echo " Errors: ${#ERRORS[@]}" for err in "${ERRORS[@]}"; do echo " - $err" done fi echo "" echo "Migration complete."