User Story
As an OpenShell maintainer on triage duty,
I want an issue with active linked work to stay out of the stale sweep,
so that epics and tracked bugs are not mislabeled state:stale while a pull request implementing them is under review.
Problem Statement
The stale sweep in .github/workflows/stale.yml decides staleness from an issue's updated_at timestamp. GitHub does not bump updated_at when an issue is cross-referenced by a pull request, when a linked PR is pushed to or reviewed, or when a sub-issue is updated. As a result, an issue with active implementation work in flight is treated as inactive and receives state:stale after 14 days.
Only direct activity on the issue itself — a comment, a label change, an edit — clears or prevents the label.
Impact / Why This Matters
Today the label is cosmetically wrong but operationally harmful in three ways:
- It misrepresents queue state. During triage,
state:stale signals "nobody is working on this." A maintainer scanning the backlog cannot distinguish a genuinely abandoned issue from an epic with an open PR against it.
- It requires manual, repeating cleanup. The only workaround is for a human to comment on the issue to bump
updated_at, or to hand-apply an exempt label. This has to be redone every 14 days for the life of the work.
- It becomes destructive when closing is enabled.
days-before-issue-close is currently -1 (dry-run), so nothing closes today. When that is set to 7 as the comment anticipates, an issue with an open, actively reviewed PR will be auto-closed as not_planned.
Observed on #2174:
| Time (UTC) |
Event |
| 2026-08-28T12:07:01Z |
Stale bot commented and applied state:stale |
| 2026-08-31T08:34:58Z |
Cross-referenced by PR #3027 (Part of #2174) |
| 2026-09-02, 09-04 |
PR #3027 pushed and reviewed |
| — |
updated_at still reads 2026-08-28T12:07:01Z |
The same pattern appears earlier in that issue's history: state:stale applied 2026-07-25, cross-references from #2497 (07-27) and #1129 (08-01) did not clear it, and the label was only removed on 08-02 after a human comment.
Sub-issue activity has the same shape — a parent issue's updated_at does not move when a child issue is updated.
Acceptance Criteria
Reproduction Steps
- Open an issue and leave it without direct activity for 14 days so the sweep applies
state:stale.
- Open a pull request whose body references the issue (
Part of #<n> or Closes #<n>). Confirm the cross-referenced event appears in the issue timeline.
- Push commits to that PR and leave a review on it.
- Run
gh api repos/NVIDIA/OpenShell/issues/<n> --jq .updated_at and observe it is unchanged from step 1.
- Wait for the next scheduled sweep (
17 8 * * *). The state:stale label remains.
Live example, no setup required:
gh api repos/NVIDIA/OpenShell/issues/2174 --jq '{updated_at}'
gh api repos/NVIDIA/OpenShell/issues/2174/timeline --paginate \
--jq '.[] | select(.event=="cross-referenced") | "\(.created_at)\t\(.source.issue.number)"'
Environment
- Repository automation, not the OpenShell runtime
- Workflow:
.github/workflows/stale.yml
- Action:
actions/stale v11.0.0 (4391f3da665fdf50b6810c1a66712fb9ba21aa93)
- Schedule:
cron: "17 8 * * *"
- Current config:
days-before-issue-stale: 14, days-before-issue-close: -1 (dry-run)
- Exempt labels today:
state:triage-needed, state:validated, state:accepted, agent:*, roadmap
Notes
actions/stale has no built-in option to consider linked pull requests or sub-issues; it filters and sorts on updated_at only. A fix likely needs a pre-step that queries each candidate issue's timeline for cross-referenced events pointing at open PRs, and the sub-issues API for recent child activity, then feeds the results to exempt-issue-labels or skips those issues.
Applying an exempt label such as state:accepted works as a per-issue mitigation but does not generalize, since it conflates "a maintainer decided to pursue this" with "keep the bot away from this."
User Story
As an OpenShell maintainer on triage duty,
I want an issue with active linked work to stay out of the stale sweep,
so that epics and tracked bugs are not mislabeled
state:stalewhile a pull request implementing them is under review.Problem Statement
The stale sweep in
.github/workflows/stale.ymldecides staleness from an issue'supdated_attimestamp. GitHub does not bumpupdated_atwhen an issue is cross-referenced by a pull request, when a linked PR is pushed to or reviewed, or when a sub-issue is updated. As a result, an issue with active implementation work in flight is treated as inactive and receivesstate:staleafter 14 days.Only direct activity on the issue itself — a comment, a label change, an edit — clears or prevents the label.
Impact / Why This Matters
Today the label is cosmetically wrong but operationally harmful in three ways:
state:stalesignals "nobody is working on this." A maintainer scanning the backlog cannot distinguish a genuinely abandoned issue from an epic with an open PR against it.updated_at, or to hand-apply an exempt label. This has to be redone every 14 days for the life of the work.days-before-issue-closeis currently-1(dry-run), so nothing closes today. When that is set to7as the comment anticipates, an issue with an open, actively reviewed PR will be auto-closed asnot_planned.Observed on #2174:
state:stalePart of #2174)updated_atstill reads2026-08-28T12:07:01ZThe same pattern appears earlier in that issue's history:
state:staleapplied 2026-07-25, cross-references from #2497 (07-27) and #1129 (08-01) did not clear it, and the label was only removed on 08-02 after a human comment.Sub-issue activity has the same shape — a parent issue's
updated_atdoes not move when a child issue is updated.Acceptance Criteria
state:stale.state:stale.state:stalegains a linked open PR or sub-issue activity, the label is removed on the next sweep without a human comment.days-before-issue-closeis set to a positive value, so no issue with active linked work is auto-closed.Reproduction Steps
state:stale.Part of #<n>orCloses #<n>). Confirm thecross-referencedevent appears in the issue timeline.gh api repos/NVIDIA/OpenShell/issues/<n> --jq .updated_atand observe it is unchanged from step 1.17 8 * * *). Thestate:stalelabel remains.Live example, no setup required:
Environment
.github/workflows/stale.ymlactions/stalev11.0.0 (4391f3da665fdf50b6810c1a66712fb9ba21aa93)cron: "17 8 * * *"days-before-issue-stale: 14,days-before-issue-close: -1(dry-run)state:triage-needed,state:validated,state:accepted,agent:*,roadmapNotes
actions/stalehas no built-in option to consider linked pull requests or sub-issues; it filters and sorts onupdated_atonly. A fix likely needs a pre-step that queries each candidate issue's timeline forcross-referencedevents pointing at open PRs, and the sub-issues API for recent child activity, then feeds the results toexempt-issue-labelsor skips those issues.Applying an exempt label such as
state:acceptedworks as a per-issue mitigation but does not generalize, since it conflates "a maintainer decided to pursue this" with "keep the bot away from this."