Editor's Note
post-pr-for-review
Post a `lifinance/contracts` pull request to `#dev-sc-review` and enable auto-merge (squash). Top-level message plus a thread reply tagging `@smartcontract_core`. Use when the user says "post PR for review", "send for review", "share for review", "post to dev-sc-review", or supplies a `lifinance/contracts` PR URL with review intent. Requires the Slack MCP server.
Install
npx skills add https://github.com/lifinance/contracts --skill post-pr-for-reviewPost PR for Review (Smart Contracts)
Posts a lifinance/contracts pull request to #dev-sc-review and (optionally) enables auto-merge. This is the smart-contract variant of post-pr-for-review and lives in the contracts repo. Other repos (backend, frontend, tooling) have their own routing skills — do not extend this one to handle them; surface the mismatch and stop.
Inputs
PR URL (optional). If omitted, resolve from the current branch via:
gh pr view --json url,title,body,number,headRefName,isDraft
If no PR exists, ask for the URL.
Scope guard
This skill posts to #dev-sc-review only. If the PR's owner/repo is not lifinance/contracts, stop and tell the user which skill or channel to use instead. Do not guess a backend / frontend channel.
Channel and tag
| Channel | Channel ID | Group tag |
|---|---|---|
#dev-sc-review | C088UJWC8PR | <!subteam^S096X6MCB0C> (renders @smartcontract_core) |
@smartcontract_core MUST be sent as <!subteam^S096X6MCB0C> — plain @… does not notify (verified 2026-05-13).
Post format
Top-level message (no prefix, no decorative emoji — channel is high-signal / low-noise):
<PR_URL> << <PR_TITLE>
Thread reply (sent immediately after the top-level):
<!subteam^S096X6MCB0C> please review 🙏
Workflow
1. Resolve PR
Parse owner/repo/pull/N from URL or gh pr view. Extract title, url, number, isDraft. Confirm owner/repo == lifinance/contracts; otherwise hit the scope guard above.
2. Pre-flight
Two blocking checks plus one workflow branch:
-
Unresolved review threads (blocking) — REST lacks
isResolved; use GraphQL:gh api graphql -f query=' query($owner:String!,$repo:String!,$num:Int!){ repository(owner:$owner,name:$repo){ pullRequest(number:$num){ reviewThreads(first:100){ nodes{ isResolved isOutdated comments(first:1){ nodes{ author{login} body url path } } } } } } }' \ -f owner=lifinance -f repo=contracts -F num=<N> \ --jq '.data.repository.pullRequest.reviewThreads.nodes | map(select(.isResolved == false and .isOutdated == false))'Group by author; CodeRabbit is
coderabbitai/coderabbitai[bot]. -
Failing CI (blocking,
gh pr checks <N>): block onFAILURE/CANCELLED/TIMED_OUT/ACTION_REQUIRED. Ignore any check whose name ends in(pull_request_review)— those are review-gated workflows that haven't fired yet; posting is what triggers them, so blocking would be circular. Match on the suffix only —version-control,audit-verification, and someprotect-*checks appear in both push and(pull_request_review)forms; only the latter is exempt. Surface unfamiliar checks; don't silently widen the allowlist. -
Draft status (workflow branch) — if drafted, offer
gh pr ready <N>; confirm first.
3. Gate on pre-flight
-
Unresolved threads OR failing CI → don't post. Summarize and stop:
Not posting to #dev-sc-review yet — please resolve these first: Unresolved review threads (N): • <author> (X): <url>, <url>… Failing CI: • <name>: <conclusion> — <details_url> Re-run after fixing.This skill does NOT auto-fix.
-
CI in progress, nothing failing → tell user, default to waiting.
-
Draft + clean → offer
gh pr ready <N>; confirm first. -
Clean + ready → step 4.
4. Confirm
Skip confirmation if the invoking message includes explicit intent ("post for review", "ship it", "send it", "post to dev-sc-review", "move to ready and push"). Re-asking is friction the user has cleared.
Otherwise show the planned top-level + thread reply text and wait for go.
Step 3's pre-flight is the real safety net; step 4 is content-check only.
5. Auto-merge
First, fetch merge state — --auto consumes immediately on a fully-approved + green PR, which would merge the PR before step 6 posts to Slack (leaving the team a "please review" message for an already-merged PR):
state=$(gh pr view <N> --repo lifinance/contracts \
--json mergeStateStatus --jq '.mergeStateStatus')
if [ "$state" = "CLEAN" ]; then
# PR would merge instantly under --auto. Skip and ask the user:
# "PR is already mergeable; not enabling auto-merge so reviewers can still see it. Merge now instead?"
else
gh pr merge <N> --repo lifinance/contracts --auto --squash
fi
Squash is LI.FI's default for lifinance/contracts.
Silently log + continue on:
- Already enabled → no-op.
- "Auto-merge is not enabled for this repository" → skip with a one-line note.
- Any other
gherror → surface verbatim, ask.
Opt-out: invoking message contains "without auto-merge" / "no auto-merge" / "manual merge" → skip.
6. Resolve channel + post
Channel ID: primary is C088UJWC8PR. Use slack_search_channels as a safety net to confirm the exact-name non-archived match if needed.
Top-level: slack_send_message with text = "<url> << <title>". Capture ts.
Thread reply: slack_send_message with thread_ts = <ts>, text = "<!subteam^S096X6MCB0C> please review 🙏".
7. Report
Posted to #dev-sc-review ✓ — auto-merge (squash) enabled
Failure modes
- MCP not connected → ask user to connect Slack MCP. Do NOT fall back to webhooks (wrong identity).
- Channel not found → surface search results; may have been renamed.
ghmissing / unauthenticated → ask for URL, skip pre-flight, warn.- GraphQL fails → fall back to
gh pr view --json reviewDecision,commentswith a warning that resolution state is unknown.
Variations
- "also @ <person>" → append
@<person>after the group tag in the thread reply. - "add context: <msg>" → append as a second thread reply, never the top-level.
- "quiet ping" → drop the 🙏; thread reply becomes
<!subteam^S096X6MCB0C> please review. Keep the subteam syntax — plain@smartcontract_coredoes not notify. - "without auto-merge" → skip step 5.
- Explicit channel override → use that channel; keep the post shape unless overridden too.
Why this design
Slack MCP posts as the human user, preserving thread-reply notifications and attribution — right etiquette for review channels. Webhook posting (used by audit-request-slack-relay) is intentionally NOT used here (wrong identity). No secrets stored; each teammate authenticates the MCP themselves.
The skill is intentionally scoped to lifinance/contracts → #dev-sc-review only. A multi-repo dispatcher (SC + backend + others) lives outside the contracts repo; mixing routing logic into this file invites the wrong-channel posts the routing rule was meant to prevent.