بنقرة واحدة
auto-merge
Merge a GitHub PR when all gates pass; uses Slack HIGH_RISK gate by default
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Merge a GitHub PR when all gates pass; uses Slack HIGH_RISK gate by default
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Dispatch a background worker with role-templated prompt and auto-populated collision fences
Comprehensive system health monitoring — checks agent performance, database, Kafka topics, pattern discovery, and service status across the ONEX platform
Orchestrate a Claude Code agent team to autonomously work a Linear epic across multiple repos
Run DoD evidence checks against a ticket contract and generate a verification receipt
Autonomous per-ticket pipeline that chains ticket-work, local-review, PR creation, CI watching, PR review loop, integration verification gate, and auto-merge into a single unattended workflow with Slack notifications and policy guardrails
Full autonomous audit-debug-fix loop for all dashboard pages — Playwright recon, parallel systematic-debug, fix, PR, Linear ticket, re-audit, iterate until clean. Supports local and cloud targets with optional post-fix redeployment.
| name | auto-merge |
| description | Merge a GitHub PR when all gates pass; uses Slack HIGH_RISK gate by default |
Merge a GitHub PR after posting a Slack HIGH_RISK gate. A human must reply "merge" to proceed. Silence does NOT consent — this gate requires explicit approval. Exit when PR is merged, held, or timed out.
Announce at start: "I'm using the auto-merge skill to merge PR #{pr_number}."
Implements: OMN-2525
/auto-merge 123 org/repo
/auto-merge 123 org/repo --strategy merge
/auto-merge 123 org/repo --gate-timeout-hours 48
/auto-merge 123 org/repo --no-delete-branch
CDQA gates must pass before any merge proceeds. This requirement applies on all invocation paths — whether called from ticket-pipeline or directly.
When invoked from ticket-pipeline: CDQA gates run in Phase 5.5 before this skill is
dispatched. The gate log is written to ~/.claude/skill-results/{context_id}/cdqa-gate-log.json.
When invoked directly (not from ticket-pipeline): this skill MUST run the CDQA gates itself before executing the merge mutation.
1. Read: ~/.claude/skill-results/{context_id}/cdqa-gate-log.json
If record exists with overall=PASS or overall=bypassed AND pr_number matches:
→ skip re-run, proceed to Step 1
If no matching record:
→ run all 3 CDQA gates (see @_lib/cdqa-gate/helpers.md)
→ BLOCK result: post HIGH_RISK bypass gate, await operator reply
→ BLOCK + held/timeout: exit with status: held
→ all PASS or bypassed: proceed to Step 1
There is no --skip-cdqa flag. Bypassing CDQA requires the explicit Slack bypass
protocol documented in @_lib/cdqa-gate/helpers.md. Any attempt to invoke auto-merge
without CDQA gates passing (or a recorded bypass) must exit with status: error and
message: "CDQA gates not passed — run contract-compliance-check and verify CI gates".
Timeout model: gate_timeout_hours is a single shared wall-clock budget for the entire flow (Steps 2 + 4 combined). A wall-clock start time is recorded on entry; each poll checks elapsed time against this budget. If the budget is exhausted in either phase, the skill exits with status: timeout.
The merge readiness check depends on the current ONEX tier (see @_lib/tier-routing/helpers.md):
FULL_ONEX Path:
from omniclaude.nodes.node_git_effect.models import GitOperation, ModelGitRequest
request = ModelGitRequest(
operation=GitOperation.PR_VIEW,
repo=repo,
pr_number=pr_number,
json_fields=["mergeable", "mergeStateStatus", "reviewDecision",
"statusCheckRollup", "latestReviews"],
)
result = await handler.pr_view(request)
STANDALONE / EVENT_BUS Path:
${CLAUDE_PLUGIN_ROOT}/_bin/pr-merge-readiness.sh --pr {pr_number} --repo {repo}
# Returns: { ready, mergeable, ci_status, review_decision, merge_state_status, blockers }
Poll CI readiness (check every 60s until mergeStateStatus == "CLEAN"; consumes from the shared gate_timeout_hours budget):
mergeable and mergeStateStatus, log both fields:
[auto-merge] poll cycle {N}: mergeable={mergeable} mergeStateStatus={mergeStateStatus}
mergeStateStatus == "CLEAN": exit poll loop, proceed to gatemergeStateStatus == "DIRTY": exit immediately with status: error, message: "PR has merge conflicts -- resolve before retrying"mergeStateStatus == "BEHIND", "BLOCKED", "UNSTABLE", "HAS_HOOKS", or "UNKNOWN": continue pollinggate_timeout_hours elapsed): exit with status: timeout, message: "CI readiness poll timed out -- mergeStateStatus never reached CLEAN"Post HIGH_RISK Slack gate (see message format below).
Poll for Slack reply (check every 5 minutes; this phase shares the same gate_timeout_hours budget started in Step 2):
status: heldstatus: timeoutgh Exception) The merge mutation always uses gh pr merge directly -- this is an explicit exception
to the tier routing policy. Rationale: the merge is a thin CLI call (single mutation, no
parsing of output needed). There is no benefit to routing through node_git_effect.pr_merge()
for this operation.
gh pr merge {pr_number} --repo {repo} --{strategy} {--delete-branch if delete_branch}
This exception is documented and intentional. All other PR operations (view, list, checks) use tier-aware routing.
After a successful merge:
ticket_id is available in context — passed by ticket-pipeline):
if ticket_id:
try:
mcp__linear-server__save_issue(id=ticket_id, state="Done")
except Exception as e:
print(f"[auto-merge] Warning: Could not mark {ticket_id} as Done: {e}")
# Non-blocking: merge already succeeded; do not fail the skill
This is a belt-and-suspenders step. The primary path (ticket-pipeline Phase 6)
also marks the ticket Done. The linear-close-on-merge GitHub Actions workflow
(.github/workflows/linear-close-on-merge.yml) runs unconditionally on every PR
merge to main/develop, ensuring ticket closure even when the pipeline session has
ended (simultaneous closes from multiple paths are safe — Linear state updates are idempotent).Ticket ID resolution order:
--ticket-id OMN-XXXX argumentOMN-XXXX pattern (fallback if --ticket-id not provided)
(branch name extraction: git branch --show-current | grep -ioE '(OMN|omn)-[0-9]+' | head -1 | tr '[:lower:]' '[:upper:]'; only reliable when session is checked out on the PR branch — returns empty string if HEAD is detached)[HIGH_RISK] auto-merge: Ready to merge PR #{pr_number}
Repo: {repo}
PR: {pr_title}
Strategy: {strategy}
Branch: {branch_name}
All gates passed:
CI: passed
PR Review: approved (or changes resolved)
Reply "merge" to proceed. Silence = HOLD (this gate requires explicit approval).
Gate expires in {gate_timeout_hours}h.
Output contract: ModelSkillResult from omnibase_core.models.skill
Note: This contract reference is behavioral guidance for the LLM executing this skill. Runtime validation not yet implemented.
Write to: ~/.claude/skill-results/{context_id}/auto-merge.json
| Field | Value |
|---|---|
skill_name | "auto-merge" |
status | One of the canonical string values: "success", "gated", "error" (see mapping below) |
extra_status | Domain-specific status string (see mapping below) |
run_id | Correlation ID |
repo | Repository slug (org/repo) |
pr_number | PR number |
ticket_id | Linear ticket ID (e.g. "OMN-3262") or null |
extra | {"merge_commit": str, "strategy": str, "ticket_close_status": str} |
Note on
context_id: Prior schema versions includedcontext_idas a top-level field. This field is not part ofModelSkillResult— it belongs to the file path convention (~/.claude/skill-results/{context_id}/auto-merge.json). Consumers should derive context from the file path, not fromcontext_idin the result body.
Status mapping:
| Current status | Canonical status (string value) | extra_status |
|---|---|---|
merged | "success" (EnumSkillResultStatus.SUCCESS) | "merged" |
held | "gated" (EnumSkillResultStatus.GATED) | "held" |
timeout | "error" (EnumSkillResultStatus.ERROR) | "timeout" |
error | "error" (EnumSkillResultStatus.ERROR) | null |
Behaviorally significant extra_status values:
"merged" → ticket-pipeline treats as SUCCESS; clears ledger, updates Linear to Done"held" → ticket-pipeline treats as GATED; pipeline exits with held state (non-terminal), awaits human "merge" reply to resume"timeout" → ticket-pipeline treats as ERROR; merge gate expired — retryable with a new pipeline runPromotion rule for extra fields: If a field appears in 3+ producer skills, open a ticket to evaluate promotion to a first-class field. If any orchestrator consumer (epic-team, ticket-pipeline) branches on extra["x"], that field MUST be promoted.
Example result:
{
"skill_name": "auto-merge",
"status": "success",
"extra_status": "merged",
"pr_number": 123,
"repo": "org/repo",
"ticket_id": "OMN-3262",
"run_id": "pipeline-1709856000-OMN-3262",
"extra": {
"merge_commit": "abc1234",
"strategy": "squash",
"ticket_close_status": "closed"
}
}
ticket_id: The Linear ticket identifier closed in Step 6 (e.g. "OMN-3262"), or null if no ticket was identified.
extra["ticket_close_status"] values:
"closed": mcp__linear-server__save_issue succeeded; ticket marked Done"skipped": No ticket_id could be resolved — explicit arg absent and branch-name extraction returned empty"failed": save_issue call raised an exception; merge still succeeded (non-blocking)null: Step 6 was not reached (skill exited before merge — status is gated, error)auto-merge.shBash wrapper for programmatic invocation of this skill.
#!/usr/bin/env bash
set -euo pipefail
# auto-merge.sh — wrapper for the auto-merge skill
# Usage: auto-merge.sh <PR_NUMBER> <REPO> [--strategy squash|merge|rebase] [--gate-timeout-hours N] [--no-delete-branch]
PR_NUMBER=""
REPO=""
STRATEGY="squash"
GATE_TIMEOUT_HOURS="24"
DELETE_BRANCH="true"
TICKET_ID=""
while [[ $# -gt 0 ]]; do
case "$1" in
--strategy) STRATEGY="$2"; shift 2 ;;
--gate-timeout-hours) GATE_TIMEOUT_HOURS="$2"; shift 2 ;;
--no-delete-branch) DELETE_BRANCH="false"; shift ;;
--ticket-id) TICKET_ID="$2"; shift 2 ;;
-*) echo "Unknown flag: $1" >&2; exit 1 ;;
*)
if [[ -z "$PR_NUMBER" ]]; then PR_NUMBER="$1"; shift
elif [[ -z "$REPO" ]]; then REPO="$1"; shift
else echo "Unexpected argument: $1" >&2; exit 1
fi
;;
esac
done
if [[ -z "$PR_NUMBER" || -z "$REPO" ]]; then
echo "Usage: auto-merge.sh <PR_NUMBER> <REPO> [options]" >&2
exit 1
fi
exec claude --skill onex:auto-merge \
--arg "pr_number=${PR_NUMBER}" \
--arg "repo=${REPO}" \
--arg "strategy=${STRATEGY}" \
--arg "gate_timeout_hours=${GATE_TIMEOUT_HOURS}" \
--arg "delete_branch=${DELETE_BRANCH}" \
${TICKET_ID:+--arg "ticket_id=${TICKET_ID}"}
| Invocation | Description |
|---|---|
/auto-merge 123 org/repo | Interactive: merge PR 123 with default HIGH_RISK gate (24h timeout) |
/auto-merge 123 org/repo --strategy merge | Interactive: use merge commit strategy |
Skill(skill="onex:auto-merge", args="123 org/repo --gate-timeout-hours 48") | Programmatic: composable invocation from orchestrator |
auto-merge.sh 123 org/repo --no-delete-branch | Shell: direct invocation, keep branch after merge |
PR merge readiness checks use tier-aware backend selection:
| Tier | Readiness Check | Merge Execution |
|---|---|---|
FULL_ONEX | node_git_effect.pr_view() | gh pr merge (explicit exception) |
STANDALONE | _bin/pr-merge-readiness.sh | gh pr merge (explicit exception) |
EVENT_BUS | _bin/pr-merge-readiness.sh | gh pr merge (explicit exception) |
Merge execution exception: The actual gh pr merge call is always direct -- it is a
thin mutation (single API call, no output parsing). Routing it through node_git_effect
adds complexity without benefit. This is the only exception to the tier routing policy.
Tier detection: see @_lib/tier-routing/helpers.md.
ticket-pipeline skill (invokes auto-merge after cdqa_gate Phase 5.5 passes)pr-watch skill (runs before auto-merge; Phase 5 in ticket-pipeline)contract-compliance-check skill (CDQA Gate 1, OMN-2978)_lib/cdqa-gate/helpers.md (CDQA gate protocol, bypass flow, result schema — OMN-3189)slack-gate skill (LOW_RISK/MEDIUM_RISK/HIGH_RISK gate primitives)_bin/pr-merge-readiness.sh -- STANDALONE merge readiness backend_lib/tier-routing/helpers.md -- tier detection and routing helpers