Skip to content

chore(contributing): make issue claims visible and expire them - #859

Merged
s-annam merged 1 commit into
mainfrom
chore/claim-visibility-and-expiry
Aug 17, 2026
Merged

chore(contributing): make issue claims visible and expire them#859
s-annam merged 1 commit into
mainfrom
chore/claim-visibility-and-expiry

Conversation

@s-annam

@s-annam s-annam commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Claim state for an issue lived only in the assignee field, which is invisible in every channel a contributor browses. This puts it in a label, documents the protocol, and expires claims that go quiet.

No product code is touched — CONTRIBUTING.md and one new workflow.

Why

On 2026-08-16, four PRs arrived for two issues:

Issue PRs Assigned at the time?
#681 #853, #854 Yes — for 17 days
#832 #840, #855 No

The #681 case is the interesting one. The assignment wasn't missing; @rohithgollapalli self-assigned on 2026-07-30. Two contributors still built it independently, because:

  • gh issue list prints labels, not assignees. The default table is number / state / title / labels / updated. A contributor scanning the backlog from the CLI sees no claim signal at all.
  • On the web list the assignee is a small right-margin avatar, easy to miss and absent from some search views.
  • Both collisions were on good first issue. That label selects for newcomers and for tooling that scans the backlog — precisely the population least likely to open an issue and read its sidebar before starting. One of the four PRs arrived on manus/* branches, which points at agent-driven contribution; that reads labels and issue text, not avatars.
  • CONTRIBUTING.md had no claim protocol. 193 lines on setup, branches, commits, PRs, tests, style, filing and the board — nothing on how to pick up work. The only assign match in the file is an env-var assignment.

Storing the claim where nobody looks is the whole defect. Three contributors lost an evening to it in one day.

What changes

1. status:claimed label — already created on the repo and applied to #681 and #832. It rides alongside the assignee and appears inline in every list view:

832  OPEN  [parser] skills — single-letter language tokens…  bug, good first issue, ux:parsing, status:claimed

That line is what both contributors saw before; it now carries the claim.

2. CONTRIBUTING.md → "Claiming an issue" — check the label before starting, comment to claim, a maintainer assigns and labels, what happens when a claim lapses. Also states that a maintainer-initiated assignment is a request, not an obligation.

3. .github/workflows/stale-claims.yml — daily job releasing a claim after 7 days with no linked PR and no activity.

A claim that never expires is worse than no claim: it reads as abandoned, so people route around it and the label stops meaning anything. A 17-day-old claim is exactly what this incident ran into.

The job is deliberately narrow:

  • never closes an issue, never edits a body, never changes a milestone
  • never touches a claim with an open linked PR — the PR is the work, however quiet the issue went
  • any activity resets the clock, so a one-line "still on it" holds a claim indefinitely
  • comments whenever it releases one, saying what happened and inviting re-claim
  • everything it does is undone by re-assigning and re-adding the label
  • cleans up the inconsistent status:claimed-with-no-assignee state too

workflow_dispatch takes a dry_run input so its selection can be inspected before the cron is trusted.

Verification

  • npm run verify green (pre-push gate): typecheck, lint, gates, tests, build, fallow.
  • fallow clean on both changed files.
  • Workflow YAML parses; the embedded github-script body passes node --check.
  • Label behaviour confirmed live against gh issue list --label "good first issue" — see the table above.

The scheduled job has not run yet. Recommend one workflow_dispatch with dry_run: true after merge to confirm its selection before the first real cron; it writes nothing in that mode.

Deliberately not included

  • Removing good first issue while claimed. It attacks the magnet more directly but churns labels and loses the newcomer-friendly signal on an issue that may be released a week later. Worth revisiting if collisions continue.
  • Auto-assign on a "I'll take this" comment. Wanted eventually, but it needs intent parsing, and a wrong auto-assign is more annoying than a missing one.

Follow-up

@rohithgollapalli's claim on #681 has been released and they've been notified on the issue; #681 and #832 are now assigned to @shubhransh-gupta, who has approved work on both.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 16, 2026

Copy link
Copy Markdown

Deploying offlinecv with  Cloudflare Pages  Cloudflare Pages

Latest commit: bc2ed4a
Status: ✅  Deploy successful!
Preview URL: https://82a342a5.offlinecv.pages.dev
Branch Preview URL: https://chore-claim-visibility-and-e.offlinecv.pages.dev

View logs

@s-annam s-annam left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Verdict: APPROVE (0 Blocking findings; mechanism is sound, safe-by-construction, and fully non-destructive).

This PR introduces status:claimed visibility and an automated expiry workflow (.github/workflows/stale-claims.yml) to resolve issue-claiming collisions (like the #681 / #832 incidents). The design is clean, conservative, and reversible.

Gates & Quality Pass

  • Verification Suite: npm run verify passed cleanly (5,864 tests green, typecheck clean, lint clean, fallow clean).
  • Fixture PII: N/A (no fixture files touched).
  • Design System / Style Tokens: N/A (no frontend code touched).
  • Dead Code / Fallow: Clean (0 issues in changed files).
  • Description Audit: Accurate claims; correctly documents behavior and manual dry-run workflow.

Findings Summary

  • Blocking: 0
  • Secondary: 2 (cross-repo timeline scoping, loop error resilience)
  • Nits: 2 (workflow concurrency group, self-assignment doc polish)

Reviewed by: Gemini 3.7 Flash (high)

Comment thread .github/workflows/stale-claims.yml
Comment thread .github/workflows/stale-claims.yml
Comment thread .github/workflows/stale-claims.yml
Comment thread CONTRIBUTING.md
Two contributors independently built #681 while it was assigned to a third,
because the claim was invisible: `gh issue list` prints labels and not
assignees, and on the web list the assignee is a small avatar in the right
margin. Pair the assignee with a `status:claimed` label so a claim is readable
without opening the issue, and document the two-signal rule in CONTRIBUTING —
including the corollary that a contributor with write access who self-assigns
must add the label themselves, since self-assignment skips the maintainer step
that would otherwise attach it.

A claim that never expires is worse than no claim: it reads as abandoned, so
people route around it and the label stops meaning anything. Add a daily
`stale-claims.yml` job that drops the assignee and the label after 7 days with
no activity and no linked PR, commenting to say what happened and how to take
the claim back. It never closes an issue, never edits a body, and everything it
does is reversible by re-assigning and re-adding the label.

The open-PR exemption is scoped to this repository on purpose. `cross-referenced`
timeline events fire for a reference from any public repo on GitHub, including a
PR opened on a personal fork against the fork's own `main` and never submitted
here; unscoped, any of those would exempt a claim forever. Per-issue mutations
run under try/catch so one locked issue or concurrently-removed label cannot
halt the batch, and a queueing concurrency group keeps a manual dispatch from
double-commenting over the scheduled run.
@s-annam
s-annam force-pushed the chore/claim-visibility-and-expiry branch from 18e7093 to bc2ed4a Compare August 17, 2026 00:13
@s-annam
s-annam merged commit dc4dede into main Aug 17, 2026
3 checks passed
@s-annam
s-annam deleted the chore/claim-visibility-and-expiry branch August 17, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant