x-manage-pr-merge-train
Merge-train automation: discovers, validates, and merges a sequence of PRs into develop in deterministic order. Supports --prs, --epic, and --pattern discovery modes with pre-merge validation and dry-run auditing.
- License 许可
- MIT
- 最近更新
- 2026-10-27
- Stars
- ★ 0
- Forks
- 1
01 前言 Front Matter
- name
- x-manage-pr-merge-train
- description
- Merge-train automation: discovers, validates, and merges a sequence of PRs into develop in deterministic order. Supports --prs, --epic, and --pattern discovery modes with pre-merge validation and dry-run auditing.
- allowed-tools
- Read, Write, Edit, Bash, Grep, Glob, Skill, Agent, TaskCreate, TaskUpdate
- argument-hint
- [--prs N,M,...] [--epic ID] [--pattern regex] [--max-parallel N] [--dry-run] [--resume]
- context-budget
- medium
- user-invocable
- true
- requires-capabilities
- []
02 资源文件 1
- 参考文档references/full-protocol.md13.1 KB
03 SKILL.md 正文
Global Output Policy
- Language: English ONLY.
- Tone: Technical, Direct, and Concise.
- Efficiency: Remove all conversational fillers. Start directly with technical information.
- Progress lines: Prefix with the current phase, e.g.
[Phase 0],[Phase 1],[Phase 2].
Triggers
/x-manage-pr-merge-train --epic 0042 --dry-run
/x-manage-pr-merge-train --prs 374,375,376
/x-manage-pr-merge-train --pattern "feat/task-0042-" --max-parallel 2
/x-manage-pr-merge-train --epic 0042 --resume
Parameters
| Flag | Type | Required | Default | Description |
|---|---|---|---|---|
--prs |
String (CSV integers) |
Mutually exclusive¹ | — | Literal comma-separated PR numbers; order preserved. |
--epic |
String (4-digit ID) |
Mutually exclusive¹ | — | Reads ai/epics/epic-{ID}/execution-state.json to resolve PRs. |
--pattern |
String (GitHub search regex) |
Mutually exclusive¹ | — | Enumerates open PRs via gh pr list --search. Sorted by createdAt. |
--max-parallel |
Integer |
Optional | 3 |
Max concurrent rebase workers in Phase 5 (1–8). |
--dry-run |
Flag | Optional | false |
Report plan and VETOs without merging. Exits after Phase 2. |
--resume |
Flag | Optional | false |
Resume interrupted train from plans/merge-train/{id}/state.json. |
¹ Exactly one of
--prs,--epic, or--patternmust be provided; zero or multiple emitsMODE_AMBIGUOUS.
Output Contract
| Artifact | Path | Description |
|---|---|---|
state.json |
plans/merge-train/{trainId}/state.json |
Full train lifecycle state; survives interruptions and supports --resume. |
report.md |
plans/merge-train/{trainId}/report.md |
Human-readable completion report: PRs merged, waves, errors, duration. |
worker-{pr}.log |
plans/merge-train/{trainId}/worker-{pr}.log |
Per-PR rebase worker result: {status, headSha, durationMs, reason?}. |
Train state transitions: PREPARATION → DISCOVERY → VALIDATION → SORTING → MERGING_BASE → WAVE_N_DISPATCHED → WAVE_N_RETURNED → VERIFYING → REPORTING → COMPLETED (or FAILED).
Error Envelope
| Code | Phase | Condition | Remediation |
|---|---|---|---|
MODE_AMBIGUOUS |
1 | 0 or 2+ mode flags | Provide exactly one of --prs, --epic, --pattern. |
EPIC_STATE_MISSING |
1 | --epic N but no execution-state.json |
Use --prs or --pattern. |
PR_CLOSED |
2 | state != "OPEN" |
Remove from train or reopen. |
PR_DRAFT |
2 | isDraft == true |
Mark PR as Ready for review. |
PR_BASE_MISMATCH |
2 | baseRefName != "develop" |
Rebase PR against develop. |
PR_NOT_APPROVED |
2 | reviewDecision != "APPROVED" |
Request review. |
PR_CI_FAILING |
2 | CI has FAILURE/ERROR check |
Fix CI. |
PR_MERGE_CONFLICT |
2 | mergeable == "CONFLICTING" |
Rebase manually. |
NEUTERED_PARALLEL |
3 | Code-file overlap detected (advisory, non-fatal) | MAX_PARALLEL=1 forced; train continues serially. |
MERGE_REJECTED_BY_PROTECTION |
4–5 | Branch protection blocks merge | Adjust protection rules. |
MERGE_POLL_TIMEOUT |
4–5 | PR did not reach MERGED within timeout |
Increase --merge-timeout-seconds or investigate CI. |
CODE_CONFLICT_NEEDS_HUMAN |
5 | Rebase conflict in non-golden file | Resolve manually → git rebase --continue → push → --resume. |
PUSH_LEASE_REJECTED |
5 | --force-with-lease rejected after retry |
Fetch + rebase manually → --resume. |
GOLDENS_REGEN_FAILED |
5 | GoldenFileRegenerator non-zero |
Diagnose build failure; see worker log. |
SMOKE_TEST_FAILED |
6 | mvn test fails after all merges |
Diagnose; worktree preserved for diagnosis. |
STATE_CONFLICT |
resume | No state.json or ambiguous train ID |
Start fresh or provide --train-id. |
Phase Overview (Rule 25 — Task Hierarchy)
Eight phases (Rule 25 REGRA-001, EPIC-0055). Each opens with a PRE gate + TaskCreate, closes with a POST/FINAL gate + TaskUpdate(completed). Phase 0 is exempted from gates (read-only setup). Full per-phase implementation in references/full-protocol.md.
0. PREPARATION → detect state file, parse args, validate mode flag (inline)
1. DISCOVERY → enumerate PRs for the chosen mode (inline + gh CLI)
2. VALIDATION → VETO check per PR — open, non-draft, approved, CI pass (inline)
3. SORTING → topological sort + overlap pre-check (inline)
4. BASE-MERGE → merge base wave into develop (x-merge-pr per PR)
5. REBASE-WAVE → parallel rebase workers per wave (subagents)
6. SMOKE-VERIFY → mvn test after all merges (inline)
7. REPORT → write report.md + cleanup (inline)
State machine: PREPARATION → DISCOVERY → VALIDATION → SORTING → MERGING_BASE → WAVE_N_DISPATCHED → WAVE_N_RETURNED → VERIFYING → REPORTING → COMPLETED (or FAILED).
<!-- phase-no-gate: read-only arg parsing and state-file detection; no artifact produced -->
Phase 0 - Preparation
Open a phase tracker (close with TaskUpdate(id: phase0TaskId, status: "completed") at end of setup):
TaskCreate(subject: "PR-MERGE › Phase 0 - Preparation", activeForm: "Preparing merge-train setup")
Resolve --resume (load existing state.json) vs fresh run. Validate exactly one of --prs, --epic, --pattern. Produce trainId (derived from mode + epoch). Errors: MODE_AMBIGUOUS, EPIC_STATE_MISSING, STATE_CONFLICT.
See references/full-protocol.md §Phase 0 for full implementation.
Persist interactiveMode to state file (EPIC-0068 — consumed by Stop hook enforce-continuous-flow.sh):
Skill(skill: "x-internal-update-status", args: "--file plans/merge-train/{trainId}/state.json --type merge-train --id {trainId} --field interactiveMode --value <interactive|non-interactive>")
Value: "interactive" when --interactive passed or CLAUDE_LEGACY_INTERACTIVE=1; otherwise "non-interactive" (Rule 20 default, EPIC-0061).
TaskUpdate(id: phase0TaskId, status: "completed")
Phase 1 - Discovery
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode pre --skill x-manage-pr-merge-train --phase Phase-1-Discovery")
TaskCreate(subject: "PR-MERGE › Phase 1 - Discovery", activeForm: "Discovering PRs for merge train")
Enumerate PRs per chosen mode:
--prs: parse CSV, preserve order.--epic: readai/epics/epic-{ID}/execution-state.json, collect merged story PR URLs.--pattern:gh pr list --search {pattern} --state open --json number,createdAt | sort by createdAt.
Write initial state.json at plans/merge-train/{trainId}/state.json with phase: DISCOVERY and the discovered PR list. Advance state to VALIDATION.
See references/full-protocol.md §Phase 1 for full implementation.
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode post --skill x-manage-pr-merge-train --phase Phase-1-Discovery --expected-artifacts plans/merge-train/{trainId}/state.json")
TaskUpdate(id: phase1TaskId, status: "completed")
Phase 2 - Validation
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode pre --skill x-manage-pr-merge-train --phase Phase-2-Validation")
TaskCreate(subject: "PR-MERGE › Phase 2 - Validation", activeForm: "Validating PR merge eligibility")
For each discovered PR, query gh pr view {N} --json state,isDraft,baseRefName,reviewDecision,mergeable,statusCheckRollup and apply VETO rules:
PR_CLOSED:state != OPENPR_DRAFT:isDraft == truePR_BASE_MISMATCH:baseRefName != developPR_NOT_APPROVED:reviewDecision != APPROVEDPR_CI_FAILING: any check withFAILUREorERRORPR_MERGE_CONFLICT:mergeable == CONFLICTING
If --dry-run: print VETO report and exit after Phase 2. Non-vetoed PRs advance to Phase 3.
See references/full-protocol.md §Phase 2 for full implementation.
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode post --skill x-manage-pr-merge-train --phase Phase-2-Validation --expected-artifacts plans/merge-train/{trainId}/state.json")
TaskUpdate(id: phase2TaskId, status: "completed")
Phase 3 - Sorting
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode pre --skill x-manage-pr-merge-train --phase Phase-3-Sorting")
TaskCreate(subject: "PR-MERGE › Phase 3 - Sorting", activeForm: "Sorting and overlap-checking PRs")
Topological sort validated PRs by createdAt (or explicit --prs order). Run file-overlap pre-check against each pair: if code-file overlap detected, emit NEUTERED_PARALLEL advisory and force MAX_PARALLEL=1 (serial). Update state.json with sorted order and parallelism decision.
See references/full-protocol.md §Phase 3 for full implementation.
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode post --skill x-manage-pr-merge-train --phase Phase-3-Sorting --expected-artifacts plans/merge-train/{trainId}/state.json")
TaskUpdate(id: phase3TaskId, status: "completed")
Phase 4 - Base Merge
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode pre --skill x-manage-pr-merge-train --phase Phase-4-BaseMerge")
TaskCreate(subject: "PR-MERGE › Phase 4 - Base Merge", activeForm: "Merging base PRs into develop")
For each PR in sorted order, invoke x-merge-pr:
Skill(skill: "x-merge-pr", args: "--pr {N} --strategy squash --target develop")
On MERGE_REJECTED_BY_PROTECTION or MERGE_POLL_TIMEOUT: abort train with state FAILED. Record failed PR in state.json. See references/full-protocol.md §Phase 4.
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode post --skill x-manage-pr-merge-train --phase Phase-4-BaseMerge --expected-artifacts plans/merge-train/{trainId}/state.json")
TaskUpdate(id: phase4TaskId, status: "completed")
Phase 5 - Rebase Wave
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode pre --skill x-manage-pr-merge-train --phase Phase-5-RebaseWave")
TaskCreate(subject: "PR-MERGE › Phase 5 - Rebase Wave", activeForm: "Rebasing PR wave onto develop")
Dispatch rebase workers in parallel (up to --max-parallel sibling agents per wave). Each worker:
- Creates worktree via
x-manage-worktrees. - Rebases branch onto develop HEAD.
- On
GOLDENS_REGEN_FAILED: runsGoldenFileRegeneratorand re-pushes. - On
CODE_CONFLICT_NEEDS_HUMAN: preserves worktree, marks PRFAILED, continues. - Writes result to
plans/merge-train/{trainId}/worker-{pr}.log.
Collect results; any non-fatal failure marks that PR skipped but continues the train.
See references/full-protocol.md §Phase 5 for full implementation.
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode post --skill x-manage-pr-merge-train --phase Phase-5-RebaseWave --expected-artifacts plans/merge-train/{trainId}/state.json")
TaskUpdate(id: phase5TaskId, status: "completed")
Phase 6 - Smoke Verify
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode pre --skill x-manage-pr-merge-train --phase Phase-6-SmokeVerify")
TaskCreate(subject: "PR-MERGE › Phase 6 - Smoke Verify", activeForm: "Running smoke verification after merges")
After all wave merges, run:
mvn test
On failure: set state FAILED, emit SMOKE_TEST_FAILED, preserve worktree for diagnosis.
On success: advance to Phase 7.
See references/full-protocol.md §Phase 6 for full implementation.
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode post --skill x-manage-pr-merge-train --phase Phase-6-SmokeVerify --expected-artifacts plans/merge-train/{trainId}/state.json")
TaskUpdate(id: phase6TaskId, status: "completed")
Phase 7 - Report
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode pre --skill x-manage-pr-merge-train --phase Phase-7-Report")
TaskCreate(subject: "PR-MERGE › Phase 7 - Report", activeForm: "Writing merge-train completion report")
Write plans/merge-train/{trainId}/report.md with: PRs merged, waves executed, errors encountered, total duration. Update state.json to phase: COMPLETED. Cleanup worktrees of successfully merged PRs via x-manage-worktrees cleanup.
See references/full-protocol.md §Phase 7 for full implementation.
Skill(skill: "x-internal-verify-phase-gates", model: "haiku", args: "--mode final --skill x-manage-pr-merge-train --phase Phase-7-Report --expected-artifacts plans/merge-train/{trainId}/report.md,plans/merge-train/{trainId}/state.json")
TaskUpdate(id: phase7TaskId, status: "completed")
Full Protocol
Full 8-phase workflow (Phase 0 Preparation → Phase 7 Report + Cleanup),
state.jsoncomplete schema, atomic-write pattern,--resumelogic, rebase-subagent canonical prompt, file-overlap precheck algorithm, and VETO evaluation rules inreferences/full-protocol.md.
04 同仓库更多 Skills
x-parallel-eval
Detects and classifies file-collision risks between work units (tasks, stories, or epic phases) before parallel execution. Reads ## File Footprint blocks produced by x-task-plan / x-story-plan, applies the parallelism-heuristics knowledge pack (hard / regen / soft categories + hotspot overrides), and emits a collision matrix + serialization recommendation in Markdown (default) or JSON.
parallelism-heuristics
Canonical catalog of file-collision heuristics for parallel task, story, and epic execution. Defines the File Footprint block format, the three Conflict Categories (hard / regen / soft), a hotspot list of high-contention paths, and the degrade-with-warning policy. Consumed by x-task-plan, x-story-plan, x-epic-map, x-parallel-eval, and x-dev-*-implement.
x-watch-pr-ci
Polls a PR's CI checks and Copilot review status, blocking until checks complete or timeout. Returns one of 8 stable exit codes (SUCCESS=0, CI_PENDING_PROCEED=10, CI_FAILED=20, TIMEOUT=30, PR_ALREADY_MERGED=40, NO_CI_CONFIGURED=50, PR_CLOSED=60, PR_NOT_FOUND=70). Writes a versioned state-file for session resume.
x-validate-docs
Documentation freshness gate: validates 6 dimensions (readme, api-specs, grpc-proto, adr, skill-docs, system-architecture) against code changes in a PR. Stack-aware — only validates targets declared/auto-detected from ProjectConfig.documentation.targets. Returns exit non-zero on staleness; produces structured report.
x-update-system-architecture
Incrementally updates docs/architecture/system.md after an epic completes. Appends new entries to the Decision Log (§11) using x-internal-write-report --append (dedup by ## ID: marker) and surgically inserts component/integration changes into sections 1-10 via Edit. Idempotent: re-running with the same epic produces a byte-identical system.md.
x-update-architecture
Incrementally updates the service architecture document with changes from architecture plans. Adds new components, integrations, flows, and ADR references without rewriting existing content. Use after implementation to keep architecture documentation current.