From d86636ac3f6408c5a4703d19cfc2ab90e12ac6c2 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Sun, 5 Apr 2026 14:16:13 -0400 Subject: [PATCH 1/3] 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" -- 2.43.0 From 04f07c04e673f792a37190c2c66f4d5b69a8ca5d Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Sun, 5 Apr 2026 14:23:24 -0400 Subject: [PATCH 2/3] fix: keep kimi queue labels truthful --- uniwizard/kimi-heartbeat.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/uniwizard/kimi-heartbeat.sh b/uniwizard/kimi-heartbeat.sh index baa2f53..5be38a5 100755 --- a/uniwizard/kimi-heartbeat.sh +++ b/uniwizard/kimi-heartbeat.sh @@ -305,6 +305,8 @@ $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 "$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 [ -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 -- 2.43.0 From e99e753c5c56b574c683900b1ec66cf8e1dad901 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Sun, 5 Apr 2026 15:32:16 -0400 Subject: [PATCH 3/3] chore: point kimi heartbeat at forge api --- uniwizard/kimi-heartbeat.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/uniwizard/kimi-heartbeat.sh b/uniwizard/kimi-heartbeat.sh index 5be38a5..16d3039 100755 --- a/uniwizard/kimi-heartbeat.sh +++ b/uniwizard/kimi-heartbeat.sh @@ -21,12 +21,7 @@ set -euo pipefail # --- Config --- TOKEN=$(cat "$HOME/.timmy/kimi_gitea_token" | tr -d '[:space:]') TIMMY_TOKEN=$(cat "$HOME/.config/gitea/timmy-token" | tr -d '[:space:]') -# Prefer Tailscale (private network) over public IP -if curl -sf --connect-timeout 2 "http://100.126.61.75:3000/api/v1/version" > /dev/null 2>&1; then - BASE="http://100.126.61.75:3000/api/v1" -else - BASE="http://143.198.27.163:3000/api/v1" -fi +BASE="${GITEA_API_BASE:-https://forge.alexanderwhitestone.com/api/v1}" LOG="/tmp/kimi-heartbeat.log" LOCKFILE="/tmp/kimi-heartbeat.lock" MAX_DISPATCH=10 # Increased max dispatch to 10 -- 2.43.0