Janitor rule: dispatch rebase for unmergeable open PRs (closes the no-event gap) #781
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks#781
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
User story
As an operator, I want unmergeable open PRs whose author is a configured agent to be auto-rebased even when no triggering webhook fires, so that a long-lived PR doesn't sit stuck after
mainmoves on under it.Background
Forgejo fires no event when a PR's
mergeableflips tofalse. We currently close that loop in two places:handlePostMergeRebase(apps/server/src/domain/workflow/event-handlers.ts:1069) — runs onpull_request closed && merged=trueand walks siblings on the same base.pr-changes-requested-graph.jsonmergeable_route— routes anot_mergeablearm when a reviewer requests changes.Gaps both miss:
mainoutside the PR-merge path (release tags, manual fast-forward, force push).Operator observation 2026-05-03: rebase agents not triggered "at least not all the time" on conflicts.
Proposed fix
Add a janitor rule
unmergeable_pr_rebaseinapps/server/src/background/janitor.ts:mergeable === false.resolveAgentByUser; skip non-agent authors.pr_dependencies— same three-way routing ashandlePostMergeRebase(skip if PR declares parents that haven't merged).markPostMergeRebaseDispatchedso a janitor pass and an event-driven pass can't double-dispatch.skillForEvent("rebase")+buildAgentRequest+dispatchByTypepath ashandlePostMergeRebase.Acceptance criteria
Janitor rule
unmergeable_pr_rebaseregistered in_ALL_RULESandreconcileOnceimpl.listOpenPullRequestsdetail.mergeable !== falsepr_dependenciesmarkers (skip if declared parents are still open)dispatchByType("rebase")pathDedup
_postMergeRebaseDispatchedmap keyed onrepo#pr@shaalreadyDispatchedPostMergeRebaseis exported and consumed by the ruleIdempotency
canActwindow also gates the rule (defence in depth)markActed("unmergeable_pr_rebase", repo, "PR#N")after dispatchTests
mergeable=false+ agent author + no parentsmergeable=truejust qacleanOut of scope
tail-pr-rebase-watchdog).handleStackedRebaseCascade).References
apps/server/src/domain/workflow/event-handlers.ts:1014-1018— author's own comment names the missing event.event-handlers.ts:1069-1153.apps/server/src/background/janitor.ts:528-564(ruleReadyToMerge).1043-1067.