fix: feat: persistent Claude tmux session for reviewer (#78)
Rewrite review-pr.sh to use persistent tmux sessions instead of one-shot
claude -p. Re-reviews inject incremental diffs into the same session so
Claude remembers what it flagged and can verify fixes were addressed.
- review-pr.sh: tmux session review-{project}-{pr}, phase protocol
(PHASE:review_complete), JSON output via file, retry on invalid JSON
- review-poll.sh: session lifecycle cleanup (merged/closed PRs, 4h idle)
- matrix_listener.sh: route human questions to review sessions via
/tmp/review-thread-map
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5ec587a7b6
commit
85d05cdee2
3 changed files with 263 additions and 100 deletions
|
|
@ -13,11 +13,13 @@ source "$(dirname "$0")/../lib/env.sh"
|
|||
|
||||
|
||||
REPO="${CODEBERG_REPO}"
|
||||
REPO_ROOT="${PROJECT_REPO_ROOT}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
API_BASE="${CODEBERG_API}"
|
||||
LOGFILE="$SCRIPT_DIR/review.log"
|
||||
MAX_REVIEWS=3
|
||||
REVIEW_IDLE_TIMEOUT=14400 # 4h: kill review session if idle
|
||||
|
||||
log() {
|
||||
printf '[%s] %s\n' "$(date -u '+%Y-%m-%d %H:%M:%S UTC')" "$*" >> "$LOGFILE"
|
||||
|
|
@ -34,6 +36,40 @@ fi
|
|||
|
||||
log "--- Poll start ---"
|
||||
|
||||
# --- Clean up stale review sessions ---
|
||||
# Kill sessions for merged/closed PRs or idle > 4h
|
||||
REVIEW_SESSIONS=$(tmux list-sessions -F '#{session_name}' 2>/dev/null | grep "^review-${PROJECT_NAME}-" || true)
|
||||
if [ -n "$REVIEW_SESSIONS" ]; then
|
||||
while IFS= read -r session; do
|
||||
pr_num="${session#review-"${PROJECT_NAME}"-}"
|
||||
phase_file="/tmp/review-session-${PROJECT_NAME}-${pr_num}.phase"
|
||||
|
||||
# Check if PR is still open
|
||||
pr_state=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \
|
||||
"${API_BASE}/pulls/${pr_num}" | jq -r '.state // "unknown"' 2>/dev/null) || true
|
||||
|
||||
if [ "$pr_state" != "open" ]; then
|
||||
log "cleanup: killing session ${session} (PR #${pr_num} state=${pr_state})"
|
||||
tmux kill-session -t "$session" 2>/dev/null || true
|
||||
rm -f "$phase_file" "/tmp/${PROJECT_NAME}-review-output-${pr_num}.json"
|
||||
cd "$REPO_ROOT"
|
||||
git worktree remove "/tmp/${PROJECT_NAME}-review-${pr_num}" --force 2>/dev/null || true
|
||||
rm -rf "/tmp/${PROJECT_NAME}-review-${pr_num}" 2>/dev/null || true
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check idle timeout (4h)
|
||||
phase_mtime=$(stat -c %Y "$phase_file" 2>/dev/null || echo 0)
|
||||
now=$(date +%s)
|
||||
if [ "$phase_mtime" -gt 0 ] && [ $(( now - phase_mtime )) -gt "$REVIEW_IDLE_TIMEOUT" ]; then
|
||||
log "cleanup: killing session ${session} (idle > 4h)"
|
||||
tmux kill-session -t "$session" 2>/dev/null || true
|
||||
rm -f "$phase_file" "/tmp/${PROJECT_NAME}-review-output-${pr_num}.json"
|
||||
continue
|
||||
fi
|
||||
done <<< "$REVIEW_SESSIONS"
|
||||
fi
|
||||
|
||||
PRS=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \
|
||||
"${API_BASE}/pulls?state=open&limit=20" | \
|
||||
jq -r --arg branch "${PRIMARY_BRANCH}" '.[] | select(.base.ref == $branch) | select(.draft != true) | select(.title | test("^\\[?WIP[\\]:]"; "i") | not) | "\(.number) \(.head.sha) \(.head.ref)"')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue