Receber por email
← Voltar para o catálogo

merge-pr

Token-efficient Claude Code workspace with parallel agents and persistent memory. Research → Plan → Implement → Validate workflow.

18estrelas
Atualizado há 3 meses

Ver no GitHub ↗

Como adicionar

/plugin marketplace add coalesce-labs/catalyst

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/merge-pr-coalesce-labs/svg)](https://www.skillteca.com.br/skills/merge-pr-coalesce-labs)

Skills relacionadas

Ver todas de Pesquisa e Web →

Alerta por categoria

Receba novas skills de Pesquisa e Web toda segunda

1 email curto, só com as skills novas de Pesquisa e Web. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Merge Pull Request

Safely merges a PR after comprehensive verification, with Linear integration and automated cleanup.

Prerequisites

# Project setup + orch-monitor daemon liveness (REQUIRED — Phase 6 consumes webhook events)
if [[ -f "${CLAUDE_PLUGIN_ROOT}/scripts/check-project-setup.sh" ]]; then
  "${CLAUDE_PLUGIN_ROOT}/scripts/check-project-setup.sh" || exit 1
fi

Branch Protection — Safety Rules

Read and follow the safety rules in "${CLAUDE_PLUGIN_ROOT}/references/merge-blocker-diagnosis.md" — specifically the "Safety Rules" section. Summary: NEVER use --admin, --force, or any flag that bypasses branch protection. Always resolve blockers legitimately or escalate with specifics.

Configuration

Read team configuration from .catalyst/config.json:

CONFIG_FILE=".catalyst/config.json"
[[ ! -f "$CONFIG_FILE" ]] && CONFIG_FILE=".claude/config.json"
TEAM_KEY=$(jq -r '.catalyst.linear.teamKey // "PROJ"' "$CONFIG_FILE")
TEST_CMD=$(jq -r '.catalyst.pr.testCommand // "make test"' "$CONFIG_FILE")

Process:

1. Identify PR to merge

If argument provided:

  • Use that PR number: /merge_pr 123

If no argument:

# Try current branch
gh pr view --json number,url,title,state,mergeable 2>/dev/null

If no PR on current branch:

gh pr list --limit 10 --json number,title,headRefName,state

Ask: "Which PR would you like to merge? (enter number)"

2. Get PR details

gh pr view $pr_number --json \
  number,url,title,state,mergeable,mergeStateStatus,\
  baseRefName,headRefName,reviewDecision

Extract:

  • PR number, URL, title
  • Mergeable status
  • Base branch (usually main)
  • Head branch (feature branch)
  • Review decision (APPROVED, REVIEW_REQUIRED, etc.)

3. Verify PR is open and mergeable

state=$(gh pr view $pr_number --json state -q .state)
mergeable=$(gh pr view $pr_number --json mergeable -q .mergeable)

If PR not OPEN:

❌ PR #$pr_number is $state

Only open PRs can be merged.

If not mergeable (CONFLICTING):

❌ PR has merge conflicts

Resolve conflicts first:
  gh pr checkout $pr_number
  git fetch origin $base_branch
  git merge origin/$base_branch
  # ... resolve conflicts ...
  git push

Exit with error.

4. Check if head branch is up-to-date with base

# Checkout PR branch
gh pr checkout $pr_number

# Fetch latest base
base_branch=$(gh pr view $pr_number --json baseRefName -q .baseRefName)
git fetch origin $base_branch

# Check if behind
if git log HEAD..origin/$base_branch --oneline | grep -q .; then
    echo "Branch is behind $base_branch"
fi

If behind:

# Auto-rebase
git rebase origin/$base_branch

# Check for conflicts
if [ $? -ne 0 ]; then
    echo "❌ Rebase conflicts"
    git rebase --abort
    exit 1
fi

# Push rebased branch
git push --force-with-lease

If conflicts during rebase:

❌ Rebase conflicts detected

Conflicting files:
  $(git diff --name-only --diff-filter=U)

Resolve manually:
  1. Fix conflicts in listed files
  2. git add <resolved-files>
  3. git rebase --continue
  4. git push --force-with-lease
  5. Run /catalyst-dev:merge-pr again

Exit with error.

5. Run local tests

Read test command from config:

test_cmd=$(jq -r '.catalyst.pr.testCommand // "make test"' .catalyst/config.json)

Execute tests:

echo "Running tests: $test_cmd"
if ! $test_cmd; then
    echo "❌ Tests failed"
    exit 1
fi

If tests fail:

❌ Local tests failed

Fix failing tests before merge:
  $test_cmd

Or skip tests (not recommended):
  /catalyst-dev:merge-pr $pr_number --skip-tests

Exit with error (unless --skip-tests flag provided).

6. Diagnose and resolve merge blockers — reactive PR lifecycle

Read and follow the full workflow in "${CLAUDE_PLUGIN_ROOT}/references/merge-blocker-diagnosis.md". The wake-up mechanism here is the canonical "Reactive PR lifecycle" pattern from monitor-events (Pattern 3, CTL-228) — a single wait-for that fires on any of: PR merged, PR closed, CI failure, review changes-requested, or push to the base branch. Each wake-up is paired with an authoritative gh api REST re-check; the event tells the agent what changed, gh api tells it the current truth.

Why a multi-event filter and not just github.pr.merged: most of the time between PR-create and PR-merge is spent on CI, review, and base-branch churn — not waiting on a clean merge to land. Subscribing only to the merge event means the agent learns nothing from a check failure or a changes-requested review until the 600-second timeout fires, at which point it falls back to REST polling via gh api. The disjunctive filter restores event-driven dispatch for those cases.

# Two-phase compliant cadence loop — see [[wait-for-github]]. The 600s timeout
# serves as a fallback cadence; the authoritative REST check runs on every wake-up.
REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
BASE_BRANCH=$(gh api "repos/${REPO}/pulls/${pr_number}" --jq '.base.ref')
ITER=0
MAX_ITER=20

while [ $ITER -lt $MAX_ITER ]; do
  ITER=$((ITER + 1))

  # Reactive multi-event subscription. wait-for is a no-op on event arrival;
  # on timeout we fall through to the authoritative re-check below. The
  # 600-second timeout is the fallback cadence when no events arrive (e.g.
  # daemon down).
  EVENT_JSON=$(catalyst-events wait-for \
    --filter '
      (.attributes."event.name" == "github.pr.merged" and .attributes."vcs.pr.number" == '"$pr_number"') or
      (.attributes."event.name" == "github.pr.closed" and .attributes."vcs.pr.number" == '"$pr_number"') or
      (.attributes."event.name" == "github.check_suite.completed"
         and (.body.payload.prNumbers // [] | index('"$pr_number"') != null)
         and (.attributes."cicd.pipeline.run.conclusion" == "failure" or .attributes."cicd.pipeline.run.conclusion" == "timed_out")) or
      (.attributes."event.name" == "github.pr_review.submitted"
         and .attributes."vcs.pr.number" == '"$pr_number"'
         and (.body.payload.state == "changes_requested"
              or (.body.payload.state == "commented" and (.body.payload.author.type // "") == "Bot"))) or
      (.attributes."event.name" == "github.push" and .attributes."vcs.ref.name" == "refs/heads/'"$BASE_BRANCH"'")
    ' \
    --timeout 600 || true)

  # MANDATORY authoritative REST re-check on every wake-up.
  STATE=$(gh api "repos/${REPO}/pulls/${pr_number}" \
    --jq 'if .merged then "MERGED" elif .state == "closed" then "CLOSED" else "OPEN" end' \
    2>/dev/null || echo "OPEN")
  if [ "$STATE" = "MERGED" ]; then break; fi
  if [ "$STATE" = "CLOSED" ]; then
    echo "❌ PR #$pr_number was closed without merging"
    exit 1
  fi

  EVENT=$(echo "$EVENT_JSON" | jq -r '.attributes."event.name" // ""')
  case "$EVENT" in
    github.check_suite.completed)
      # CI failed — diagnose via merge-blocker-diagnosis.md, push fix.
      ;;
    github.pr_review.submitted)
      # Bot reviewers (Codex, claude-code-review) are addressable inline;
      # humans require operator action. body.payload.author.type is "Bot" or "User".
      # Codex submits inline-thread reviews as state="commented", not
      # "changes_requested" — handle both via /catalyst-dev:review-comments,
      # which addresses the code AND resolves threads via the GraphQL
      # resolveReviewThread mutation.
      AUTHOR_TYPE=$(echo "$EVENT_JSON" | jq -r '.body.payload.author.type // "User"')
      if [ "$AUTHOR_TYPE" = "Bot" ]; then
        /catalyst-dev:review-comments "$pr_number"
      fi
      ;;
    github.push)
      gh pr update-branch "$pr_number" || true
      ;;
    "")
      # Timeout — gh api check above confirmed we're not merged.
      # Diagnose blockers per the reference doc.
      ;;
  esac
done

Why every wake-up runs gh api: if the orch-monitor daemon is down, no GitHub webhook events flow into the log and wait-for blocks until ti

Compartilhar X LinkedIn