Skip to content

ci(1979): call the board-aware stale sweep instead of copying actions/stale - #131

Merged
LukasWodka merged 2 commits into
developfrom
ci/1979-stale-backlog-caller
Aug 22, 2026
Merged

ci(1979): call the board-aware stale sweep instead of copying actions/stale#131
LukasWodka merged 2 commits into
developfrom
ci/1979-stale-backlog-caller

Conversation

@LukasWodka

@LukasWodkaLukasWodka commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Part of the backend#1979 wave. backend#1680 closes on this landing.

What changes

.github/workflows/stale-backlog.yml — a byte-identical copy of an actions/stale
config carried in 16 repos — becomes a thin caller of the reusable that .github#288
landed, following the -caller.yml convention already used by fr-gate-caller.yml,
code-quality-caller.yml and fr-pass-comment-caller.yml.

jobs:
stale:
uses: tracebloc/.github/.github/workflows/stale-backlog.yml@mainsecrets: inherit

Why it is not just deduplication

The copy called actions/stale, which is column-blind: it can see labels and
dates, not the board. So it would close a North Stars epic, or anything already in
the pipeline, on the same 6-week/8-week timer as a forgotten Backlog item — the
defect behind backend#1597 item 1.

Board awareness needs a script, and a script cannot be maintained as sixteen
byte-identical copies. The reusable's eligibility is exactly Backlog, and it
fails toward skipping, because the destructive direction here is closing.

No inputs passed, on purpose

Every input the callee declares is defaulted (project-number: 2, dry-run: false,
strict: false, script-ref: main). A caller may only pass inputs the @main
callee declares — passing one it lacks kills the run at startup_failure, which is
exactly why the callee had to reach main before any caller could be armed.

permissions: contents: read only: the sweep's writes go through the App token
minted inside the reusable, and asking for more here than the callee needs fails the
run at startup with no jobs.

DRAFT — and what un-drafts it

This cannot merge yet, and draft is the mechanical guarantee of that. Callers pin
@main, and .github/main still carries the old 1174-byte copy — the reusable is on
.github/develop, 4 commits ahead. Merging this first would leave a scheduled
workflow that fails at startup every Monday.

Order, per the note carried in repo-inventory.yml:

  1. .github promotes develop → staging → main, carrying the reusable
  2. these 16 callers merge
  3. one final .github PR adds .github's own caller and flips all 17 inventory
    entries from exempt to required

Step 3 is last for a stated reason: flipping to required before a repo's caller
lands would redden the org audit for every repo still waiting — the drift window made
to look permanent. And .github's caller ships with the flip rather than before it,
because exempt plus a caller on the audited branch is itself a finding
(caller-drift.py:2260).

🤖 Generated with Claude Code


Note

Medium Risk
Changes automated issue-closing behavior (destructive if eligibility is wrong) and depends on the reusable already being on @main. Low blast radius otherwise: CI-only, no app code.

Overview
Replaces the local Monday actions/stale copy with a thin caller of tracebloc/.github’s stale-backlog.yml@main.

The sweep is now board-aware: only Backlog cards are eligible, so North Stars and in-pipeline issues are no longer auto-closed on inactivity. No workflow inputs are passed (callee defaults), and this workflow only grants contents: read because writes use the App token minted inside the reusable.

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

@LukasWodkaLukasWodka self-assigned this Aug 20, 2026
@LukasWodka
LukasWodka marked this pull request as ready for review August 22, 2026 15:40

@saadqbalsaadqbal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, careful PR 👍 — checked it properly rather than waving the fan-out through, and it holds up.

What I verified against the source rather than the description:

  • The callee exists on main with exactly the four inputs the comment claims, all defaulted (project-number: 2, dry-run: false, strict: false, script-ref: main), so passing nothing is right and can't startup_failure.
  • The callee declares permissions: contents: read — so contents: read here is sufficient and not exceeded. Its writes really do go through the App token minted in the job, scoped permission-issues: write + permission-organization-projects: read and narrowed with repositories: to the calling repo.
  • No behaviour is lost against the actions/stale block being deleted: stale-backlog.py carries EXEMPT_LABELS = {"keep-open", "blocked"} and DAYS_TO_STALE = 42 / DAYS_TO_CLOSE = 14 — the same labels and the same 6-weeks-then-2 windows. And PRs stay untouched (the callee explicitly takes no pull-requests permission), which is what days-before-pr-stale: -1 was doing.
  • Eligibility genuinely narrows rather than shifts: allow-list of exactly Backlog, archived excluded, unreadable Status skipped. Strictly fewer things can be auto-closed than before, which is the right direction for an unattended destructive sweep.
  • secrets: inherit resolves here — this repo already references the App secrets on its default branch, so the token mint isn't going to fail for want of a secret.

And the fan-out itself: I diffed the added caller across all four repos (start-training#66, e2e-test-agent#182, docs#131, claude-skills#31) and they are byte-identical, which is the whole point of the thin-caller shape.

@saqlainsyed007saqlainsyed007 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verified at head. backend#1979 dedup wave: adds stale-backlog-caller.yml — a thin caller of tracebloc/.github's reusable stale-backlog.yml@main (secrets: inherit, permissions: contents: read, Monday cron + workflow_dispatch) — and deletes the local actions/stale copy. Diff is exactly those two files, nothing else; no inputs passed (callee defaults), eligibility is now board-aware (only Backlog), and perms correctly drop to contents: read since writes go through the App token minted inside the reusable. CI green, no open review threads. Approving.

@LukasWodka
LukasWodka merged commit 5b2e912 into developAug 22, 2026
19 checks passed
@LukasWodka
LukasWodka deleted the ci/1979-stale-backlog-caller branch August 22, 2026 18:31
@LukasWodka

Copy link
Copy Markdown
ContributorAuthor

/fr-pass

Sign up for freeto 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.

3 participants

@LukasWodka@saadqbal@saqlainsyed007