Repository navigation
ci: stale-PR automation — bestaxbot closer + generic stale (#275) - #279
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughAdds scheduled and manually triggered workflows that close inactive bestaxbot or Claude-assisted PRs after 90 days and manage general pull-request staleness after 30 days plus a 14-day closure period. Documentation describes these timings and the ChangesStale pull request automation
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Scheduler
participant StaleWorkflow
participant GitHub
Scheduler->>StaleWorkflow: trigger scheduled or manual run
StaleWorkflow->>GitHub: identify inactive pull requests
StaleWorkflow->>GitHub: apply stale labels or close eligible PRs
Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Preview DeploymentPreview URL: https://7d20799c.bestax.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/close-stale-bestaxbot-prs.yml:
- Around line 12-17: Add a workflow-level concurrency group to the closer
workflow identified by its `on` schedule and `workflow_dispatch` triggers, using
a stable group name and cancel-in-progress behavior that prevents overlapping
runs, including manual dispatches. If serialization with the loop watchdog is
required, configure both workflows to use the same concurrency group naming
scheme.
- Around line 47-54: Remove the `|| true` from the `gh pr edit` cleanup command
in the stale PR-closing workflow. Ensure label removal failures stop execution
so `gh pr close` is not called, keeping the PR open when cleanup encounters
authentication, API, or network errors.
- Around line 39-43: Increase the result limit for the gh pr list invocation in
the stale PR processing pipeline by adding --limit 1000 (or another sufficiently
high bound), ensuring all stale bestaxbot PRs are considered rather than only
the default 30.
In @.github/workflows/stale.yml:
- Around line 39-42: Update the stale workflow configuration to exempt
bestaxbot-authored PRs from actions/stale, either by adding the supported
bestaxbot-specific exemption or by ensuring the bot workflow automatically
applies the neverstale label before this sweep. Preserve the existing 30-day
stale and 14-day close settings for other PRs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 2a000ce6-0135-4fa3-a4f6-fc72b4dfc62b
📒 Files selected for processing (4)
.github/workflows/close-stale-bestaxbot-prs.yml.github/workflows/stale.ymlCLAUDE.mddocs/docs/guides/getting-started/ai-development.md
| on: | ||
| schedule: | ||
| # 03:41 UTC daily — deliberately offset from the loop watchdog's | ||
| # `23 */2 * * *` so the closer never races a sweep re-dispatch. | ||
| - cron: '41 3 * * *' | ||
| workflow_dispatch: |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## File list\n'
git ls-files '.github/workflows/*' | sed 's#^`#-` #'
printf '\n## Target workflow\n'
wc -l .github/workflows/close-stale-bestaxbot-prs.yml
cat -n .github/workflows/close-stale-bestaxbot-prs.yml
printf '\n## Search for concurrency and watchdog references\n'
rg -n "concurrency|23 \\*/2 \\* \\* \\*|close-stale|bestaxbot|watchdog|re-dispatch" .github/workflowsRepository: allxsmith/bestax
Length of output: 9279
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## claude-pr-loop relevant sections\n'
sed -n '1,120p' .github/workflows/claude-pr-loop.yml
printf '\n## on-slop relevant sections\n'
sed -n '1,90p' .github/workflows/on-slop.ymlRepository: allxsmith/bestax
Length of output: 8538
Add a concurrency group to the closer workflow. The cron offset doesn’t prevent overlap with manual dispatches or another in-flight run, so duplicate comments and competing label/close operations can still happen. If this needs to serialize with the watchdog too, use the same group naming scheme there.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/close-stale-bestaxbot-prs.yml around lines 12 - 17, Add a
workflow-level concurrency group to the closer workflow identified by its `on`
schedule and `workflow_dispatch` triggers, using a stable group name and
cancel-in-progress behavior that prevents overlapping runs, including manual
dispatches. If serialization with the loop watchdog is required, configure both
workflows to use the same concurrency group naming scheme.
Preview DeploymentPreview URL: https://6ca048c6.bestax.pages.dev |
|
@claude perform deep review Generated by Claude Code |
Two zero-Claude workflows mirroring oven-sh/bun: a daily closer for bestaxbot PRs inactive 90+ days (strips loop labels before closing, per the on-slop.yml pattern), and actions/stale (pinned to v9.1.0 by commit SHA) marking PRs stale at 30 days and closing 14 days later, with a neverstale exemption label. Issues are deliberately excluded from stale processing. Docs: label table + CLAUDE.md note. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pohc8xLkdx4gwXkW3xd7up
The neverstale label documents "exempts a PR from stale automation" — that must include the 90-day bot sweep, not just the generic stale.yml layer. Fetch labels in gh pr list and filter them out in jq. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pohc8xLkdx4gwXkW3xd7up
21f4d75 to
f49942a
Compare
Preview DeploymentPreview URL: https://ba4a37ba.bestax.pages.dev |
| days-before-pr-stale: 30 | ||
| days-before-pr-close: 14 | ||
| stale-pr-label: stale | ||
| exempt-pr-labels: neverstale |
There was a problem hiding this comment.
Generic stale layer preempts the 90-day bestaxbot closer — 🟠 Major · Correctness
What: This workflow processes all open PRs (no exempt-authors), and bestaxbot PRs are not automatically given neverstale. So a bestaxbot PR that goes inactive is marked stale at 30 days and closed at 44 days (30 + 14). The dedicated close-stale-bestaxbot-prs.yml only fires at 90 days — 46 days after this workflow has already closed the PR.
Why it matters: The two files encode conflicting intents for the same PRs (44-day vs. 90-day leash), and the stricter one always wins. Consequences:
close-stale-bestaxbot-prs.ymlis effectively dead — it can never reach a bot PR that has been inactive for 90 continuous days, because such a PR was closed at day 44.- The documented behavior is false:
CLAUDE.mdandai-development.mdnow claim "bestaxbot PRs close after 90 days of inactivity," but they actually close at 44. The bot's 90-day close comment (and its loop-label stripping) never runs.
The dedicated closer strongly implies the intent was to give bot PRs a longer, gentler leash (the loop churns them). If so, this workflow must exclude bestaxbot as an author so the 90-day closer becomes the sole authority for bot PRs:
| days-before-pr-stale: 30 | |
| days-before-pr-close: 14 | |
| stale-pr-label: stale | |
| exempt-pr-labels: neverstale | |
| days-before-pr-stale: 30 | |
| days-before-pr-close: 14 | |
| stale-pr-label: stale | |
| exempt-pr-labels: neverstale | |
| # bestaxbot-authored PRs are handled by close-stale-bestaxbot-prs.yml | |
| # (90-day leash); excluding them here prevents this 44-day layer from | |
| # closing them first and making that workflow unreachable. | |
| exempt-authors: bestaxbot |
Timeline of an inactive bestaxbot PR under the current config
gantt
dateFormat X
axisFormat %s
title Inactive bestaxbot PR — days of inactivity
section stale.yml (all PRs)
marked `stale` :milestone, 30, 0d
CLOSED here :crit, milestone, 44, 0d
section close-stale-bestaxbot-prs.yml
intended close (never reached) :done, milestone, 90, 0d
PR is gone at day 44; the 90-day bot closer never gets a turn.
If instead the intent is genuinely 44 days for everyone including the bot, then close-stale-bestaxbot-prs.yml and the "90 days" wording in CLAUDE.md/ai-development.md should be removed to avoid the contradiction.
There was a problem hiding this comment.
Deep review — 1 finding
| # | Severity | Area | Finding | Location |
|---|---|---|---|---|
| 1 | 🟠 Major | Correctness | Generic 30/14-day stale closer preempts the 90-day bestaxbot closer, making it unreachable and contradicting the documented "90 days" behavior | .github/workflows/stale.yml:39-42 |
Overall: The change is well-structured and the security hardening is exemplary — permissions: {} at workflow level with narrow job grants, a SHA-pinned actions/stale, zero Claude/token spend, and deliberately offset crons. The one real issue is a layering conflict: stale.yml applies to all PRs with no exempt-authors, so bestaxbot PRs close at day 44, which means the dedicated 90-day close-stale-bestaxbot-prs.yml can never fire and the "bot PRs close after 90 days" wording in CLAUDE.md/ai-development.md is inaccurate. A human should decide the intended bot leash (44 vs. 90 days) and either add exempt-authors: bestaxbot to stale.yml or drop the redundant 90-day workflow + docs. Everything else — the neverstale exemption on both layers, loop-label stripping before close, docs table rows — is correct.
🏄 Clean set on the security barrels, dude — locked-down perms and pinned actions, no worries there. Only snag is two closers paddling for the same wave: the 30-day one drops in and closes out the 90-day bot ride before it ever stands up. Sort out who owns that break and it is all smooth cruising.
…90-day closer (#275) Addresses the deep-review Major on PR #279: the generic stale.yml closed every PR at day 44, so the dedicated 90-day bestaxbot closer could never fire and the documented 90-day bot leash was inaccurate. actions/stale has no author exemption, so the fix keys off the claude-assisted label that auto-label-claude-prs.yml (PR #276) applies: - stale.yml adds claude-assisted to exempt-pr-labels, so AI-assisted PRs skip the 30/14 sweep. - close-stale-bestaxbot-prs.yml now sweeps the union of author:bestaxbot and label:claude-assisted (deduped), so labeled human-authored Claude-assisted PRs don't escape both layers, and pre-labeler bot PRs are still covered by the author query. - CLAUDE.md and the docs label table describe the two-layer split. Until #276 merges and labels new bot PRs, unlabeled bestaxbot PRs remain under the generic 30/14 sweep — an acceptable transition state. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142miDJt2AX9QUw5fNJt2xu
Preview DeploymentPreview URL: https://817d0932.bestax.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/close-stale-bestaxbot-prs.yml:
- Around line 61-62: Update the jq filter in the stale PR workflow to use an
inclusive cutoff by changing the updatedAt comparison from < $cutoff to <=
$cutoff, preserving the existing unique_by, neverstale exclusion, and number
selection logic.
- Around line 8-14: Ensure unlabeled PRs authored by bestaxbot are exempted from
the generic stale workflow before its 30/14-day sweep, either by updating
stale.yml’s exemption logic to include author:bestaxbot or by reliably applying
the claude-assisted exemption label to those PRs before the sweep. Preserve the
dedicated 90-day handling in close-stale-bestaxbot-prs.yml.
- Around line 61-65: Revalidate each candidate PR immediately before side
effects in the stale-PR processing loop: use the GitHub CLI to fetch its current
updatedAt timestamp and labels, then skip it if it is no longer older than
CUTOFF or has the neverstale label. Only comment on and close the PR after this
fresh eligibility check, updating the existing jq/while-loop logic accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d6fe00dd-09d4-4733-abaa-8e3a15d89c40
📒 Files selected for processing (4)
.github/workflows/close-stale-bestaxbot-prs.yml.github/workflows/stale.ymlCLAUDE.mddocs/docs/guides/getting-started/ai-development.md
✅ Files skipped from review due to trivial changes (1)
- CLAUDE.md
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/stale.yml
…lusive cutoff (#275) Addresses the three CodeRabbit findings on the previous push: - A new first step labels any open bestaxbot PR missing claude-assisted, so pre-labeler bot PRs can't be closed at day 44 by stale.yml's generic sweep — this job's 03:41 cron fires before the 04:17 sweep, and the REST call auto-creates the label like auto-label-claude-prs.yml does. - The close loop re-fetches state/updatedAt/labels per PR right before commenting/closing, skipping anything updated, neverstale-labeled, or closed since the listing snapshot; fetch failures count as ineligible. - The cutoff comparison is now inclusive (<=) to match the documented "90+ days" threshold. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142miDJt2AX9QUw5fNJt2xu
Preview DeploymentPreview URL: https://1653795b.bestax.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
.github/workflows/close-stale-bestaxbot-prs.yml (1)
108-111: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winCleanup failures are still swallowed by
|| true.
gh pr edit --remove-labelalready returns success when a label is absent, so this|| trueonly masks genuine auth/API/network failures — and the PR still closes with stale loop labels attached. Same unresolved concern as a prior review.🛠️ Proposed fix
gh pr edit "$PR" --repo "$REPO" \ --remove-label ai-loop \ --remove-label ai-loop-paused \ - --remove-label needs-human-review || true + --remove-label needs-human-review🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/close-stale-bestaxbot-prs.yml around lines 108 - 111, Remove the trailing `|| true` from the `gh pr edit` cleanup command in the stale PR workflow so authentication, API, and network failures are not swallowed; rely on `gh pr edit --remove-label` succeeding when labels are already absent and ensure cleanup failure prevents closing the PR.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/close-stale-bestaxbot-prs.yml:
- Line 57: All three gh pr list invocations in the backfill query and union
selectors omit --limit, so candidates beyond the default 30 are skipped. Update
each command to specify an appropriate sufficiently high --limit, including the
bestaxbot query and both claude-assisted selector queries.
---
Duplicate comments:
In @.github/workflows/close-stale-bestaxbot-prs.yml:
- Around line 108-111: Remove the trailing `|| true` from the `gh pr edit`
cleanup command in the stale PR workflow so authentication, API, and network
failures are not swallowed; rely on `gh pr edit --remove-label` succeeding when
labels are already absent and ensure cleanup failure prevents closing the PR.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 6d0cfaa1-b13e-4ac1-a959-109c24b7d2b4
📒 Files selected for processing (1)
.github/workflows/close-stale-bestaxbot-prs.yml
Two more CodeRabbit findings: gh pr list defaults to 30 results, which would silently skip older candidates in both the backfill and the close sweep once the repo has more than 30 matching PRs — all three calls now pass --limit 1000. And the || true on the loop-label strip masked real API/auth failures (gh already succeeds when a label is absent), letting a PR close with loop labels still attached; a genuine failure now aborts the run and the daily cron retries tomorrow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142miDJt2AX9QUw5fNJt2xu
Preview DeploymentPreview URL: https://249b0170.bestax.pages.dev |
# Conflicts: # docs/docs/guides/getting-started/ai-development.md
Preview DeploymentPreview URL: https://4bbe8599.bestax.pages.dev |
| # The sweep is the union of author:bestaxbot and label:claude-assisted — | ||
| # the label (auto-applied by auto-label-claude-prs.yml) also covers | ||
| # human-authored PRs with Claude attribution, and the author query covers | ||
| # bot PRs opened before the labeler existed. A first step backfills the | ||
| # claude-assisted label onto any unlabeled bestaxbot PR so the generic | ||
| # sweep can't close pre-labeler bot PRs at day 44: this job's 03:41 cron |
There was a problem hiding this comment.
auto-label-claude-prs.yml doesn't exist — human-authored Claude PRs are never protected — 🟠 Major · Correctness
What: Both new workflows repeatedly cite auto-label-claude-prs.yml as the source of the claude-assisted label (here, and in stale.yml:11). That workflow does not exist anywhere in the repo — the only thing that ever applies claude-assisted is the backfill step below, and it is scoped to --author bestaxbot.
Why it matters: The stated design is a union: author:bestaxbot plus label:claude-assisted so the label leg "also covers human-authored PRs with Claude attribution." In reality no human-authored PR ever receives the label, so:
stale.yml'sexempt-pr-labels: …,claude-assistednever matches a human PR → it gets marked stale at 30 days and closed at 44.- This 90-day closer's
--label claude-assistedleg only ever returns bestaxbot PRs (which the author leg already covers), so it's currently redundant.
Net: the entire "longer leash for human Claude-assisted PRs" story is inoperative. The bot path works (author query + backfill); the human path silently does not.
Fix: Either ship the auto-label-claude-prs.yml labeler in this PR (so the label is actually applied on human PRs with Claude attribution), or drop the claims/leg that depend on it and document that only bestaxbot-authored PRs get the 90-day leash.
Verification
$ ls .github/workflows | grep -i label → (nothing)
$ grep -rn "auto-label-claude-prs" . → only the two new files, as dangling references
$ grep -rn 'claude-assisted' .github/workflows
→ applied only by the backfill step (author bestaxbot); exempted in stale.yml
| gh pr edit "$PR" --repo "$REPO" \ | ||
| --remove-label ai-loop \ | ||
| --remove-label ai-loop-paused \ | ||
| --remove-label needs-human-review |
There was a problem hiding this comment.
Un-guarded label strip can halt the whole closer — 🟡 Minor · Correctness
What: This diverges from the on-slop.yml pattern it claims to mirror — that one ends the same three --remove-label calls with || true (on-slop.yml:67); here it runs bare under set -e. gh pr edit --remove-label X is a silent no-op only when X still exists as a repo label; if any of ai-loop / ai-loop-paused / needs-human-review has been deleted or renamed, gh exits non-zero with 'X' not found.
Why it matters: The comment justifies dropping the guard as "a failure here is a real API/auth error" — but a label removed from the repo is neither, yet it aborts the step on the first PR in the loop, so no PRs get closed that day (and every subsequent day until the label is restored). Most 90-day-stale PRs carry none of these loop labels, making them the common case that trips it.
Fix: restore the tolerant form so a stray label can't wedge the sweep, while still surfacing genuine auth failures via the daily retry:
| gh pr edit "$PR" --repo "$REPO" \ | |
| --remove-label ai-loop \ | |
| --remove-label ai-loop-paused \ | |
| --remove-label needs-human-review | |
| gh pr edit "$PR" --repo "$REPO" \ | |
| --remove-label ai-loop \ | |
| --remove-label ai-loop-paused \ | |
| --remove-label needs-human-review || true |
There was a problem hiding this comment.
Deep review — 2 finding(s)
| # | Severity | Area | Finding | Location |
|---|---|---|---|---|
| 1 | 🟠 Major | Correctness | auto-label-claude-prs.yml is referenced as the labeler but does not exist; human-authored Claude PRs never get claude-assisted, so they are swept at 30/14 instead of the intended 90-day leash |
close-stale-bestaxbot-prs.yml:12, stale.yml:11 |
| 2 | 🟡 Minor | Correctness | Label strip runs bare under set -e (unlike on-slop.yml's guard); a deleted/renamed loop label makes gh pr edit --remove-label abort the whole closer for the day |
close-stale-bestaxbot-prs.yml:111-114 |
Overall: The two-tier stale design is sound and the shell is careful (union dedupe, inclusive cutoff, fail-safe eligibility re-check, offset crons). The riskiest part is that the whole "longer leash for human Claude-assisted PRs" story depends on a labeler workflow (auto-label-claude-prs.yml) that is not in the repo — the bot path works via backfill, but the human path silently does not, so a human should decide whether to ship that labeler here or trim the claims. The label-strip guard is a lower-stakes robustness nit worth restoring. No changes touch library/runtime code, so there is no test/story/docs-API surface at stake beyond the docs table already updated.
🏄 Clean two-lane setup, dude — bot PRs ride the 90-day wave no problem. Just one board (
auto-label-claude-prs.yml) never made it to the beach, so the human surfers are gonna wipe out at day 44. Patch that in and it is all smooth swells.
# Conflicts: # docs/docs/guides/getting-started/ai-development.md
Addresses the remaining CodeRabbit thread: a workflow_dispatch overlapping the daily cron could double-comment or race gh pr close into a set -e abort. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pohc8xLkdx4gwXkW3xd7up
Preview DeploymentPreview URL: https://a4849ce6.bestax.pages.dev |
Preview DeploymentPreview URL: https://50d9f42b.bestax.pages.dev |
|
🎉 This PR is included in version 3.2.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 5.4.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 1.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 1.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |

Pull Request
Description
Two new zero-Claude workflows for stale-PR hygiene, mirroring oven-sh/bun's
close-stale-robobun-prs.ymlandstale.yaml:.github/workflows/close-stale-bestaxbot-prs.yml— daily cron (41 3 * * *, deliberately offset from the loop watchdog's23 */2 * * *) plusworkflow_dispatch. Plain shell +gh: lists open bestaxbot PRs, filtersupdatedAtolder than 90 days via adate -u -d '90 days ago'cutoff andjq select(.updatedAt < $cutoff), comments, strips the loop labels (ai-loop/ai-loop-paused/needs-human-review) before closing — the on-slop.yml pattern — so the PR exits the loop state machine cleanly, then closes..github/workflows/stale.yml—actions/stalepinned by full commit SHA (5bef64f19d7facfb25b37b414482c7164d639639# v9.1.0). PRs gostaleafter 30 days, close 14 days later;neverstaleexempts; any activity resets the clock (remove-stale-when-updated: true). Issues are deliberately disabled (days-before-issue-stale/close: -1) — a deviation from bun, whose issue side keys off a needs-repro/waiting-for-author triage process this repo doesn't run. Daily cron17 4 * * *, distinct from both other crons, plusworkflow_dispatch.Both follow house style: header comment block, workflow-level
permissions: {}, per-job least privilege (pull-requests: write,issues: write),set -euo pipefail,timeout-minutes.Docs in the same PR: two rows in the label table in
docs/docs/guides/getting-started/ai-development.md(stale,neverstale) and one sentence in rootCLAUDE.md's "AI development loop" section.@allxsmith/bestax-bulma)create-bestax)@allxsmith/bestax-docs).github/workflows/) + docsRelated Issue(s)
Closes #275
Type of Change
Checklist
--checkpasses on the changed markdown)CLAUDE.mdfiles are updatedScreenshots / Demos
n/a
Additional Context
Part 4 of 4 alongside #272 / #273 / #274 — all four touch the same label table in
ai-development.md, so trivial merge conflicts there are expected and easy to resolve.actions/stale pin verification: resolved via
git ls-remote https://github.com/actions/stale.git 'refs/tags/v9*'. The tags are lightweight (no peeled^{}entries), so the listed SHAs are the commit SHAs directly. Highest stable v9 tag isv9.1.0→5bef64f19d7facfb25b37b414482c7164d639639(also what the floatingv9tag points at). Reviewers can re-run the same command to verify.neverstalealso exempts bestaxbot PRs from the 90-day closer (the jq filter skips PRs carrying the label), so the label's documented meaning — exempt from stale automation — holds across both layers.Label rollout note:
staleauto-creates on first application (suggested color#ededed);neverstale(#c2e0c6) is human-applied and should be created at rollout.The prettier hook re-padded the existing label-table rows (whitespace-only column alignment) — no wording changes to sibling rows.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Pohc8xLkdx4gwXkW3xd7up
Summary by CodeRabbit
staleafter 30 days of inactivity and are closed 14 days later if no activity resumes.claude-assisted/bestaxbot PRs after 90+ days, withneverstalefully exempt; the closer posts closure guidance and clears AI-loop-related labels.CLAUDE.mdand AI development docs to documentstale,neverstale, and Claude-assisted timing/exemptions.