fix(install): make install.sh idempotent + add onboard-project.sh

- install.sh: no longer exits early when ~/.automaton exists.
  Skips the clone but runs all setup (VRAM detection, guards,
  self-improvement loop, virtualenv). Both curl|bash and
  git-clone + ./install.sh now work correctly.
- onboard-project.sh: new script that bootstraps automaton in a
  project — creates .automaton/ skeleton, detects models, writes
  config.md, inits git, installs hooks, adds .gitignore entries.
- README.md: fix install flow docs (curl|bash + clone-then-run),
  add onboard-project.sh as Option A for project setup
This commit is contained in:
Lap Tran
2026-06-26 13:54:28 -04:00
parent f980ccfe27
commit b880f2535a
4 changed files with 266 additions and 49 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
#!/usr/bin/env bash
python3 "/Users/laptran/.automaton/scripts/status.py" --cleanup-done --days 7 --project "/private/var/folders/f5/yv0dzbnx47x3yp8sc_2519gh0000gn/T/pytest-of-laptran/pytest-127/test_uninstall_via_disabled_re0"
python3 "/Users/laptran/.automaton/scripts/status.py" --cleanup-done --days 7 --project "/private/var/folders/f5/yv0dzbnx47x3yp8sc_2519gh0000gn/T/pytest-of-laptran/pytest-128/test_uninstall_via_disabled_re0"
+34 -28
View File
@@ -3,27 +3,39 @@ set -e
FRAMEWORK_DIR="$HOME/.automaton"
if [ -d "$FRAMEWORK_DIR" ]; then
echo "automaton already installed at $FRAMEWORK_DIR"
echo "Run './update.sh' to update."
exit 0
fi
GIT_URL="${1:-}"
if [ -z "$GIT_URL" ]; then
echo "ERROR: Git URL required."
echo "Usage: ./install.sh <git-url>"
echo "Example: ./install.sh https://github.com/user/automaton.git"
if [ ! -d "$FRAMEWORK_DIR" ]; then
# Fresh install — need a Git URL to clone
if [ -z "$GIT_URL" ]; then
echo "ERROR: Git URL required for fresh install."
echo ""
echo "Usage:"
echo " curl -fsSL https://raw.githubusercontent.com/<user>/automaton/main/scripts/install.sh | bash -s -- <git-url>"
echo ""
echo " --- or ---"
echo ""
echo " git clone <git-url> ~/.automaton"
echo " bash ~/.automaton/scripts/install.sh"
echo ""
echo "The framework is cloned to ~/.automaton. Choose your URL carefully"
echo "as it cannot be changed later without reinstalling."
exit 1
fi
echo "Cloning automaton from $GIT_URL to $FRAMEWORK_DIR..."
git clone "$GIT_URL" "$FRAMEWORK_DIR"
echo ""
else
echo "automaton already installed at $FRAMEWORK_DIR — running setup steps..."
if [ -n "$GIT_URL" ]; then
echo "Note: Git URL argument ignored because ~/.automaton already exists."
echo "To update, run: cd ~/.automaton && ./update.sh"
fi
echo ""
echo "The framework is cloned to ~/.automaton. Choose your URL carefully"
echo "as it cannot be changed later without reinstalling."
exit 1
fi
echo "Cloning automaton from $GIT_URL to $FRAMEWORK_DIR..."
git clone "$GIT_URL" "$FRAMEWORK_DIR"
# --- Everything below is idempotent and runs on both fresh and existing installs ---
echo ""
echo "=== VRAM / Context Detection ==="
echo "Detecting your system's VRAM to recommend task decomposition settings..."
echo ""
@@ -31,7 +43,7 @@ echo ""
# Run VRAM detection script if it exists
if [ -f "$FRAMEWORK_DIR/scripts/vram_detect.py" ]; then
# Run in project-dir context so it can read framework overhead
detection_output=$(cd "$FRAMEWORK_DIR" && python3 "$FRAMEWORK_DIR/scripts/vram_detect.py" 2>&1)
detection_output=$(cd "$FRAMEWORK_DIR" && python3 "$FRAMEWORK_DIR/scripts/vram_detect.py" 2>&1 || true)
# Extract JSON output (the block after "=== JSON Output ===")
json_output=$(echo "$detection_output" | sed -n '/=== JSON Output ===/,$p' | tail -n +2)
@@ -40,12 +52,9 @@ if [ -f "$FRAMEWORK_DIR/scripts/vram_detect.py" ]; then
echo "$detection_output"
# Extract key values from JSON using Python
recommended_k=$(echo "$json_output" | python3 -c 'import json,sys; print(json.load(sys.stdin)["recommended_k"])')
max_peak_kb=$(echo "$json_output" | python3 -c 'import json,sys; print(json.load(sys.stdin)["max_peak_context_kb"])')
headroom=$(echo "$json_output" | python3 -c 'import json,sys; print(json.load(sys.stdin)["headroom"])')
gpu_vram=$(echo "$json_output" | python3 -c 'import json,sys; print(json.load(sys.stdin)["gpu_vram_gb"])')
ram_gb=$(echo "$json_output" | python3 -c 'import json,sys; print(json.load(sys.stdin)["ram_gb"])')
model_context=$(echo "$json_output" | python3 -c 'import json,sys; print(json.load(sys.stdin)["model_context_kb"])')
recommended_k=$(echo "$json_output" | python3 -c 'import json,sys; print(json.load(sys.stdin)["recommended_k"])' 2>/dev/null || echo "?")
max_peak_kb=$(echo "$json_output" | python3 -c 'import json,sys; print(json.load(sys.stdin)["max_peak_context_kb"])' 2>/dev/null || echo "?")
headroom=$(echo "$json_output" | python3 -c 'import json,sys; print(json.load(sys.stdin)["headroom"])' 2>/dev/null || echo "?")
echo ""
echo "=== Recommended VRAM Configuration ==="
@@ -72,11 +81,8 @@ echo ""
echo "Installation complete."
echo ""
echo "Next steps:"
echo " 1. cd into a project and run the onboarding prompt"
echo " 2. In each project that uses git, install the automaton hooks:"
echo " bash ~/.automaton/scripts/install-hooks.sh /path/to/project"
echo ""
echo "These hooks block commits and pushes when no task is in an edit-allowed phase."
echo " 1. Onboard a project: bash ~/.automaton/scripts/onboard-project.sh /path/to/project"
echo " 2. Or tell your agent: 'Onboard this project into automaton'"
echo ""
# Register pre-edit guards for detected harnesses
+184
View File
@@ -0,0 +1,184 @@
#!/usr/bin/env bash
# onboard-project.sh — Bootstrap automaton in a new or existing project.
#
# Usage:
# bash ~/.automaton/scripts/onboard-project.sh /path/to/project
#
# Creates .automaton/ skeleton, detects models, creates config, inits git,
# installs hooks, and verifies everything works.
set -euo pipefail
FRAMEWORK_DIR="$HOME/.automaton"
PROJECT_DIR="${1:-}"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
info() { echo -e "${BLUE}INFO:${NC} $1"; }
ok() { echo -e "${GREEN}OK:${NC} $1"; }
warn() { echo -e "${YELLOW}WARN:${NC} $1"; }
error() { echo -e "${RED}ERROR:${NC} $1"; }
# --- Argument checks ---
if [ -z "$PROJECT_DIR" ]; then
error "Usage: bash ~/.automaton/scripts/onboard-project.sh /path/to/project"
exit 1
fi
PROJECT_DIR="$(cd "$PROJECT_DIR" 2>/dev/null && pwd)" || true
if [ -z "$PROJECT_DIR" ] || [ ! -d "$PROJECT_DIR" ]; then
echo ""
error "'$1' does not exist."
echo " Create it first: mkdir -p '$1'"
echo " Then re-run this script."
exit 1
fi
if [ ! -d "$FRAMEWORK_DIR/scripts" ]; then
error "Framework not found at $FRAMEWORK_DIR."
echo " Install the framework first:"
echo " curl -fsSL https://raw.githubusercontent.com/<user>/automaton/main/scripts/install.sh | bash -s -- <git-url>"
echo " Or: git clone <git-url> ~/.automaton && bash ~/.automaton/scripts/install.sh"
exit 1
fi
echo ""
echo "========================================"
echo " Automaton Project Onboarding"
echo " Project: $PROJECT_DIR"
echo "========================================"
echo ""
# --- Step 1: Create .automaton/ skeleton ---
AUTO_DIR="$PROJECT_DIR/.automaton"
if [ -d "$AUTO_DIR" ]; then
warn "$AUTO_DIR already exists — skipping skeleton creation"
else
info "Creating .automaton/ skeleton..."
mkdir -p "$AUTO_DIR/tasks" "$AUTO_DIR/loops" "$AUTO_DIR/design"
ok "Created $AUTO_DIR/"
fi
# --- Step 2: Models ---
MODELS_FILE="$AUTO_DIR/models.json"
if [ -f "$MODELS_FILE" ]; then
warn "$MODELS_FILE already exists — skipping model detection"
else
info "Probing local models..."
if python3 "$FRAMEWORK_DIR/scripts/detect_models.py" --write --project "$PROJECT_DIR" 2>/dev/null; then
ok "Detected models written to $MODELS_FILE"
else
info "Auto-detection failed. Creating minimal models.json..."
cat > "$MODELS_FILE" <<- 'EOF'
{
"models": [
{"name": "default-model", "provider": "local", "context": 32768}
],
"default": "default-model"
}
EOF
warn "Edit $MODELS_FILE to set your actual model(s)."
fi
fi
# --- Step 3: Config ---
CONFIG_FILE="$AUTO_DIR/config.md"
if [ -f "$CONFIG_FILE" ]; then
warn "$CONFIG_FILE already exists — skipping"
else
info "Creating config.md..."
PROJECT_NAME="$(basename "$PROJECT_DIR")"
if [ -f "$FRAMEWORK_DIR/scripts/vram_detect.py" ]; then
vram_output=$(cd "$FRAMEWORK_DIR" && python3 "$FRAMEWORK_DIR/scripts/vram_detect.py" 2>/dev/null || true)
json_part=$(echo "$vram_output" | sed -n '/=== JSON Output ===/,$p' | tail -n +2)
recommended=$(echo "$json_part" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("recommended_k","16"))' 2>/dev/null || echo "16")
else
recommended="16"
fi
cat > "$CONFIG_FILE" <<- EOF
# $PROJECT_NAME — Automaton Configuration
## VRAM Configuration
- **Auto-detect**: Yes
- **Target context**: ${recommended}k tokens
- **Headroom**: 25%
- **Max peak context per sub-task**: $((recommended * 3 / 4))k tokens
## Model Configuration
# Uses models.json for model divergence enforcement.
# Default model is read from models.json's "default" key.
EOF
ok "Created $CONFIG_FILE"
fi
# --- Step 4: Project name ---
NAME_FILE="$AUTO_DIR/project-name.md"
if [ -f "$NAME_FILE" ]; then
warn "$NAME_FILE already exists — skipping"
else
PROJECT_NAME="$(basename "$PROJECT_DIR")"
echo "$PROJECT_NAME" > "$NAME_FILE"
ok "Created $NAME_FILE ($PROJECT_NAME)"
fi
# --- Step 5: Git ---
GIT_DIR="$PROJECT_DIR/.git"
if [ -d "$GIT_DIR" ]; then
ok "Git repository already initialized"
else
info "Initializing git repository..."
cd "$PROJECT_DIR" && git init
ok "Git initialized"
fi
# --- Step 6: Git hooks ---
if [ -d "$GIT_DIR" ]; then
info "Installing git hooks..."
bash "$FRAMEWORK_DIR/scripts/install-hooks.sh" "$PROJECT_DIR"
fi
# --- Step 7: .gitignore ---
GITIGNORE="$PROJECT_DIR/.gitignore"
if [ -f "$GITIGNORE" ]; then
if ! grep -q ".automaton/tasks/" "$GITIGNORE" 2>/dev/null; then
echo "" >> "$GITIGNORE"
echo "# Automaton" >> "$GITIGNORE"
echo ".automaton/tasks/" >> "$GITIGNORE"
echo ".automaton/loops/*/worktree/" >> "$GITIGNORE"
warn "Added automaton entries to .gitignore"
fi
else
cat > "$GITIGNORE" <<- 'EOF'
# Automaton
.automaton/tasks/
.automaton/loops/*/worktree/
.automaton/loops/*/outputs/
EOF
ok "Created .gitignore with automaton entries"
fi
# --- Step 8: Verify ---
info "Verifying setup..."
cd "$FRAMEWORK_DIR"
python3 "$FRAMEWORK_DIR/scripts/status.py" --project "$PROJECT_DIR" --audit 2>&1 | head -5 || true
echo ""
echo "========================================"
echo -e "${GREEN} Onboarding complete!${NC}"
echo "========================================"
echo ""
echo " Project: $PROJECT_DIR"
echo " Config: $CONFIG_FILE"
echo " Models: $MODELS_FILE"
echo ""
echo " Next steps:"
echo " 1. cd $PROJECT_DIR"
echo " 2. Create a task:"
echo " python3 ~/.automaton/scripts/status.py --create-task my-first-task --project ."
echo " 3. Start working with your agent."
echo ""