From 604d1f13caef96b0d3a0a9f1d9e20b62cdefc643 Mon Sep 17 00:00:00 2001 From: openhands Date: Sun, 22 Mar 2026 13:41:57 +0000 Subject: [PATCH] fix: feat: dev-poll checks priority-labeled issues before plain backlog (#555) Add two-tier backlog pickup in dev-poll.sh: 1. in-progress issues (existing) 2. priority + backlog issues (FIFO within tier) 3. plain backlog issues (FIFO within tier) The priority label coexists with backlog (not a replacement). ensure_priority_label() auto-creates the label if missing. Co-Authored-By: Claude Opus 4.6 (1M context) --- AGENTS.md | 1 + dev/dev-poll.sh | 27 ++++++++++++++++++++++++--- lib/ci-helpers.sh | 21 +++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 0bf0231..1060c37 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -93,6 +93,7 @@ Issues flow: `backlog` → `in-progress` → PR → CI → review → merge → | Label | Meaning | Set by | |---|---|---| | `backlog` | Issue is queued for implementation. Dev-poll picks the first ready one. | Planner, gardener, humans | +| `priority` | Queue tier above plain backlog. Issues with both `priority` and `backlog` are picked before plain `backlog` issues. FIFO within each tier. | Planner, humans | | `in-progress` | Dev-agent is actively working on this issue. Only one issue per project is in-progress at a time. | dev-agent.sh (claims issue) | | `blocked` | Issue is stuck — agent session failed, crashed, timed out, or CI exhausted. Diagnostic comment on the issue has details. Also used for unmet dependencies. | dev-agent.sh, action-agent.sh, dev-poll.sh (on failure) | | `tech-debt` | Pre-existing issue flagged by AI reviewer, not introduced by a PR. | review-pr.sh (auto-created follow-ups) | diff --git a/dev/dev-poll.sh b/dev/dev-poll.sh index bdf698a..b8509c8 100755 --- a/dev/dev-poll.sh +++ b/dev/dev-poll.sh @@ -7,7 +7,8 @@ # # Priority: # 1. Orphaned "in-progress" issues (agent died or PR needs attention) -# 2. Ready "backlog" issues (all deps merged) +# 2. Ready "priority" + "backlog" issues (FIFO within tier) +# 3. Ready "backlog" issues without "priority" (FIFO within tier) # # Usage: # cron every 10min @@ -590,18 +591,38 @@ done # ============================================================================= # PRIORITY 2: find ready backlog issues (pull system) +# +# Two-tier pickup: priority+backlog issues first (FIFO), then plain backlog +# issues (FIFO). The "priority" label is added alongside "backlog", not instead. # ============================================================================= log "scanning backlog for ready issues" -BACKLOG_JSON=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \ + +# Ensure the priority label exists on this repo +ensure_priority_label >/dev/null 2>&1 || true + +# Tier 1: issues with both "priority" and "backlog" labels +PRIORITY_BACKLOG_JSON=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \ + "${API}/issues?state=open&labels=priority,backlog&limit=20&type=issues&sort=oldest") || true +PRIORITY_BACKLOG_JSON="${PRIORITY_BACKLOG_JSON:-[]}" + +# Tier 2: all "backlog" issues (includes priority ones — deduplicated below) +ALL_BACKLOG_JSON=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \ "${API}/issues?state=open&labels=backlog&limit=20&type=issues&sort=oldest") +# Combine: priority issues first, then remaining backlog issues (deduped) +BACKLOG_JSON=$(jq -n \ + --argjson pri "$PRIORITY_BACKLOG_JSON" \ + --argjson all "$ALL_BACKLOG_JSON" \ + '($pri | map(.number)) as $pnums | $pri + [$all[] | select(.number as $n | $pnums | map(. == $n) | any | not)]') + BACKLOG_COUNT=$(echo "$BACKLOG_JSON" | jq 'length') if [ "$BACKLOG_COUNT" -eq 0 ]; then log "no backlog issues" exit 0 fi -log "found ${BACKLOG_COUNT} backlog issues" +PRIORITY_COUNT=$(echo "$PRIORITY_BACKLOG_JSON" | jq 'length') +log "found ${BACKLOG_COUNT} backlog issues (${PRIORITY_COUNT} priority)" # Check each for readiness READY_ISSUE="" diff --git a/lib/ci-helpers.sh b/lib/ci-helpers.sh index e24dfc8..384826c 100644 --- a/lib/ci-helpers.sh +++ b/lib/ci-helpers.sh @@ -27,6 +27,27 @@ ensure_blocked_label_id() { printf '%s' "$_BLOCKED_LABEL_ID" } +# ensure_priority_label — look up (or create) the "priority" label, print its ID. +# Caches the result in _PRIORITY_LABEL_ID to avoid repeated API calls. +# Requires: CODEBERG_TOKEN, CODEBERG_API (from env.sh), codeberg_api() +ensure_priority_label() { + if [ -n "${_PRIORITY_LABEL_ID:-}" ]; then + printf '%s' "$_PRIORITY_LABEL_ID" + return 0 + fi + _PRIORITY_LABEL_ID=$(codeberg_api GET "/labels" 2>/dev/null \ + | jq -r '.[] | select(.name == "priority") | .id' 2>/dev/null || true) + if [ -z "$_PRIORITY_LABEL_ID" ]; then + _PRIORITY_LABEL_ID=$(curl -sf -X POST \ + -H "Authorization: token ${CODEBERG_TOKEN}" \ + -H "Content-Type: application/json" \ + "${CODEBERG_API}/labels" \ + -d '{"name":"priority","color":"#f59e0b"}' 2>/dev/null \ + | jq -r '.id // empty' 2>/dev/null || true) + fi + printf '%s' "$_PRIORITY_LABEL_ID" +} + # diff_has_code_files — check if file list (stdin, one per line) contains code files # Non-code paths: docs/*, formulas/*, evidence/*, *.md # Returns 0 if any code file found, 1 if all files are non-code.