Files
automaton/scripts/migrate-project.sh
T
Lap Tran 81ccf548e5
CI / build (push) Has been cancelled
Fix 10 audit bugs: path prefix matching, verdict parsing, CORS, stale-task detection, phase mapping
Batch 1 (High severity):
- Bug 1: --audit cat3 now checks .automaton/tasks/ paths
- Bug 4: Verdict PASS/FAIL uses structured ## Status: line parsing
- Bug 5: register-guards.sh checks .json/.jsonc, writes plugin key, strips comments
- Bug 7: --can-edit/--scope-check path prefix uses os.sep boundary

Batch 2 (Medium/Low severity):
- Bug 2: migrate-project.sh find command parentheses for -prune binding
- Bug 3: vram_detect model prefix matching with known-suffix whitelist
- Bug 6: dashboard reads .state file before artifact heuristic fallback
- Bug 8: removed wildcard CORS, added security headers (nosniff, DENY)
- Bug 9: stale-task detection uses .state.lastedit instead of .state mtime
- Bug 10: TEST_PLAN.md maps to test_design (was implement)

249 tests pass (up from 235). All 10 tasks driven through full workflow to completion.
2026-06-22 10:40:58 -04:00

140 lines
4.3 KiB
Bash
Executable File

#!/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)
# Task directory — tasks always live in .automaton/tasks/ for all modes
ROOT_TASKS="$PROJECT_DIR/tasks"
AUTOMATON_TASKS="$PROJECT_AUTOMATON/tasks"
if [ -d "$ROOT_TASKS" ] && [ ! -e "$AUTOMATON_TASKS" ]; then
echo " MOVING tasks/ → .automaton/tasks/ (tasks belong in .automaton/)"
mv "$ROOT_TASKS" "$AUTOMATON_TASKS"
MOVED+=("tasks/ -> .automaton/tasks/")
elif [ -d "$ROOT_TASKS" ] && [ -d "$AUTOMATON_TASKS" ]; then
echo " MERGING tasks/ contents into .automaton/tasks/"
cp -r "$ROOT_TASKS"/* "$AUTOMATON_TASKS/" 2>/dev/null || true
rm -rf "$ROOT_TASKS"
MOVED+=("tasks/ merged -> .automaton/tasks/")
fi
# 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."