From d86636ac3f6408c5a4703d19cfc2ab90e12ac6c2 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Sun, 5 Apr 2026 14:16:13 -0400 Subject: [PATCH] fix: block false kimi completion without pr proof --- uniwizard/kimi-heartbeat.sh | 62 ++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/uniwizard/kimi-heartbeat.sh b/uniwizard/kimi-heartbeat.sh index e7c172c..baa2f53 100755 --- a/uniwizard/kimi-heartbeat.sh +++ b/uniwizard/kimi-heartbeat.sh @@ -45,6 +45,31 @@ REPOS=( # --- Helpers --- log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; } +needs_pr_proof() { + local haystack="${1,,}" + [[ "$haystack" =~ implement|fix|refactor|feature|perf|performance|rebase|deploy|integration|module|script|pipeline|benchmark|cache|test|bug|build|port ]] +} + +has_pr_proof() { + local haystack="${1,,}" + [[ "$haystack" == *"proof:"* || "$haystack" == *"pr:"* || "$haystack" == *"/pulls/"* || "$haystack" == *"commit:"* ]] +} + +post_issue_comment_json() { + local repo="$1" + local issue_num="$2" + local token="$3" + local body="$4" + local payload + payload=$(python3 - "$body" <<'PY' +import json, sys +print(json.dumps({"body": sys.argv[1]})) +PY +) + curl -sf -X POST -H "Authorization: token $token" -H "Content-Type: application/json" \ + -d "$payload" "$BASE/repos/$repo/issues/$issue_num/comments" > /dev/null 2>&1 || true +} + # Prevent overlapping runs if [ -f "$LOCKFILE" ]; then lock_age=$(( $(date +%s) - $(stat -f %m "$LOCKFILE" 2>/dev/null || echo 0) )) @@ -257,20 +282,33 @@ print(payloads[0]['text'][:3000] if payloads else 'No response') " 2>/dev/null || echo "No response") if [ "$status" = "ok" ] && [ "$response_text" != "No response" ]; then - log "COMPLETED: $repo #$issue_num" - - # Post result as comment (escape for JSON) escaped=$(echo "$response_text" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read())[1:-1])" 2>/dev/null) - curl -sf -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ - -d "{\"body\":\" **KimiClaw result:**\\n\\n$escaped\"}" \ - "$BASE/repos/$repo/issues/$issue_num/comments" > /dev/null 2>&1 || true + if needs_pr_proof "$title $body" && ! has_pr_proof "$response_text"; then + log "BLOCKED: $repo #$issue_num — response lacked PR/proof for code task" + post_issue_comment_json "$repo" "$issue_num" "$TOKEN" "🟡 **KimiClaw produced analysis only — no PR/proof detected.** - # Remove kimi-in-progress, add kimi-done - [ -n "$progress_id" ] && curl -sf -X DELETE -H "Authorization: token $TIMMY_TOKEN" \ - "$BASE/repos/$repo/issues/$issue_num/labels/$progress_id" > /dev/null 2>&1 || true - [ -n "$done_id" ] && curl -sf -X POST -H "Authorization: token $TIMMY_TOKEN" -H "Content-Type: application/json" \ - -d "{\"labels\":[$done_id]}" \ - "$BASE/repos/$repo/issues/$issue_num/labels" > /dev/null 2>&1 || true +This issue looks like implementation work, so it is NOT being marked kimi-done. +Kimi response excerpt: + +$escaped + +Action: removing Kimi queue labels so a code-capable agent can pick it up." + [ -n "$progress_id" ] && curl -sf -X DELETE -H "Authorization: token $TIMMY_TOKEN" \ + "$BASE/repos/$repo/issues/$issue_num/labels/$progress_id" > /dev/null 2>&1 || true + [ -n "$kimi_id" ] && curl -sf -X DELETE -H "Authorization: token $TIMMY_TOKEN" \ + "$BASE/repos/$repo/issues/$issue_num/labels/$kimi_id" > /dev/null 2>&1 || true + else + log "COMPLETED: $repo #$issue_num" + post_issue_comment_json "$repo" "$issue_num" "$TOKEN" "🟢 **KimiClaw result:** + +$escaped" + + [ -n "$progress_id" ] && curl -sf -X DELETE -H "Authorization: token $TIMMY_TOKEN" \ + "$BASE/repos/$repo/issues/$issue_num/labels/$progress_id" > /dev/null 2>&1 || true + [ -n "$done_id" ] && curl -sf -X POST -H "Authorization: token $TIMMY_TOKEN" -H "Content-Type: application/json" \ + -d "{\"labels\":[$done_id]}" \ + "$BASE/repos/$repo/issues/$issue_num/labels" > /dev/null 2>&1 || true + fi else log "FAILED: $repo #$issue_num — status=$status"