Skip to content

fix(kanban): a failed sibling-merge label write must not abort the sweep - #254

Merged
LukasWodka merged 3 commits into
developfrom
fix/1598-sibling-label-abort
Aug 14, 2026
Merged

fix(kanban): a failed sibling-merge label write must not abort the sweep#254
LukasWodka merged 3 commits into
developfrom
fix/1598-sibling-label-abort

Conversation

@LukasWodka

@LukasWodka LukasWodka commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Closes tracebloc/backend#1598, under epic backend#1680.

The bug

The sibling-merge label writes ran bare under set -euo pipefail. The comment called this "hard-fails per the PROJECTS_KANBAN_TOKEN write rule" — but a hard fail here doesn't fail one item, it aborts the whole step mid-loop:

  • every item after the failure goes unprocessed
  • added.tsv is left truncated at the failure point
  • everything downstream still reads it as the complete record

A 403 on this write is also the likeliest failure in the step: PROJECTS_KANBAN_TOKEN is one user PAT shared by CI, the conformance gate, the weekly cron and any local script, all on one 5,000/hr budget.

The fix

Record the failure in add_fail instead. The existing end-of-step check already turns a non-zero add_fail into a red run, so the rule is kept — the run still fails. The sweep just finishes first, and the record stays complete.

Fail closed, finish the work. The label-create call is also made non-fatal with an explicit notice, since a missing label is reported by the write that follows it.

Reproduced, both ways

A gh stub that 403s the label POST, three items in the loop:

exit added.tsv rows
before 1 0 — aborted on item 1, record empty
after 1 3 — all swept, ::error::3 item(s) failed emitted

Both fail closed. Only the completeness differs — which is the whole bug.

Ordering is unchanged: the label is still written after the status, so a label failure can never cost a card its column (.github#157's lesson).


Note

Low Risk
Workflow-only error handling in the kanban reconcile job; no app runtime, auth, or data-path changes.

Overview
Membership sweep in kanban-reconcile.yml no longer lets a failed sibling-merge label API call exit the loop under set -euo pipefail. Those writes are counted in add_fail instead, so the run still fails closed at the end of the step but finishes every missing item and keeps added.tsv complete.

Label create and apply are wrapped so failures emit [WARN] with captured gh stderr (and a status_note when Status was set). The final ::error:: message now explicitly includes sibling-merge label write failures alongside add/Status failures.

Reviewed by Cursor Bugbot for commit 5a9995f. Bugbot is set up for automated code reviews on this repo. Configure here.

The label writes ran bare under `set -euo pipefail`, described in the comment
as "hard-fails per the PROJECTS_KANBAN_TOKEN write rule". But a hard fail here
does not fail ONE ITEM -- it aborts the whole step mid-loop. Every item after
it goes unprocessed, and `added.tsv` is left truncated at the failure point
while everything downstream reads it as the complete record.

A 403 on this write is also the likeliest failure in the step:
PROJECTS_KANBAN_TOKEN is one user PAT shared by CI, the conformance gate, the
weekly cron and any local script, on one 5,000/hr budget.

The failure is now recorded in `add_fail`, which the existing end-of-step check
already turns into a red run. The rule is kept -- the run still fails -- but the
sweep finishes first and the record stays complete. Fail closed, finish the work.

Reproduced with a `gh` stub that 403s the label POST, three items in the loop:

  before   exit=1   added.tsv rows=0   (aborted on item 1, record empty)
  after    exit=1   added.tsv rows=3   (all swept, ::error:: emitted)

Both fail closed; only the completeness differs.

Closes #1598.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@LukasWodka LukasWodka self-assigned this Aug 14, 2026
Comment thread .github/workflows/kanban-reconcile.yml
Comment thread .github/workflows/kanban-reconcile.yml Outdated
…e wrong cause

Both Bugbot findings on #254.

MEDIUM - the end-of-step ::error:: attributed every non-zero add_fail to
"could not be added, or added without a Status". This change added a THIRD
cause (a failed sibling-merge label write), so a label 403 was reported as a
card with no Status - sending the operator to look at a column that is fine.
The verdict now names all three and points at the [FAIL]/[WARN] lines for which.

LOW - the label POST discarded stdout AND stderr, so the warning carried no
HTTP status and no body. A 403 is the exact failure this change exists to
survive, and "the label write failed" cannot distinguish a rate limit from a
missing scope from a deleted repo. stderr is now captured into the warning;
stdout still goes to /dev/null because it is the created-label JSON.

Verified the redirect order captures stderr only and leaves the success path
silent:
  fail -> captured=[HTTP 403: rate limit exceeded]
  ok   -> no warning

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor Author

bugbot run

Comment thread .github/workflows/kanban-reconcile.yml Outdated
The sibling-merge label [WARN] hardcoded "status set", but it runs after
the set_status if/else and so also fires when the Status write failed. A
403 can fail both, and the two [WARN] lines then contradicted each other
-- "added ... but Status set failed" vs "status set, but the label write
failed" -- the exact at-least-once incident this PR is built to survive.

Carry the set_status result into status_note and have the label WARN
reference it: "status set, but ..." on success, "Status set failed,
and ..." on failure. Still non-fatal: counted in add_fail, never aborts
the sweep.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 5a9995f. Configure here.

@shujaatTracebloc shujaatTracebloc left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve (backend#1598). The sibling-merge label writes ran bare under set -euo pipefail, so a 403 (the single most likely failure — one shared PROJECTS_KANBAN_TOKEN PAT on a 5000/hr budget) aborted the WHOLE sweep mid-loop, leaving every later item unprocessed and added.tsv truncated but still read as complete. Now the failure is counted into add_fail (run still goes red at end — rule kept) so the sweep finishes and the record stays whole. Keeps the captured stderr so an operator can tell a rate-limit from a missing scope. Label write stays AFTER the status write (#157 ordering lesson preserved). CI green, Bugbot resolved.

@LukasWodka
LukasWodka merged commit 4562b76 into develop Aug 14, 2026
10 checks passed
@LukasWodka
LukasWodka deleted the fix/1598-sibling-label-abort branch August 14, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants