feat: auto-update harness files when plugin version changes

setup.sh now stamps .harness-version in .loop/ at scaffold time. On each
/agent-loop:run, Phase 1 compares the installed harness version against
the plugin version and auto-updates lib/, prompts/, and loop.sh if stale.
Run state (prd.json, contracts, config.json) is preserved.

Also adds setup.sh --update mode for refreshing harness files without
re-scaffolding. Bump to 0.10.0.
This commit is contained in:
2026-04-02 09:02:41 -04:00
parent 1bd8004854
commit 71b00cf11f
4 changed files with 63 additions and 5 deletions

View File

@@ -10,7 +10,7 @@
"name": "agent-loop",
"source": "./",
"description": "Autonomous generator-evaluator agent loop for long-running coding tasks. Plan interactively, then execute with full visibility.",
"version": "0.9.0",
"version": "0.10.0",
"author": {
"name": "Sheldon"
},

View File

@@ -1,6 +1,6 @@
{
"name": "agent-loop",
"version": "0.9.0",
"version": "0.10.0",
"description": "Autonomous generator-evaluator agent loop for long-running coding tasks. Run /agent-loop:run to start.",
"author": {
"name": "Sheldon"

View File

@@ -10,10 +10,17 @@
set -euo pipefail
# --- Parse arguments ---
UPDATE_ONLY=false
MODE="${1:-implement}"
if [ "$MODE" = "--update" ]; then
UPDATE_ONLY=true
MODE="${2:-implement}" # mode not used in update, but keep arg parsing clean
fi
# --- Validate mode ---
if [[ ! "$MODE" =~ ^(implement|explore|fix)$ ]]; then
if [ "$UPDATE_ONLY" = false ] && [[ ! "$MODE" =~ ^(implement|explore|fix)$ ]]; then
echo "[setup] ERROR: Invalid mode '$MODE'. Must be: implement, explore, fix"
exit 1
fi
@@ -45,6 +52,37 @@ fi
echo "[setup] Harness source: $HARNESS_SRC"
# Read plugin version from source
PLUGIN_VERSION=""
if [ -f "$HARNESS_SRC/.claude-plugin/plugin.json" ]; then
if command -v jq &>/dev/null; then
PLUGIN_VERSION=$(jq -r '.version // empty' "$HARNESS_SRC/.claude-plugin/plugin.json" 2>/dev/null)
elif command -v python3 &>/dev/null; then
PLUGIN_VERSION=$(python3 -c "import json; print(json.load(open('$HARNESS_SRC/.claude-plugin/plugin.json')).get('version',''),end='')" 2>/dev/null)
fi
fi
# --- Update-only mode: refresh harness files without touching run state ---
if [ "$UPDATE_ONLY" = true ]; then
LOOP_DIR="$(pwd)/.loop"
if [ ! -d "$LOOP_DIR" ]; then
echo "[setup] ERROR: No .loop/ directory found. Run setup first."
exit 1
fi
echo "[setup] Updating harness files..."
cp -r "$HARNESS_SRC/prompts" "$LOOP_DIR/"
cp -r "$HARNESS_SRC/templates" "$LOOP_DIR/"
cp -r "$HARNESS_SRC/lib" "$LOOP_DIR/"
cp "$HARNESS_SRC/loop.sh" "$LOOP_DIR/"
chmod +x "$LOOP_DIR/loop.sh"
[ -n "$PLUGIN_VERSION" ] && echo "$PLUGIN_VERSION" > "$LOOP_DIR/.harness-version"
echo "[setup] Harness updated to ${PLUGIN_VERSION:-unknown}. Run state (prd.json, contracts, config.json) unchanged."
exit 0
fi
# --- Ensure git repo exists ---
if ! git rev-parse --git-dir &>/dev/null; then
echo "[setup] No git repo found. Initializing..."
@@ -79,6 +117,9 @@ cp -r "$HARNESS_SRC/lib" "$LOOP_DIR/"
cp "$HARNESS_SRC/loop.sh" "$LOOP_DIR/"
chmod +x "$LOOP_DIR/loop.sh"
# Stamp harness version
[ -n "$PLUGIN_VERSION" ] && echo "$PLUGIN_VERSION" > "$LOOP_DIR/.harness-version"
# Verify critical files
for f in prompts/generator/_base.md prompts/evaluator/_base.md templates/progress.md.template lib/state.sh loop.sh; do
if [ ! -f "$LOOP_DIR/$f" ]; then
@@ -99,6 +140,7 @@ triage/
archive/
.archive-staging/
.last-branch
.harness-version
.loop.lock
GITIGNORE

View File

@@ -20,7 +20,7 @@ Follow this sequence. Each phase checks what exists and skips if already done.
---
## Phase 1: Scaffold (if needed)
## Phase 1: Scaffold or Update Harness
Check if `.loop/config.json` exists.
@@ -36,7 +36,23 @@ bash "$(ls -d ~/.claude/plugins/cache/agent-loop/agent-loop/*/setup.sh 2>/dev/nu
Show the output. If setup fails, stop.
**If it already exists**, skip to Phase 2.
**If it already exists**, check if the harness files need updating. Compare the installed harness version against the plugin version:
```bash
INSTALLED=$(cat .loop/.harness-version 2>/dev/null || echo "unknown")
PLUGIN=$(jq -r '.version // empty' "$(ls -d ~/.claude/plugins/cache/agent-loop/agent-loop/*/.claude-plugin/plugin.json 2>/dev/null | tail -1)" 2>/dev/null || echo "unknown")
echo "installed=$INSTALLED plugin=$PLUGIN"
```
If the versions differ (or installed is "unknown"), update the harness files:
```bash
bash "$(ls -d ~/.claude/plugins/cache/agent-loop/agent-loop/*/setup.sh 2>/dev/null | tail -1)" --update
```
Tell the user: *"Updated harness files to v{version}."* Then continue to Phase 2.
If versions match, skip to Phase 2.
---