Add a stale-assignment sweep: warn-then-release ownership decay (#209) - #217
Conversation
Add skills/pr-batch/bin/stale-assignment-sweep, a dry-run-first sweep that decays inactive human assignments. Assignment is a lease, not a deed: an assigned-but-inactive item is nudged, then (only after an unanswered grace) released back to the batch pool — the human-timescale analog of the backend's agent heartbeat leases. - Dry-run by default (zero mutations); writes only behind --apply. - Clocks: time-to-first-activity (7d anti-squatting) and inactivity-after-start (14d issues / 7d PRs), renewed only by the assignee's own activity. - Flow: nudge -> 4-day grace -> release; never release without a prior unanswered nudge; any assignee reply resets; exempt labels pause; agent-claimed items skipped (owned by backend heartbeats). - Automation set = trust-config trusted_bots + [bot]-suffixed logins (trusted_users are human/sweepable); fails closed to skip when unresolved. - Leading-@ and login guards on every gh field value; timeout-bounded gh. - 16-test suite (fake gh, injected clock); registered in bin/validate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 9 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0574053fd5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Review: stale-assignment sweepWell-structured addition — dry-run-first default, fail-closed automation resolution, Two issues flagged inline, one worth a hard look before merge: 🔴 Correctness bug —
|
Review (codex P1 x2 + claude): - Nudge markers are now attributed to the sweep's own identity (--comment-identity, else `gh api user`); an unverifiable identity fails closed (no release, nudges still run) — closing a spoof where any commenter's hidden marker could trigger a release. - Release re-fetches and re-classifies the item immediately before mutating and aborts if the decision changed (assignee reply, added agent-claimed/exempt label, reassignment) — closing a snapshot-vs-mutate TOCTOU. It acts on the fresh set. - automation_login? now requires the `[bot]` suffix AND `trusted_bots` membership (mirroring pr-security-preflight's bot_login_in_set?); a bare login is human even if it matches a bot's base name — fixing a case where a human sharing a bot's base name was never swept. Docs updated to match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 952a5498e8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Review: Stale-Assignment SweepOverview: Adds Strengths
Issues found (see inline comments for detail):
Nice work overall — the design is careful about the destructive-action risk surface here (leases, grace windows, fail-closed everywhere). The commit-activity gap is the one thing worth confirming/fixing before relying on this for PRs where assignees mostly push commits rather than comment. |
…ents Round 2 review (codex P2 + claude): - apply_nudge now re-fetches and re-classifies before posting, aborting if the item changed (reply / exempt / agent-claimed) — the same guard already used for release. - Drop `committed` from ACTIVITY_EVENTS: GitHub's timeline `committed` event carries no GitHub login, so it never matched an assignee and silently did not renew a lease. A lease now renews on the assignee's own comments, reviews, and issue-referencing commits / linked-PR events (referenced/cross-referenced, which carry a login). Help/docs/CHANGELOG updated to describe this accurately; the report-only rollout is the mechanism to validate activity coverage. - The Timeout-doesn't-kill-a-hung-gh-child issue is tracked as follow-up #218. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review: Stale-assignment sweep (#217)Overall this is a well-designed, defensively-written addition. It mirrors pr-security-preflight's trust-config resolution and bot-detection logic almost exactly (same env vars, same precedence order, same [bot]-suffix + trusted_bots check), fails closed when the automation set cannot be resolved, validates all logins before they reach gh -f fields, and re-fetches + re-classifies live state immediately before every mutation (nudge and release) to guard against races between scan and apply. Dry-run-by-default with zero mutations is the right default for a tool that removes assignees. I traced the logic by hand against the accompanying test fixtures (could not execute ruby in this sandbox: command execution required approval that was not available) and did not find a functional defect. Two things worth a look, flagged inline on the relevant lines:
Neither blocks merging given the safety-first dry-run design; both are candidates for a follow-up or doc note. Other observations (non-blocking):
Tests are extensive (dry-run, nudge, grace, release, reply-reset, exempt-label pause, agent-claimed skip, forged-marker rejection, re-check aborts, bot vs bare-login disambiguation, fail-closed) and I traced several of them (e.g. items #2 and #3 grace-day math) against the implementation by hand, and the numbers line up. |
…an items Round 3 review (claude): - Fix C: always resolve the gh-authenticated login and recognize nudge markers from either it or --comment-identity (union), so a mismatched --comment-identity can no longer hide the sweep's own gh-posted nudges and re-nudge the same item forever; a startup WARN names both on mismatch. - Fix D: the sweep only acts on single-human-assignee items. An item with 2+ human assignees is surfaced as "reserved (N human assignees) — manual review" and is never nudged or released, closing the co-assignee shielding loophole (an active co-assignee shielding an inactive squatter) and avoiding removing an active co-assignee on release. Per-assignee decay is out of scope for this version. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 78dea697fc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Review: stale-assignment sweep (#217)Overview. Adds The core state machine (fail-closed on unresolved trust, own-identity-only nudge markers, live re-check before every mutation, multi-human items surfaced instead of auto-swept, Issues found (posted inline)
Minor / non-blocking observations
Overall: solid, well-tested implementation of a genuinely tricky decay/lease state machine. The two issues above are worth addressing before relying on this for unattended scheduled runs, but neither is a security concern. |
…reads Round 4 review (codex P2 + claude): - Fix E: classify skips a non-open item (state guard), so a re-checked item that was closed/merged between listing and --apply is not nudged/released. - Fix F: --exempt-label now adds to the blocked/on-hold defaults instead of silently replacing them. - Fix G: a single gh failure no longer aborts the whole run — per-item read errors are reported as UNKNOWN and skipped, a failing repo doesn't stop the others, and the digest still prints (exit 0). Per-item --apply mutations stay fail-safe. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review: stale-assignment sweep (#209)Overall this is a well-designed, cautious piece of automation — dry-run-first default, fail-closed on unresolved trust config, re-check-before-mutate on both nudge and release, per-item/per-repo error isolation, and a genuinely thorough test suite (16 tests covering the tricky edge cases: forged markers, grace windows, multi-human items, closed-between-scan-and-apply, bot co-assignees). Nice work. Findings
Nice details
Nothing here is release-blocking given the dry-run-first rollout plan, but #1 is worth a decision before |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 65eadaa002
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… epoch Round 5 review (codex P2 x2 + claude): - Fix J: automation_login? treats any [bot]-suffixed login as automation when trusted_bots is empty (the packaged-fallback default), so consumer deployments don't sweep every bot; a configured trusted_bots still requires membership. - Fix H: reject negative --grace-days / TTL flags before any gh call. - Fix I: remove the assignee before posting the release audit comment, so a failed DELETE leaves no misleading "Released" comment. - Fix K: skip a login with no assigned event instead of measuring from EPOCH, so pre-assignment activity can't renew a lease (falls through to fail-closed UNKNOWN). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review: Add stale-assignment sweep (#209)OverviewAdds Code quality
Correctness
Security
Performance
Test coverage
Overall this is a careful, conservative implementation with no blocking issues found. Two minor suggestions left as inline comments. |
Summary
Adds
skills/pr-batch/bin/stale-assignment-sweep— a dry-run-first warn-then-release sweep that decays inactive human assignments soowned means skip(#208) can't reserve work forever. Assignment is a lease, not a deed.Behavior
--apply. (Ship report-only for ~2 weeks to tune TTLs before enabling writes.)time-to-first-activity(7d anti-squatting) andinactivity-after-start(14d issues / 7d PRs). A lease is renewed only by the assignee's own commits/comments/reviews/linked-PR events.blocked,on-hold) pause the clock.trusted_bots+[bot]-suffixed logins via thepr-security-preflightchain (trusted_usersare human/sweepable). Fails closed (leaves human assignments untouched) when the set can't be resolved.agent-claimeditems are skipped entirely (owned by backend heartbeats — the Mirror agent lane claims to GitHub with an agent-claimed label #210 hook).@guard on comment bodies,valid_login?checks before anygh -ffield,--reposhape validation, timeout-boundedgh. Nothing silently dropped — every skip is reported with its reason.Config / flags
--repo(repeatable),--apply,--now/STALE_ASSIGNMENT_SWEEP_NOW,--first-activity-ttl-days,--issue-inactivity-ttl-days,--pr-inactivity-ttl-days,--grace-days,--exempt-label,--comment-identity,--trust-config; gh bounded bySTALE_ASSIGNMENT_SWEEP_GH_TIMEOUT_SECONDS.Tests
skills/pr-batch/bin/stale-assignment-sweep-test.rb— 16 tests / 113 assertions (fakeghon PATH, deterministic injected clock), registered inbin/validate. Covers: dry-run zero-mutation, nudge/grace/release, release-requires-prior-nudge, reply-resets, exempt-pause, agent-claimed skip, automation-never-swept, co-assigned-bot-kept, fail-closed, and@-injection guards.rubocop _1.87.0_clean.Acceptance criteria (issue #209)
agent-claimeditems (Mirror agent lane claims to GitHub with an agent-claimed label #210 marker).Closes #209.
Part of the assignment-aware series (#208 merged → #209 → #210).
🤖 Generated with Claude Code