feat(pi): pi-automaton.sh startup context printer for Pi Dev
Pi Dev doesn't auto-load automaton's system prompt (unlike opencode), so the agent has no awareness of tasks, phases, or status.py commands. This bridges that gap: - scripts/pi-automaton.sh: NEW — detects scope (framework/project), reads active tasks, default model, config snippet, AGENTS.md rules, and prints a formatted context block the user pastes as their first message to the Pi Dev agent. Does NOT launch pi. - scripts/register-guards.sh: EXTENDED — after Pi Dev guard install, offers to symlink pi-automaton.sh to ~/bin/pi-automaton (interactive prompt only when stdin is a terminal). - README.md: added 'Using Pi Dev with automaton' FAQ subsection documenting the context printer workflow.
This commit is contained in:
@@ -215,6 +215,27 @@ python3 ~/.automaton/scripts/status.py --install-schedule my-loop \
|
|||||||
--interval 3600 --project /path/to/project
|
--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
|
## The Autopilot Workflow
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#!/usr/bin/env bash
|
#!/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"
|
||||||
|
|||||||
Executable
+174
@@ -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 <phase> --task <name>"
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}To create a new task:${NC}"
|
||||||
|
info "python3 ~/.automaton/scripts/status.py --create-task <name>"
|
||||||
|
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 ""
|
||||||
@@ -66,6 +66,31 @@ if command -v pi &>/dev/null; then
|
|||||||
INSTALLED_PI=true
|
INSTALLED_PI=true
|
||||||
echo "Pi Dev: installed"
|
echo "Pi Dev: installed"
|
||||||
fi
|
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
|
else
|
||||||
echo "Pi Dev: not detected (pi not in PATH)"
|
echo "Pi Dev: not detected (pi not in PATH)"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user