From 067d703279afaaf8246b74767fef197638e28521 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Wed, 2 Sep 2026 18:16:51 +0200 Subject: [PATCH 1/3] fix(impl-merge): remove stale failed labels one at a time so a merge really clears them `gh issue edit --remove-label a,b,c` resolves every name against the repository's labels before it edits and fails the whole call when one is unknown; `impl::pending` only exists on demand, so the comma-separated cleanup failed and its fallback added `impl::done` while leaving `impl::failed` in place (issues #3343 and #3650 after the 2026-09-02 rescue). Remove the labels individually, each call tolerated, and take the watchdog's `watchdog:retried-` marker with them. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01SrKzcwZBnref1sWYtdXynu --- .github/workflows/impl-merge.yml | 34 +++++++++++++++++++++----------- CHANGELOG.md | 9 +++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/.github/workflows/impl-merge.yml b/.github/workflows/impl-merge.yml index 0ff40d12c01..0a75be66adf 100644 --- a/.github/workflows/impl-merge.yml +++ b/.github/workflows/impl-merge.yml @@ -368,17 +368,29 @@ 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-`), which would + # otherwise keep reporting the pair as "already retried — needs manual + # attention" on every scan. + # + # One `gh issue edit` per label, each tolerated: `gh` resolves label + # names against the REPO's label list before it edits, and a single + # unknown name (`impl::pending` is only created on demand and + # `generate:` may never have existed for this issue) fails the + # 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::failed` next to `impl::done` after the + # rescued implementations merged (2026-09-02). + for stale in "generate:${LIBRARY}" "impl:${LIBRARY}:pending" \ + "impl:${LIBRARY}:failed" "watchdog:retried-${LIBRARY}"; do + gh issue edit "$ISSUE" --remove-label "$stale" 2>/dev/null || true + done - name: Post success to issue if: steps.check.outputs.should_run == 'true' && steps.issue.outputs.number != '' diff --git a/CHANGELOG.md b/CHANGELOG.md index ed8a6ead16f..c0d1207d78b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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::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::pending` only exists on demand), so the fallback added + `impl::done` and left `impl::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-` goes with them. - **The API image installs `libraqm0`, which is what actually restores text shaping — and unblocks a deploy pipeline that has been red since 2026-08-30** — #10813 added a build-time assertion on `features.check('raqm')` on the understanding that the locked From 7f2ffc4210f4b2604769b875bf9b0b001880f466 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Wed, 2 Sep 2026 18:18:40 +0200 Subject: [PATCH 2/3] docs(changelog): add PR reference for #11197 Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01SrKzcwZBnref1sWYtdXynu --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d1207d78b..065e827111a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,7 @@ aggregate instead: an italic *Catalog* line at the end of the version section an 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-` goes with them. + `watchdog:retried-` goes with them. (#11197) - **The API image installs `libraqm0`, which is what actually restores text shaping — and unblocks a deploy pipeline that has been red since 2026-08-30** — #10813 added a build-time assertion on `features.check('raqm')` on the understanding that the locked From 31c92079177451331036aaeb667b77835d3355b2 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Wed, 2 Sep 2026 18:23:33 +0200 Subject: [PATCH 3/3] fix(impl-merge): remove only the stale labels the issue carries, report failures Review feedback: silently tolerating every removal would hide a transient API failure and leave the stale label in place, which is the state this step exists to clear. Read the issue's labels once, remove only the stale ones that are present, and emit a warning when a removal fails. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01SrKzcwZBnref1sWYtdXynu --- .github/workflows/impl-merge.yml | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/impl-merge.yml b/.github/workflows/impl-merge.yml index 0a75be66adf..006b8a13ca0 100644 --- a/.github/workflows/impl-merge.yml +++ b/.github/workflows/impl-merge.yml @@ -379,17 +379,23 @@ jobs: # otherwise keep reporting the pair as "already retried — needs manual # attention" on every scan. # - # One `gh issue edit` per label, each tolerated: `gh` resolves label - # names against the REPO's label list before it edits, and a single - # unknown name (`impl::pending` is only created on demand and - # `generate:` may never have existed for this issue) fails the - # 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::failed` next to `impl::done` after the - # rescued implementations merged (2026-09-02). + # 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::pending` is only created on demand, `generate:` + # 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::failed` + # next to `impl::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 - gh issue edit "$ISSUE" --remove-label "$stale" 2>/dev/null || true + if echo "$PRESENT" | grep -qx "$stale"; then + 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