feat(skill/feature): add Phase 0.0 issue claim-on-start#3639
feat(skill/feature): add Phase 0.0 issue claim-on-start#3639PierreBrisorgueil merged 2 commits intomasterfrom
Conversation
Detects cross-session agent collisions on GitHub issues by claiming via assignee + timestamped WIP comment when /feature is invoked with #N. Stale-detection rule (>24h) lets reclaim with explicit user confirmation. Refs pierreb-projects/infra#28
Code-quality review feedback applied: - Reorder detection table: @me self-resume cases short-circuit first - Add gh issue view failure-mode handling (STOP on error) - Replace $RANDOM with uuidgen for session ID entropy - Clarify em-dash WIP marker (canonical, hyphen variants ignored) - Clarify branch TBD follow-up is best-effort manual - Drop misleading "cache per session" wording Refs pierreb-projects/infra#28
|
Caution Review failedPull request was closed or merged during review WalkthroughThe ChangesIssue Claim Phase Documentation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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.
Pull request overview
Adds an “Issue Claim” pre-phase to the /feature skill so that /feature #N can claim ownership (assignee + WIP comment) and detect potential cross-session collisions before proceeding to normal scope analysis.
Changes:
- Introduces Phase 0.0 to read issue state via
gh, detect collisions using assignees + recentWIP —comment, and STOP for explicit user confirmation on conflicts. - Adds a standardized claim procedure (assign to
@me+ post a timestamped WIP comment) before continuing to Phase 0. - Clarifies skip behavior for freeform invocations (
/feature <spec>), and STOP behavior for closed issues /ghfailures.
| ```bash | ||
| gh issue view <N> --json number,title,state,assignees,comments | ||
| ``` |
| Inspect `assignees[]` and the most recent comment whose body starts with `WIP —` (em dash U+2014, not a hyphen — only the canonical em-dash form is detected; hyphen variants `WIP -` are silently ignored): | ||
|
|
||
| | Situation | Action | | ||
| |-----------|--------| | ||
| | `assignees` contains `@me` (current GitHub user) | Continue silently — resuming own work | | ||
| | Most recent `WIP —` comment by `@me` (any age) | Continue silently — resuming own work | | ||
| | `assignees` empty AND no `WIP —` comment from anyone | Proceed to claim (step 3) | | ||
| | `assignees` contains user ≠ `@me` | **STOP** — surface "Issue #N already assigned to <user>. Take over? (y/N)". Wait for explicit user confirmation. | | ||
| | Most recent `WIP —` comment by user ≠ `@me` AND `<24h` old | **STOP** — surface "Issue #N has fresh WIP from <user> (started <ts>). Collision likely. Continue anyway? (y/N)". Wait. | | ||
| | Most recent `WIP —` comment by user ≠ `@me` AND `>24h` old | Stale claim — surface "Issue #N has stale WIP from <user> (started <ts>, >24h). Reclaim? (y/N)". Wait. | |
| Inspect `assignees[]` and the most recent comment whose body starts with `WIP —` (em dash U+2014, not a hyphen — only the canonical em-dash form is detected; hyphen variants `WIP -` are silently ignored): | ||
|
|
||
| | Situation | Action | | ||
| |-----------|--------| | ||
| | `assignees` contains `@me` (current GitHub user) | Continue silently — resuming own work | | ||
| | Most recent `WIP —` comment by `@me` (any age) | Continue silently — resuming own work | | ||
| | `assignees` empty AND no `WIP —` comment from anyone | Proceed to claim (step 3) | | ||
| | `assignees` contains user ≠ `@me` | **STOP** — surface "Issue #N already assigned to <user>. Take over? (y/N)". Wait for explicit user confirmation. | | ||
| | Most recent `WIP —` comment by user ≠ `@me` AND `<24h` old | **STOP** — surface "Issue #N has fresh WIP from <user> (started <ts>). Collision likely. Continue anyway? (y/N)". Wait. | | ||
| | Most recent `WIP —` comment by user ≠ `@me` AND `>24h` old | Stale claim — surface "Issue #N has stale WIP from <user> (started <ts>, >24h). Reclaim? (y/N)". Wait. | | ||
|
|
||
| "Current GitHub user" = `gh api user --jq .login`. Run inline each time `@me` is compared (the call is fast and read-only). | ||
|
|
| If detection passed (or user confirmed override), run **both** commands: | ||
|
|
||
| ```bash | ||
| gh issue edit <N> --add-assignee @me | ||
|
|
||
| gh issue comment <N> --body "WIP — session $(date -u +%Y%m%dT%H%M%SZ)-$(uuidgen | head -c 8), branch <branch-name>, started $(date -u +%Y-%m-%dT%H:%M:%SZ)" | ||
| ``` |
Summary
/featureskill, triggered when invoked with a GitHub issue number (/feature #N)/feature <spec>) and surfaces errors on closed issues orghfailuresDetails
Two
ghcommands on claim:gh issue edit #N --add-assignee @me+gh issue comment #N --body "WIP — ...". Detection priority: resume-own > claim > block-on-collision.Refs pierreb-projects/infra#28
Test plan
/feature #N(unassigned issue) → skill runsgh issue view, finds no assignee/WIP, proceeds to claim both commands/feature #N(issue assigned to someone else) → skill STOPs and asks user before continuing/feature #N(fresh WIP comment by other user, <24h) → skill STOPs with collision warning/feature <freeform>→ Phase 0.0 block is skipped entirely, noghcalls made/feature #N(already assigned to @me) → continues silently (resume path)Summary by CodeRabbit