CI / build (push) Has been cancelled
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.
140 lines
4.3 KiB
Bash
Executable File
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."
|