Problem Statement
OpenShell currently marks inactive issues as state:stale after 14 days but never closes them. Maintainers want issues that remain stale for another 14 days to close automatically, while preserving the ability to keep an issue open by commenting or removing the stale label.
Technical Context
The repository already uses the pinned actions/stale v10.4.0 action in a daily workflow. The action supports the requested issue lifecycle directly, but .github/workflows/stale.yml explicitly disables closure by setting days-before-issue-close: -1. The same workflow handles pull requests, so the issue policy must remain separate from PR handling.
Affected Components
| Component |
Key Files |
Role |
| Stale automation |
.github/workflows/stale.yml |
Schedules stale processing and configures issue and PR marking, messages, exemptions, and closure |
| Contributor policy |
CONTRIBUTING.md |
Documents stale lifecycle behavior and exemptions |
| Issue triage automation |
.github/workflows/issue-triage.yml |
Applies the existing state:triage-needed exemption to incoming community issues |
Technical Investigation
Architecture Overview
The Mark stale issues and pull requests workflow runs daily at 08:17 UTC and can also be dispatched manually. Its job grants issues: write and pull-requests: write, then invokes a SHA-pinned actions/stale release. The action tracks inactivity from GitHub item updates, adds state:stale after the configured threshold, removes the label after qualifying activity by default, and can close an item after a second threshold.
Issue and PR controls are separate. Both become stale after 14 days, but both close thresholds are currently -1, which disables closing. This is not dry-run mode despite the workflow comments; the action's actual dry-run input is debug-only.
Code References
| Location |
Description |
.github/workflows/stale.yml:3-6 |
Daily schedule and manual dispatch entry points |
.github/workflows/stale.yml:14-16 |
Existing write permissions already sufficient for closing issues |
.github/workflows/stale.yml:18 |
SHA-pinned actions/stale v10.4.0 invocation |
.github/workflows/stale.yml:23-26 |
Issues and PRs become stale after 14 days; closure is disabled with -1 |
.github/workflows/stale.yml:28-29 |
Issue exemptions and not_planned close reason |
.github/workflows/stale.yml:31-42 |
Messages still describe a seven-day close window even though closure is disabled |
.github/workflows/issue-triage.yml:47-57 |
Applies state:triage-needed, one of the existing stale exemptions |
CONTRIBUTING.md:99-101 |
Documents state labels and currently inaccurate seven-day close behavior |
Current Behavior
After 14 days without activity, issues and PRs receive state:stale and a comment. Subsequent qualifying activity removes the stale label under the action's default remove-stale-when-updated: true behavior. Items labeled state:triage-needed or roadmap are exempt from issue processing.
Neither issues nor PRs close because both days-before-*-close values are -1. The issue and PR messages nevertheless say closure may occur after seven days, and CONTRIBUTING.md repeats that policy. Workflow permissions require no change.
What Would Need to Change
In .github/workflows/stale.yml, set days-before-issue-close: 14, correct the misleading dry-run comment, and update the issue messages from seven to 14 days. Keep days-before-pr-close: -1 because the request concerns issues; remove the false closure promise from the PR stale message and either remove the inert PR close message or leave it clearly inactive.
Update CONTRIBUTING.md to state that issues close after 14 additional inactive days while PRs are only marked stale. Keep the existing not_planned close reason unless maintainers want different reporting semantics.
Before rollout, review existing stale issues and decide whether active workflow states need exemptions. At investigation time, 38 open issues carry state:stale, including issues also labeled state:in-progress, state:agent-ready, state:review-ready, state:pr-opened, and needs-rfc. Old stale issues may close as soon as a scheduled run reaches them after the configuration lands.
Alternative Approaches Considered
A separate workflow, custom script, or replacement bot could implement delayed closure but would duplicate functionality already provided by actions/stale, add maintenance cost, and require custom tests. The existing issue-specific close input is the smallest correct approach.
Increasing operations-per-run could process the backlog faster, but the default limit of 30 is already consumed by normal runs and changing it would increase the size of the initial closure burst. Keep the default unless maintainers explicitly prefer faster cleanup after reviewing API limits and backlog impact.
Patterns to Follow
Keep the action pinned to an immutable SHA with its release comment. Retain least-privilege job permissions and let Dependabot manage action updates. Document repository-governance behavior in CONTRIBUTING.md; no product or architecture documentation is needed.
Proposed Approach
Use the existing action's issue-specific days-before-issue-close: 14 input and keep PR closure disabled. Align issue and PR messages with their actual behavior and update contributor documentation. Preserve automatic unstaling, current issue exemptions, and the not_planned close reason. Audit the existing stale backlog before merge and add only those workflow-state exemptions that reflect maintainer policy.
Scope Assessment
- Complexity: Low
- Confidence: High - the pinned action directly supports the requested behavior
- Estimated files to change: 2
- Issue type:
chore
Risks & Open Questions
- Should stale issues with
state:in-progress, state:agent-ready, state:review-ready, state:pr-opened, topic:security, or needs-rfc be exempt from closure?
- Should maintainers accept immediate gradual closure of the existing stale backlog, or first remove stale labels from issues that should remain open?
- Keep
close-issue-reason: not_planned for accurate GitHub reporting, or use another reason?
actions/stale retains state:stale after closure. Is that desirable as lifecycle history? Removing it would require separate custom automation.
- Scheduled execution and the action's operation limit mean closure occurs after at least 14 additional days, not at an exact deadline.
- Existing stale comments mentioning seven days cannot be corrected retroactively.
Test Considerations
- Validate input names against the pinned
actions/stale v10.4.0 action.yml and review the rendered workflow YAML.
- Run
mise run pre-commit; no OpenShell unit or sandbox end-to-end tests are needed for this workflow-only change.
- Audit currently stale issues before merge and apply agreed exemptions or remove stale labels as needed.
- After merge, manually dispatch the workflow or inspect its next scheduled run.
- Confirm logs report
Days before issue close: 14 and Days before pull request close: -1.
- Spot-check closure message,
not_planned reason, retained stale label, and unstale-on-activity behavior.
Documentation and Platform Impact
Update CONTRIBUTING.md only. This does not affect published product docs, architecture docs, gateway TOML, Helm, compute drivers, sandbox infrastructure, or cluster guidance. It has no SELinux, AppArmor, Landlock, seccomp, process identity, /proc, or other LSM impact.
Created by spike investigation. Use build-from-issue to plan and implement.
Problem Statement
OpenShell currently marks inactive issues as
state:staleafter 14 days but never closes them. Maintainers want issues that remain stale for another 14 days to close automatically, while preserving the ability to keep an issue open by commenting or removing the stale label.Technical Context
The repository already uses the pinned
actions/stalev10.4.0 action in a daily workflow. The action supports the requested issue lifecycle directly, but.github/workflows/stale.ymlexplicitly disables closure by settingdays-before-issue-close: -1. The same workflow handles pull requests, so the issue policy must remain separate from PR handling.Affected Components
.github/workflows/stale.ymlCONTRIBUTING.md.github/workflows/issue-triage.ymlstate:triage-neededexemption to incoming community issuesTechnical Investigation
Architecture Overview
The
Mark stale issues and pull requestsworkflow runs daily at 08:17 UTC and can also be dispatched manually. Its job grantsissues: writeandpull-requests: write, then invokes a SHA-pinnedactions/stalerelease. The action tracks inactivity from GitHub item updates, addsstate:staleafter the configured threshold, removes the label after qualifying activity by default, and can close an item after a second threshold.Issue and PR controls are separate. Both become stale after 14 days, but both close thresholds are currently
-1, which disables closing. This is not dry-run mode despite the workflow comments; the action's actual dry-run input isdebug-only.Code References
.github/workflows/stale.yml:3-6.github/workflows/stale.yml:14-16.github/workflows/stale.yml:18actions/stalev10.4.0 invocation.github/workflows/stale.yml:23-26-1.github/workflows/stale.yml:28-29not_plannedclose reason.github/workflows/stale.yml:31-42.github/workflows/issue-triage.yml:47-57state:triage-needed, one of the existing stale exemptionsCONTRIBUTING.md:99-101Current Behavior
After 14 days without activity, issues and PRs receive
state:staleand a comment. Subsequent qualifying activity removes the stale label under the action's defaultremove-stale-when-updated: truebehavior. Items labeledstate:triage-neededorroadmapare exempt from issue processing.Neither issues nor PRs close because both
days-before-*-closevalues are-1. The issue and PR messages nevertheless say closure may occur after seven days, andCONTRIBUTING.mdrepeats that policy. Workflow permissions require no change.What Would Need to Change
In
.github/workflows/stale.yml, setdays-before-issue-close: 14, correct the misleading dry-run comment, and update the issue messages from seven to 14 days. Keepdays-before-pr-close: -1because the request concerns issues; remove the false closure promise from the PR stale message and either remove the inert PR close message or leave it clearly inactive.Update
CONTRIBUTING.mdto state that issues close after 14 additional inactive days while PRs are only marked stale. Keep the existingnot_plannedclose reason unless maintainers want different reporting semantics.Before rollout, review existing stale issues and decide whether active workflow states need exemptions. At investigation time, 38 open issues carry
state:stale, including issues also labeledstate:in-progress,state:agent-ready,state:review-ready,state:pr-opened, andneeds-rfc. Old stale issues may close as soon as a scheduled run reaches them after the configuration lands.Alternative Approaches Considered
A separate workflow, custom script, or replacement bot could implement delayed closure but would duplicate functionality already provided by
actions/stale, add maintenance cost, and require custom tests. The existing issue-specific close input is the smallest correct approach.Increasing
operations-per-runcould process the backlog faster, but the default limit of 30 is already consumed by normal runs and changing it would increase the size of the initial closure burst. Keep the default unless maintainers explicitly prefer faster cleanup after reviewing API limits and backlog impact.Patterns to Follow
Keep the action pinned to an immutable SHA with its release comment. Retain least-privilege job permissions and let Dependabot manage action updates. Document repository-governance behavior in
CONTRIBUTING.md; no product or architecture documentation is needed.Proposed Approach
Use the existing action's issue-specific
days-before-issue-close: 14input and keep PR closure disabled. Align issue and PR messages with their actual behavior and update contributor documentation. Preserve automatic unstaling, current issue exemptions, and thenot_plannedclose reason. Audit the existing stale backlog before merge and add only those workflow-state exemptions that reflect maintainer policy.Scope Assessment
choreRisks & Open Questions
state:in-progress,state:agent-ready,state:review-ready,state:pr-opened,topic:security, orneeds-rfcbe exempt from closure?close-issue-reason: not_plannedfor accurate GitHub reporting, or use another reason?actions/staleretainsstate:staleafter closure. Is that desirable as lifecycle history? Removing it would require separate custom automation.Test Considerations
actions/stalev10.4.0action.ymland review the rendered workflow YAML.mise run pre-commit; no OpenShell unit or sandbox end-to-end tests are needed for this workflow-only change.Days before issue close: 14andDays before pull request close: -1.not_plannedreason, retained stale label, and unstale-on-activity behavior.Documentation and Platform Impact
Update
CONTRIBUTING.mdonly. This does not affect published product docs, architecture docs, gateway TOML, Helm, compute drivers, sandbox infrastructure, or cluster guidance. It has no SELinux, AppArmor, Landlock, seccomp, process identity,/proc, or other LSM impact.Created by spike investigation. Use
build-from-issueto plan and implement.