一键导入
check-open-prs
// Personal PR inbox for LI.FI engineers — covers both outgoing PRs (yours) and incoming review queue (others'). Produces a single dry-run dashboard with (a) your OWN open PRs cross-referenced with their
// Personal PR inbox for LI.FI engineers — covers both outgoing PRs (yours) and incoming review queue (others'). Produces a single dry-run dashboard with (a) your OWN open PRs cross-referenced with their
Use when drafting, maintaining, refining, or auditing a structured user-stories catalogue from a product spec + design-review notes + open-questions list. Outputs persona-grouped stories with explicit linkage to unresolved open questions, in a readable format suited for product, engineering, and audit review alike. Trigger on "write user stories for", "draft stories from this spec", "expand the user stories", "add a story for X", "audit the catalogue", "clean up the open questions", "refine the stories", or any request to produce or maintain a stories catalogue. Use this skill whenever the user is working on a structured stories catalogue or its companion open-questions page, even if they don't say "user story" explicitly. Skip for casual feature lists or one-off ticket descriptions.
Start work on a Linear ticket — fetches the issue, creates a properly-named local git branch in the right repo, moves the ticket to "In Progress", and assigns it to the current user. Use when the user says "start ticket", "start linear ticket", "begin work on EXSC-XXX", "/start-ticket", "let's start <ID>", or supplies a Linear issue ID/URL with intent to begin work. Mirrors the "Create branch" button from Jira, but also handles the status flip and ownership claim in one step — designed for orgs where PR-auto-assign is off but starting work is the right moment to claim a ticket. Requires the Linear MCP server. Skip if the user is just asking about a ticket (read intent) rather than starting work, or if the ticket is already In Progress and has a linked branch — in that case just show the existing branch.
Post a pull request to the LI.FI `#dev-sc-review` Slack channel for smart-contract team review. Enables auto-merge (squash) on the PR by default, posts the PR URL + title as a top-level message (matching the existing channel format `<URL> << <title>`), then replies in-thread tagging the `@smartcontract_core` user group. Use when the user says "post PR for review", "send to sc review", "share PR with sc team", "post to dev-sc-review", or supplies a PR URL with intent to request review from the smart-contract core team. Requires the Slack MCP server to be connected.
| name | check-open-prs |
| description | Personal PR inbox for LI.FI engineers — covers both outgoing PRs (yours) and incoming review queue (others'). Produces a single dry-run dashboard with (a) your OWN open PRs cross-referenced with their |
A personal PR inbox: triage your own open PRs (where you're waiting on the team vs the team's waiting on you) and the team's open PRs in the review channels (where you can pick up an unreviewed one, or re-review one you already commented on). Always dry-run first; act only on explicit approval.
gh user (gh api user --jq '.login').open. Drafts go into their own bucket, not "excluded".Violations are bugs — stop, fix, re-run.
Message TS on the actual last reply by the current user. Threads routinely have multi-day-later follow-ups ("ready for re-review" two days after the parent), so parent-post ts is not a substitute.response_format="detailed". Concise format strips per-reply timestamps. If a fetch came back concise, re-fetch before classifying.reply_count or assume reply 1 is the only one.Surface a one-line audit at the end of Phase 1 with the exact Message TS used per PR, so the user can spot-check:
Audit: #1806 cooldown ts=1779065876.814329 (2026-05-18 07:57:56 +07, 0.4h ago) → RECENTLY-PINGED
gh search prs --author=@me --state=open --limit 200 \
--owner lifinance --owner lifinance-tron \
--json url,title,number,repository,createdAt,updatedAt,isDraft
No --created filter — pull ALL open PRs (keeping a clean slate is part of the job).
Scope to LI.FI orgs. --owner lifinance --owner lifinance-tron restricts results to LI.FI repos; without it, --author=@me returns every open PR on GitHub (personal forks, OSS contributions, etc.). Extend the --owner list if LI.FI publishes PRs under additional orgs.
Drop archived-repo PRs. gh search prs returns PRs in archived repositories; those can't be merged or acted on. For each unique repository.nameWithOwner, check once:
gh api repos/<owner>/<repo> --jq '.archived'
Cache per-repo (one call per repo). Add the dropped count to the Excluded section as Archived repo: N (repos: …) so the scan stays auditable.
Split by age:
createdAt within last 6w OR updatedAt within last 2w. Goes through the REMIND / YOUR-ACTION / OWN-DRAFTS flow.createdAt ≥6w ago AND updatedAt ≥2w ago. Goes to its own STALE bucket for human disposition.Route to a Slack channel by repo:
lifinance/contracts, lifinance/contracts-tron → #dev-sc-review (C088UJWC8PR).lifinance/lifi-backend, lifinance/tenderly-sim, other backend services → #dev-backend-expansion-review (resolve via slack_search_channels).lifi-claude-plugins, lifi-team-skills, …) → no channel; mark "no review thread expected".For each non-draft, non-stale active PR:
Find the Slack post. Search the routed channel:
in:#<channel> pull/<NUMBER> from:<@<current-user-slack-id>>
If no result, mark "not posted for review yet" and surface in the dashboard so the user can decide whether to post.
Read the thread (response_format="detailed"). Walk every reply.
hours_since = (now - your_last_ts) / 3600.
<48h → REMIND-RECENTLY-PINGED (skip Phase 2A; spam guard).≥48h → REMIND-DUE (eligible for Phase 2A).Edge cases:
Drafts aren't posted for review, but they're still work-in-progress that you owe yourself. Don't dump them into "Excluded".
For each active draft (stale drafts roll into STALE):
gh api repos/<owner>/<repo>/pulls/<n>/commits --jq '.[-1].commit.committer.date'
gh pr view <n> --json statusCheckRollup
Classify into a likely-disposition bucket:
/post-pr-for-review".(WIP) → suggest "finish the WIP".chore(claude): sync … or chore(skills): sync … (auto-sync output) → suggest "check if the sync target has since been re-synced (PR may be obsolete) or merge".This is the team-inbox half. Scan the same channel(s) for PRs not posted by the current user.
List PR-post messages in #dev-sc-review from the last 6 weeks (paginate as needed). Each post follows the <URL> << <title> convention. Extract (owner, repo, pr_number, parent_ts, posted_at, slack_author).
Drop entries where slack_author == current_user (already covered in 1.2).
For each remaining PR, fetch state in parallel:
gh pr view <n> --repo <owner>/<repo> --json \
author,state,isDraft,reviewDecision,reviews,latestReviews,commits,updatedAt,mergeable
Drop state != "OPEN" or isDraft == true.
Reduce against the current user (me):
my_last_review = latest reviews entry where author.login == me (capture state, submittedAt).
any_human_review = any review by a real user (exclude bots: coderabbitai, github-actions, *-bot, app/*).
last_commit_ts = latest commits[].commit.committedDate.
Slack thread state — read with response_format="detailed" (mandatory; re-review signals live in Slack, not GitHub). Capture latest author + ts. Detect a re-review signal in any message authored by the PR author after my_last_review.submittedAt, case-insensitive regex:
ready (for|to) re-?review | please re.?review | addressed | updated.*PR | PTAL | fixed @ | all comments addressed | rebased
If the re-review ping mentions someone else (@<other>) but my prior review is still open (COMMENTED / CHANGES_REQUESTED with no follow-up from me), still classify as INBOX-REREVIEW and flag the primary-reviewer ambiguity in the dashboard row.
| Bucket | Condition |
|---|---|
| INBOX-UNREVIEWED | my_last_review is null AND any_human_review is false — no human has reviewed yet |
| INBOX-REREVIEW | my_last_review.state ∈ {COMMENTED, CHANGES_REQUESTED} AND (last_commit_ts > my_last_review.submittedAt OR slack re-review signal after my review) |
| WAITING-ON-OTHERS | any_human_review true but my_last_review null — someone else owns it |
| DONE-BY-ME | my_last_review.state == APPROVED OR my review exists with no new activity since |
Only INBOX-UNREVIEWED and INBOX-REREVIEW appear in the dashboard. Drop the others; note their counts in the summary so the user knows the scan was exhaustive.
Sort INBOX-UNREVIEWED by posted_at ascending (oldest first = most painful for the author). Sort INBOX-REREVIEW by my_last_review.submittedAt ascending (oldest open feedback first).
Sections in this order:
🔔 REMIND-DUE — last message from you, ≥48h ago → ready to bump
| PR | Title | Last from you | Age |
|---|
⏳ REMIND-RECENTLY-PINGED — last from you, <48h → skip (cooldown)
| PR | Title | Last from you | Hours ago |
|---|
👀 YOUR-ACTION — team replied last → you need to respond
| PR | Title | Last message (≤120 chars, with author) | Notes |
|---|
📝 OWN-DRAFTS — your WIP, not yet posted for review
| PR | Title | Last commit | CI | Bucket | Suggested next step |
|---|
🧹 STALE — created >6w ago, no activity in 2+ weeks → needs disposition
| PR | Title | Age | Last activity | Bucket | Suggested disposition |
|---|
Stale buckets: WIP/abandoned, posted-but-ignored, reviewed-stuck-on-you, reviewed-stuck-on-team.
📥 INCOMING-UNREVIEWED — others' PRs with no human review yet → potential pick up
| PR | Author | Title | Posted | Age in channel |
|---|
🔁 INCOMING-REREVIEW — you reviewed, dev addressed → potential re-review
| PR | Author | Title | Your last review | New commits since | Re-review signal |
|---|
Excluded — other-repo PRs without a configured channel, plus Archived repo: N (repos: …).
Counts — WAITING-ON-OTHERS: N · DONE-BY-ME: N (silently-dropped buckets, for auditability).
End with the action menu:
Proceed?
(a) Bump REMIND-DUE threads
(b) Investigate YOUR-ACTION PRs with parallel sub-agents
(c) Walk through OWN-DRAFTS (decide: flip / finish / close)
(d) Walk through STALE PRs (decide: close / keep / hand off)
(e) Open INCOMING-UNREVIEWED for review (browser or sub-agent triage)
(f) Open INCOMING-REREVIEW with diff-since-my-review
(g) All of the above
(h) Cancel
STOP. No actions without explicit approval.
Eligibility is REMIND-DUE only. RECENTLY-PINGED is skipped — Phase 1 already filtered it; do not re-check here.
Post one thread reply per PR via slack_send_message with thread_ts=<parent_ts>. Exact message text — do not paraphrase:
friendly bump <!subteam^S096X6MCB0C>
Renders as friendly bump @smartcontract_core. The <!subteam^…> syntax is mandatory — plain @smartcontract_core does not trigger notifications (verified 2026-05-13). For the backend channel, swap to that channel's subteam ID or skip the tag per channel convention.
Confirm each post with its permalink.
For each draft, ask once (or in a small batch):
PR #<n> — <title> (last commit <X>w ago, CI <status>)
Bucket: <READY-TO-FLIP / NEEDS-WORK / DORMANT / SYNC-PR>
What would you like to do?
(1) Flip to Ready for Review + post via /post-pr-for-review
(2) Continue work locally (no action now)
(3) Close (with reason)
(4) Investigate first (defer to Phase 3)
(5) Skip for now
Execute the chosen disposition. For (1): gh pr ready <n> then invoke post-pr-for-review. For (3): gh pr close --comment "<reason>".
For each STALE PR:
PR #<n> — <title> (age <X>w, last activity <Y>w ago)
Bucket: <bucket>
What would you like to do?
(1) Close (with one-line reason)
(2) Mark "still working" — post "Still active — target date: <D>" comment
(3) Hand off / re-assign (you'll name the assignee)
(4) Convert to draft if not already
(5) Investigate first (defer to Phase 3)
(6) Skip
Execute. (1) gh pr close --comment. (3) gh pr edit --add-assignee. (4) gh pr ready --undo.
For INCOMING-UNREVIEWED:
gh pr view <n> --web link + a 2-line preview (changed-files count, primary language, linked issue/ticket from PR body).For INCOMING-REREVIEW:
Fetch diff since my last review:
gh pr view <n> --json reviews \
--jq '.reviews[] | select(.author.login=="<me>") | .commit.oid' | tail -1
gh pr diff <n> --color=never --commit-range <last_review_sha>..HEAD
Show filename list + line-count delta; quote the dev's "ready for re-review" message from the Slack thread; list my still-open inline review comments:
gh api repos/<o>/<r>/pulls/<n>/comments
filtered by user.login == me AND in_reply_to_id == null.
Per-PR offer: (i) open --web link to the "Files changed since" view, (ii) spawn sub-agent to verify the dev addressed each of my original comments and report mismatches, (iii) skip.
Never auto-approve, auto-comment, or auto-request-changes. The skill routes; the human reviews.
Dispatch one sub-agent per PR, in parallel. Each sub-agent:
gh pr view <n> --repo <owner>/<repo> --json reviewDecision,reviews,comments,statusCheckRollup,mergeable,mergeStateStatusgh api repos/<owner>/<repo>/pulls/<n>/comments (inline review comments)gh api repos/<owner>/<repo>/issues/<n>/comments (PR discussion)Sub-agent prompt template (self-contained):
You are investigating LI.FI PR <URL>. The user is the author. The team posted comments after the user's last reply; the user needs to decide what to do next.
1. Pull GitHub review state with the `gh` commands above.
2. Read this Slack thread: <paste detailed thread text>.
3. Summarise what the team is asking for and propose ONE concrete next step.
Be terse. Report under 300 words:
## PR #<n>
### Findings
- ...
### Suggested action
- ...
### Confidence: high | medium | low
Orchestrator consolidates all reports:
## Sub-agent findings — N PRs investigated
<each PR's findings>
Next?
(1) Implement the suggested actions one PR at a time (interactive)
(2) Implement all in parallel via sub-agents
(3) Just give me the list; I'll act manually
(4) Done
STOP. No code changes without per-PR approval.
Per PR:
gh pr checkout <n> in the right repo.Do not invoke /pr-ready here — that's the pre-create gate, not the per-iteration gate. Re-request review via gh pr edit --add-reviewer or just push and ping.