diff --git a/README.md b/README.md index 05e94cf..d64214f 100644 --- a/README.md +++ b/README.md @@ -215,6 +215,27 @@ python3 ~/.automaton/scripts/status.py --install-schedule my-loop \ --interval 3600 --project /path/to/project ``` +### Using Pi Dev with automaton +Pi Dev has the `automaton-guard-pi` plugin (installed by `register-guards.sh`) which blocks edits outside allowed phases. However, Pi Dev does **not** auto-load automaton's system prompt (unlike opencode). For the agent to understand tasks and phases, provide context manually. + +**Before starting a Pi Dev session**, run the context printer: +```bash +bash ~/.automaton/scripts/pi-automaton.sh +``` +Or if symlinked to `~/bin/`: +```bash +pi-automaton +``` + +Copy the output and paste it as your first message to the Pi Dev agent. This tells the agent about: +- The automaton workflow framework and phase lifecycle +- Active tasks in the current project +- The default model and VRAM configuration +- Project-specific rules from `AGENTS.md` +- Which commands to use for transitions and task creation + +The `automaton-guard-pi` plugin still blocks edits outside `implement`/`doc_review` even without this context — the context printer just makes the agent *aware* of why it's being blocked and how to use the framework correctly. + --- ## The Autopilot Workflow diff --git a/scripts/automaton-cleanup.sh b/scripts/automaton-cleanup.sh index 7819a21..18c4115 100755 --- a/scripts/automaton-cleanup.sh +++ b/scripts/automaton-cleanup.sh @@ -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-129/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-130/test_uninstall_via_disabled_re0" diff --git a/scripts/pi-automaton.sh b/scripts/pi-automaton.sh new file mode 100755 index 0000000..305a83a --- /dev/null +++ b/scripts/pi-automaton.sh @@ -0,0 +1,174 @@ +#!/usr/bin/env bash +# pi-automaton.sh — Pi Dev automaton context printer. +# +# Prints automaton project/framework context for the user to paste as their +# first message to a Pi Dev agent. Does NOT launch pi. +# +# Usage: +# cd /path/to/project +# bash ~/.automaton/scripts/pi-automaton.sh +# +# Copy the output and paste it as your first message in Pi Dev. + +set -euo pipefail + +FRAMEWORK_DIR="$HOME/.automaton" +STATUS_PY="$FRAMEWORK_DIR/scripts/status.py" + +# Colors +BOLD='\033[1m' +DIM='\033[2m' +NC='\033[0m' + +info() { echo -e " $1"; } +dim() { echo -e " ${DIM}$1${NC}"; } +dim_nl(){ echo -e "${DIM}$1${NC}"; } + +# --- Scope detection --- +CWD="$(pwd)" +if [ "$CWD" = "$FRAMEWORK_DIR" ] || [ "${CWD##"$FRAMEWORK_DIR"}" != "$CWD" ]; then + SCOPE="framework" + SCOPE_LABEL="framework mode (automaton itself)" + PROJECT_DIR="$FRAMEWORK_DIR" +elif [ -d "$CWD/.automaton" ]; then + SCOPE="project" + SCOPE_LABEL="project mode ($(basename "$CWD"))" + PROJECT_DIR="$CWD" +else + echo "" + echo "No automaton project detected in $CWD" + echo "" + echo "To onboard this project:" + echo " bash $FRAMEWORK_DIR/scripts/onboard-project.sh ." + echo "" + exit 1 +fi + +TASKS_DIR="$PROJECT_DIR/.automaton/tasks" +MODELS_FILE="$PROJECT_DIR/.automaton/models.json" +CONFIG_FILE="$PROJECT_DIR/.automaton/config.md" +AGENTS_FILE="$PROJECT_DIR/.automaton/AGENTS.md" + +# --- Collect data --- + +# Active tasks via status.py --audit --json +TASKS_JSON="" +if [ -f "$STATUS_PY" ] && [ -d "$TASKS_DIR" ]; then + TASKS_JSON=$(python3 "$STATUS_PY" --audit --json --project "$PROJECT_DIR" 2>/dev/null || true) +fi + +# Default model +DEFAULT_MODEL="" +if [ -f "$MODELS_FILE" ]; then + DEFAULT_MODEL=$(python3 -c " +import json +with open('$MODELS_FILE') as f: + m = json.load(f) +print(m.get('default', '')) +" 2>/dev/null || echo "") +fi + +# VRAM context snippet from config.md +CONFIG_SNIPPET="" +if [ -f "$CONFIG_FILE" ]; then + CONFIG_SNIPPET=$(grep -i 'context\|headroom\|target' "$CONFIG_FILE" 2>/dev/null | head -3 | sed 's/^/ /') +fi + +# Project rules from AGENTS.md +RULES_TEXT="" +if [ -f "$AGENTS_FILE" ]; then + RULES_TEXT=$(grep -v -E '^#|^$' "$AGENTS_FILE" 2>/dev/null | head -10) +fi + +# Can-edit status +CAN_EDIT_OUTPUT="" +if [ -f "$STATUS_PY" ]; then + CAN_EDIT_OUTPUT=$(python3 "$STATUS_PY" --can-edit --json --project "$PROJECT_DIR" 2>/dev/null || true) +fi + +# --- Build task list --- +TASK_LINES="" +TASK_COUNT=0 +if [ -n "$TASKS_JSON" ]; then + while IFS=$'\t' read -r name state edit_phase; do + if [ -n "$name" ]; then + FLAG="" + if [ "$edit_phase" = "true" ]; then + FLAG=" (edit allowed)" + elif [ "$state" != "backlog" ] && [ "$state" != "done" ] && [ "$state" != "blocked" ]; then + FLAG=" (read-only)" + fi + TASK_LINES+=" * $name\t\t$state$FLAG\n" + TASK_COUNT=$((TASK_COUNT + 1)) + fi + done < <(echo "$TASKS_JSON" | python3 -c " +import json, sys +data = json.load(sys.stdin) +tasks = [] +for t in data.get('tasks', []): + tasks.append((t['name'], t['state'])) +# Map edit-eligible phases +EDIT_PHASES = {'implement', 'doc_review'} +for name, state in tasks: + ep = 'true' if state in EDIT_PHASES else 'false' + print(f'{name}\t{state}\t{ep}') +" 2>/dev/null || true) +fi + +# --- Render --- +LINE="══════════════════════════════════════════════════" +SEP="──────────────────────────────────────────────────" + +echo "" +echo -e "${BOLD}${LINE}${NC}" +echo -e "${BOLD} Automaton Context — $SCOPE_LABEL${NC}" +echo -e "${BOLD}${LINE}${NC}" +echo "" + +echo -e "${BOLD}This project uses the automaton workflow framework.${NC}" +info "Tasks are tracked in $(basename "$PROJECT_DIR")/.automaton/tasks/" +info "and flow through phases:" + info "backlog → research → implement → code_review → bug_find → ... → complete" +echo "" + +if [ -n "$TASK_LINES" ]; then + echo -e "${BOLD}Active tasks:${NC}" + echo -e "$TASK_LINES" + echo "" +fi + +if [ -n "$DEFAULT_MODEL" ]; then + echo -e "${BOLD}Default model:${NC} $DEFAULT_MODEL" + echo "" +fi + +if [ -n "$CONFIG_SNIPPET" ]; then + echo -e "${BOLD}Configuration:${NC}" + echo "$CONFIG_SNIPPET" + echo "" +fi + +echo -e "${BOLD}To work on a task:${NC}" +info "python3 ~/.automaton/scripts/status.py --transition --task " +echo "" +echo -e "${BOLD}To create a new task:${NC}" +info "python3 ~/.automaton/scripts/status.py --create-task " +echo "" + +if [ -n "$RULES_TEXT" ]; then + echo -e "${BOLD}Project rules (from AGENTS.md):${NC}" + echo "$RULES_TEXT" | head -5 + echo "" +fi + +echo -e "${BOLD}Important:${NC}" +info "Only modify files when a task is in ${BOLD}implement${NC} or ${BOLD}doc_review${NC} phase" +info "All phase transitions go through status.py" +info "The automaton-guard-pi plugin blocks edits outside allowed phases" +echo "" + +echo -e "${DIM}$SEP${NC}" +dim_nl "Copy this entire block and paste it as your first message" +dim_nl "to the Pi Dev agent to provide automaton context." +echo -e "${DIM}$SEP${NC}" +echo "" \ No newline at end of file diff --git a/scripts/register-guards.sh b/scripts/register-guards.sh index 9103023..49d7a84 100755 --- a/scripts/register-guards.sh +++ b/scripts/register-guards.sh @@ -66,6 +66,31 @@ if command -v pi &>/dev/null; then INSTALLED_PI=true echo "Pi Dev: installed" fi + # Offer pi-automaton startup wrapper + PI_WRAPPER="$FRAMEWORK_DIR/scripts/pi-automaton.sh" + if [ -f "$PI_WRAPPER" ]; then + echo "" + echo "Pi Dev context wrapper available at:" + echo " $PI_WRAPPER" + echo "" + echo "Before starting a Pi Dev session, run this script to print" + echo "automaton project context that you can paste as your first message." + echo "" + echo " bash ~/.automaton/scripts/pi-automaton.sh" + echo "" + # Only prompt interactively if stdin is a terminal + BIN_DIR="$HOME/bin" + if [ -t 0 ] && [ ! -f "$BIN_DIR/pi-automaton" ]; then + echo -n "Symlink to ~/bin/pi-automaton for easier access? [Y/n] " + read -r REPLY + if [ -z "$REPLY" ] || [ "$REPLY" = "y" ] || [ "$REPLY" = "Y" ]; then + mkdir -p "$BIN_DIR" + ln -sf "$PI_WRAPPER" "$BIN_DIR/pi-automaton" + echo " Created $BIN_DIR/pi-automaton → $PI_WRAPPER" + echo " (ensure ~/bin is in your PATH)" + fi + fi + fi else echo "Pi Dev: not detected (pi not in PATH)" fi