feat: live status-board comment + full-fleet dogfood (#1)
Build & push image / build-and-push (push) Successful in 6s
Build & push image / build-and-push (push) Successful in 6s
Phase 3: one consolidated, live-updating PR comment aggregating every model's per-lens progress (queued -> running -> finished + verdict), so the swarm's progress is visible at a glance and a watcher can tell when it's done. Opt-in statusWriter in the binary (atomic writes) + a background status-board.sh renderer wired through entrypoint.sh; default on, GADFLY_STATUS_BOARD=0 to disable. Also restores gadfly's dogfood swarm to the full cloud fleet (9 cloud + M5; M1 dropped as too slow) matching mort, and folds in the 3 real bugs the swarm found on its own PR (skip-binary stuck-waiting, panic-stuck lens, busy-loop on bad poll interval). All 36 findings graded via the gadfly MCP (18 real / 18 false-positive). gofmt clean, go vet quiet, go build + go test -race green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Steve Dudenhoeffer <steve@stevedudenhoeffer.com> Co-committed-by: Steve Dudenhoeffer <steve@stevedudenhoeffer.com>
This commit was merged in pull request #1.
This commit is contained in:
+53
-2
@@ -155,6 +155,12 @@ DEFAULT_CONC="${GADFLY_CONCURRENCY:-1}"
|
||||
|
||||
provider_of() { case "$1" in */*) echo "${1%%/*}";; *) echo "${GADFLY_PROVIDER:-ollama-cloud}";; esac; }
|
||||
|
||||
# Per-model status file path for the live board. The model id can contain '/'
|
||||
# and ':' (e.g. m1/qwen3:14b), so sanitize to a flat filename; the JSON inside
|
||||
# carries the real model/provider, so this just needs to be unique per model.
|
||||
STATUS_DIR="${WORKDIR}/status"
|
||||
status_file_for() { echo "${STATUS_DIR}/$(echo "$1" | tr -c '[:alnum:]._-' '_').json"; }
|
||||
|
||||
provider_cap() { # provider -> concurrency (override map "p=N,...", else default)
|
||||
local p="$1" item k v
|
||||
IFS=',' read -ra _caps <<< "${GADFLY_PROVIDER_CONCURRENCY:-}"
|
||||
@@ -167,8 +173,19 @@ provider_cap() { # provider -> concurrency (override map "p=N,...", else default
|
||||
}
|
||||
|
||||
review_one() {
|
||||
local sf=""
|
||||
[ "${GADFLY_STATUS_BOARD:-1}" != "0" ] && sf="$(status_file_for "$1")"
|
||||
PROVIDER=ollama MODEL="$1" GADFLY_BIN="/usr/local/bin/gadfly" GADFLY_REPO_DIR="$REPO_DIR" \
|
||||
GADFLY_STATUS_FILE="$sf" \
|
||||
bash "${SCRIPTS_DIR}/run.sh" || log "model $1 failed (continuing)"
|
||||
# If the binary never wrote real status (run.sh skipped it: empty diff, no key,
|
||||
# binary missing), the pre-seed stays {started:0, done:false} and the board
|
||||
# would show this model "waiting to start" forever and never reach N/N. Mark
|
||||
# such a never-started file done so the board can complete. The binary stamps a
|
||||
# nonzero `started`, so that reliably distinguishes "ran" from "skipped".
|
||||
if [ -n "$sf" ] && [ -f "$sf" ] && [ "$(jq -r '.started // 0' "$sf" 2>/dev/null)" = "0" ]; then
|
||||
tmp="$(jq '.done = true' "$sf" 2>/dev/null)" && printf '%s' "$tmp" > "$sf"
|
||||
fi
|
||||
}
|
||||
|
||||
# Normalize the model list (trim, drop blanks) into MODEL_LIST.
|
||||
@@ -197,10 +214,44 @@ run_lane() { # $1=provider: run its models, at most `cap` at a time
|
||||
wait
|
||||
}
|
||||
|
||||
# --- live status board (optional, default on) ------------------------------
|
||||
# Each model process publishes per-lens progress to STATUS_DIR/<model>.json; a
|
||||
# background renderer (status-board.sh) upserts ONE consolidated PR comment so
|
||||
# progress across all models/lenses is visible at a glance — and a watcher can
|
||||
# tell when the whole swarm is finished. Advisory/best-effort; the per-model
|
||||
# findings still land in each model's own comment. Disable with
|
||||
# GADFLY_STATUS_BOARD=0.
|
||||
BOARD_PID=""
|
||||
if [ "${GADFLY_STATUS_BOARD:-1}" != "0" ]; then
|
||||
rm -rf "$STATUS_DIR"; mkdir -p "$STATUS_DIR"
|
||||
# Pre-seed every model as queued so the board shows the full swarm from t=0,
|
||||
# even models still waiting on their provider lane's concurrency cap. Each
|
||||
# binary overwrites its own file with real per-lens detail once it starts.
|
||||
for m in "${MODEL_LIST[@]}"; do
|
||||
jq -n --arg model "$m" --arg provider "$(provider_of "$m")" \
|
||||
'{model:$model, provider:$provider, started:0, updated:0, done:false, lenses:[]}' \
|
||||
> "$(status_file_for "$m")" 2>/dev/null || true
|
||||
done
|
||||
GITEA_API="$GITEA_API" GITEA_TOKEN="$GITEA_TOKEN" PR="$PR" GADFLY_STATUS_DIR="$STATUS_DIR" \
|
||||
bash "${SCRIPTS_DIR}/status-board.sh" &
|
||||
BOARD_PID=$!
|
||||
log "status board started (pid ${BOARD_PID})"
|
||||
fi
|
||||
|
||||
log "providers: ${PROVIDERS:-none}"
|
||||
# Each provider lane runs in parallel; cap is enforced within each lane.
|
||||
# Each provider lane runs in parallel; cap is enforced within each lane. Track
|
||||
# the lane PIDs so we wait ONLY for the review work — not the status board,
|
||||
# which intentionally runs until we signal it below.
|
||||
LANE_PIDS=()
|
||||
for p in $PROVIDERS; do
|
||||
run_lane "$p" &
|
||||
LANE_PIDS+=("$!")
|
||||
done
|
||||
wait
|
||||
[ "${#LANE_PIDS[@]}" -gt 0 ] && wait "${LANE_PIDS[@]}"
|
||||
|
||||
# Reviews are done: signal the board to render the final state once and exit.
|
||||
if [ -n "$BOARD_PID" ]; then
|
||||
touch "${STATUS_DIR}/.done" 2>/dev/null || true
|
||||
wait "$BOARD_PID" 2>/dev/null || true
|
||||
fi
|
||||
log "done"
|
||||
|
||||
Reference in New Issue
Block a user