Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 29 additions & 11 deletions .github/workflows/impl-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -368,17 +368,35 @@ jobs:
# Create labels if they don't exist
gh label create "impl:${LIBRARY}:done" --color "0e8a16" --description "${LIBRARY} implementation merged" 2>/dev/null || true

# Remove trigger, pending, and any stale failed label from earlier attempts,
# then add done. The :failed label is added by impl-generate.yml when an
# attempt errors out (e.g. environment setup failure); a later successful
# retry merges via this workflow but historically didn't clean up :failed,
# leaving the issue with both :done and :failed for the same library.
# Single API call (comma-separated) — matches the pattern in
# impl-generate.yml and avoids the partial-update window of separate edits.
gh issue edit "$ISSUE" \
--remove-label "generate:${LIBRARY},impl:${LIBRARY}:pending,impl:${LIBRARY}:failed" \
--add-label "impl:${LIBRARY}:done" 2>/dev/null || \
gh issue edit "$ISSUE" --add-label "impl:${LIBRARY}:done"
# Add done first — it is the completion signal everything else reads
# (the 15/15 auto-close below, monitor_spec.sh, the label sync).
gh issue edit "$ISSUE" --add-label "impl:${LIBRARY}:done"

# Then clear every label that says this library is still pending or
# broken: the generate trigger, the pending marker, the :failed label
# impl-generate.yml sets at its retry cap, and the watchdog's
# per-library retry marker (`watchdog:retried-<lib>`), which would
# otherwise keep reporting the pair as "already retried — needs manual
# attention" on every scan.
#
# Only the labels the issue actually carries are removed, one
# `gh issue edit` each: `gh` resolves every name against the REPO's
# label list before it edits, and a single unknown name
# (`impl:<lib>:pending` is only created on demand, `generate:<lib>`
# may never have existed) fails a whole comma-separated call. The
# previous single-call form did just that, and its fallback only
# added :done — so issues #3343 and #3650 kept `impl:<lib>:failed`
# next to `impl:<lib>:done` after the rescued implementations merged
# (2026-09-02). A removal that fails anyway is reported, not hidden:
# the stale label is exactly the state this step exists to clear.
PRESENT=$(gh issue view "$ISSUE" --json labels -q '.labels[].name' 2>/dev/null || echo "")
for stale in "generate:${LIBRARY}" "impl:${LIBRARY}:pending" \
"impl:${LIBRARY}:failed" "watchdog:retried-${LIBRARY}"; do
if echo "$PRESENT" | grep -qx "$stale"; then
Comment thread
MarkusNeusinger marked this conversation as resolved.
gh issue edit "$ISSUE" --remove-label "$stale" \
|| echo "::warning::Could not remove stale label '$stale' from issue #$ISSUE"
fi
done

- name: Post success to issue
if: steps.check.outputs.should_run == 'true' && steps.issue.outputs.number != ''
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ aggregate instead: an italic *Catalog* line at the end of the version section an

### Fixed

- **A merged implementation now clears its `impl:<lib>:failed` label and the watchdog's
retry marker** — impl-merge removed the stale labels in one comma-separated
`gh issue edit`, and `gh` rejects the whole call when any name in the list is not a
repository label (`impl:<lib>:pending` only exists on demand), so the fallback added
`impl:<lib>:done` and left `impl:<lib>:failed` in place. Issues #3343 and #3650 ended
the 2026-09-02 outage rescue with both labels for the same libraries, and every
watchdog scan since reported those pairs as "already retried — needs manual
attention". The labels are now removed one at a time, each call tolerated, and
`watchdog:retried-<lib>` goes with them. (#11197)
- **The watchdog now rescues a repair that crashed after a rejection** — a PR carrying
`ai-rejected` and `ai-attempt-N` is the state impl-review leaves behind when it
dispatches a repair that then dies (its crash-retry exhausted). Case 2 excluded
Expand Down
Loading