- Add scripts/lib/common.sh (ORG/BOT/FORGE_BACKEND, logging, process_running) - discover.sh: dedupe review-requested+assignee PRs; JSON+summary formats - discover.sh: FORGE_BACKEND=forgejo via Forgejo API + stoke token - Fix poll-loop process detection (basename, not install path) - health-check: jq-safe JSON; backend-aware auth (gh or stoke) - install-live: require rsync/jq/tmux; soft-warn missing gh/stoke - self-test.sh offline smoke; restore/poll-once use shared config - Docs: Forgejo table, watcher.env, OPERATIONS troubleshooting
62 lines
2.6 KiB
Bash
Executable file
62 lines
2.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Single headless poll via Grok for the heavy-duty org watcher.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
# shellcheck source=lib/common.sh
|
|
source "${SCRIPT_DIR}/lib/common.sh"
|
|
|
|
mkdir -p "${LOG_DIR}"
|
|
TS="$(utc_now)"
|
|
PROMPT_FILE="${WATCHER_DIR}/.poll-prompt.txt"
|
|
|
|
case "${FORGE_BACKEND}" in
|
|
github)
|
|
DISCOVERY_HINT="gh search prs/issues --owner ${ORG} (review-requested=@me / assignee=@me)"
|
|
POST_HINT="Prefer gh pr review / gh issue comment"
|
|
BACKEND_LABEL="GitHub"
|
|
;;
|
|
forgejo)
|
|
DISCOVERY_HINT="bash ${WATCHER_DIR}/scripts/discover.sh # FORGE_BACKEND=forgejo"
|
|
POST_HINT="Prefer stoke pr review / stoke pr comment (Forgejo at ${FORGEJO_URL})"
|
|
BACKEND_LABEL="Forgejo"
|
|
;;
|
|
*)
|
|
echo "error: unknown FORGE_BACKEND=${FORGE_BACKEND}" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
cat > "${PROMPT_FILE}" <<EOF
|
|
Execute ONE full poll cycle for the heavy-duty org ${BACKEND_LABEL} watcher.
|
|
|
|
1. Read ${WATCHER_DIR}/POLL_INSTRUCTIONS.md and ${WATCHER_DIR}/state.json
|
|
2. Bot: ${BOT_LOGIN}. Scope: ALL repos under org ${ORG} (not a single repo). Backend: ${FORGE_BACKEND}.
|
|
3. Discover open Issues/PRs where bot is assignee OR review-requested:
|
|
${DISCOVERY_HINT}
|
|
Or run: FORGE_BACKEND=${FORGE_BACKEND} bash ${WATCHER_DIR}/scripts/discover.sh
|
|
4. For each match: read ALL comments/reviews/inline threads/diff/checks first; never repeat prior ${BOT_LOGIN} comments.
|
|
5. Comment/review only if first assignment, new commits (head SHA change vs state), new human comments needing reply, material CI change, or explicit re-request. Else silent.
|
|
6. Style: clear Verdict (Approve/Comment/Request changes) or Status (Aligned/Feedback/Need info). Specific, non-redundant, actionable. Blockers vs nits. ${POST_HINT}. Keep reviewing across updates until you fully agree (then Approve).
|
|
7. Never merge/close/reassign/drive-by on unassigned items.
|
|
8. Update ${WATCHER_DIR}/state.json (keys like ${ORG}/repo#pr:N) + append one line to ${WATCHER_DIR}/logs/poll.log
|
|
9. Brief report only. If zero assignments, log and exit.
|
|
EOF
|
|
|
|
watcher_log "${LOG_DIR}/poll.log" "poll-once.sh starting headless grok (org:${ORG} backend:${FORGE_BACKEND})"
|
|
|
|
if ! command -v grok >/dev/null 2>&1; then
|
|
watcher_log "${LOG_DIR}/poll.log" "poll-once.sh failed: grok CLI not found"
|
|
echo "error: grok CLI not found on PATH" >&2
|
|
exit 127
|
|
fi
|
|
|
|
if grok --always-approve --cwd "${HOME}" --max-turns 80 \
|
|
--single "$(cat "${PROMPT_FILE}")" \
|
|
>> "${LOG_DIR}/poll-headless.log" 2>&1; then
|
|
watcher_log "${LOG_DIR}/poll.log" "poll-once.sh finished ok"
|
|
else
|
|
rc=$?
|
|
watcher_log "${LOG_DIR}/poll.log" "poll-once.sh failed rc=${rc}"
|
|
exit "${rc}"
|
|
fi
|