Repository navigation
[WIP] Block self-assignment for a cooldown after an inactivity removal #127
Description
Overview
The weekly sweep unassigns a contributor for inactivity. The contributor comments /assign and
the bot assigns them again within hours. The removal carries no weight, and a contributor who was
waiting loses the issue.
Block self-assignment for a cooldown period after the bot removes a contributor for inactivity.
During the cooldown, only a maintainer can assign them. The block covers every issue in the
community repos, not only the issue they left.
Context
On learningequality/kolibri#14261, a maintainer unassigned a contributor on 2026-10-23 at 13:07
UTC. Someone else asked for the issue the next morning. At 05:04 UTC the removed contributor
asked to be assigned again, the bot replied "Comment /assign to assign yourself", and at 05:07
the bot assigned them. The maintainer removed them a second time on 2026-10-26.
scripts/contributor-issue-comment.js reads recent unassignments and adds them to the
assignment count instead of blocking:
const totalSlots = assignedIssues.length + filteredUnassignments.length;
if (totalSlots >= MAX_ASSIGNED_ISSUES) { ... }MAX_ASSIGNED_ISSUES is 2, so one removal leaves a free slot and /assign passes.
getRecentUnassignments in scripts/utils.js reads event.assignee.login and ignores
event.actor.login, so it cannot tell who removed the contributor.
Two bot messages send the contributor back. BOT_MESSAGE_KEYWORD_GOOD_FIRST_ISSUE tells any
contributor to comment /assign, and the unassignment comment in
scripts/unassign-inactive-issues.js says "please message us here, and we'll assign you again".
The Change
Classify each unassignment by actor. Return unassignedBy from event.actor.login:
| Actor | Meaning | Effect |
|---|---|---|
| The contributor | Self-drop | Consumes a slot, as it does today |
learning-equality-bot[bot] |
Inactivity removal | Starts the cooldown |
| Anyone else | Not an inactivity removal | No cooldown |
Unassignment for inactivity belongs to the sweep, so the bot is the actor and no marker is
needed. A maintainer using the assignee menu starts no cooldown, because that removal was not
for inactivity.
Block /assign during the cooldown. Check it in handleAssignCommand before the limit
check. A block is not a slot, and the issue the contributor left is no exception. Only a
maintainer can assign them during the cooldown, by hand.
Add REMOVAL_COOLDOWN_DAYS to scripts/constants.js, set to 7.
getRecentUnassignments takes the longer of the two windows, and each rule reads its own.
Add a block message that names the days remaining and says that a maintainer can assign them
by hand. Send BOT_MESSAGE_KEYWORD_GOOD_FIRST_ISSUE only to a contributor who is not under
cooldown, and reword the unassignment comment to name the cooldown instead of promising
re-assignment.
Out of Scope
- Changing
MAX_ASSIGNED_ISSUES,ASSIGN_COOLDOWN_DAYS, or the 30-day inactivity threshold. - Blocking an assignment that a maintainer makes by hand.
- What counts as inactivity. That is [WIP] Measure inactivity as unanswered feedback to the assignee #128.
Acceptance Criteria
- A contributor whom the bot removed for inactivity within the cooldown cannot self-assign
the issue they left, or any other issue in a community repo. - A maintainer can assign a contributor under cooldown by hand.
- A removal by a maintainer through the assignee menu starts no cooldown.
- A self-drop keeps the current behaviour, that is it consumes a slot and does not block.
- Once the cooldown expires,
/assignworks again. - The block message names the days remaining and does not tell the contributor to comment
/assign. - The bot does not post
BOT_MESSAGE_KEYWORD_GOOD_FIRST_ISSUEto a contributor under
cooldown. - The unassignment comment names the cooldown and promises no re-assignment.
Testing
Test in test-actions. See
testing the automations.
The contributor cases need an account outside the organization.
- Label an issue
help wantedandgood first issue, then comment/assignfrom the
contributor account. Expect an assignment. - Dispatch the sweep so that the bot unassigns the contributor, then comment
/assignagain.
Expect a refusal that names the days remaining. - Comment
/assignon a secondgood first issue. Expect the same refusal. - Assign the contributor by hand. Expect the assignment to hold.
- Unassign the contributor through the assignee menu, then comment
/assign. Expect an
assignment, because a maintainer removal starts no cooldown. - Unassign yourself from the contributor account, then comment
/assignon a second issue.
Expect an assignment, because one slot is free.
References
The real case is learningequality/kolibri#14261. #128 fixes what the sweep counts as inactivity,
and this issue depends on it, because the sweep is the actor that starts the cooldown.
AI usage
I used Claude Code to read the assignment gate, to trace the timeline of kolibri#14261, and to
confirm that getRecentUnassignments ignores the actor. I decided that the cooldown blocks
rather than consumes a slot, that it covers every issue, and that only an inactivity removal by
the bot starts it.
Activity
[-]Block self-assignment for a cooldown after a maintainer unassigns a contributor[/-][+]Block self-assignment for a cooldown after an inactivity removal[/+][-]Block self-assignment for a cooldown after an inactivity removal[/-][+][WIP] Block self-assignment for a cooldown after an inactivity removal[/+]