Agent skill

open-integration-pr

Create an integration PR for the merge-prs. Reads pr_order_file JSON, generates a rich PR body with per-PR details, arch-lens diagrams, and carried-forward Closes #N references. Closes all collapsed PRs with a comment after creation. Use inside the merge-prs after all PRs have been merged into the integration branch.

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/open-integration-pr

SKILL.md

Open Integration PR

Read pr_order_file JSON produced by analyze-prs, generate a rich PR description (per-PR details, complexity tags, merge outcomes, optional audit verdict), generate 1–3 arch-lens diagrams, carry forward Closes #N/Fixes #N references from original PR bodies so linked issues auto-close on merge, create the integration PR via gh pr create --body-file, close each collapsed PR with a comment referencing the new PR, and output pr_url=<url>.

Arguments

/autoskillit:open-integration-pr {integration_branch} {base_branch} {pr_order_file} [audit_verdict] [conflict_report_paths]
  • integration_branch — integration branch name (e.g. pr-batch/pr-merge-20250228-143052)
  • base_branch — PR target branch (e.g. main)
  • pr_order_file — absolute path to JSON produced by analyze-prs
  • audit_verdict (optional) — GO, NO GO, or empty string when audit was skipped
  • conflict_report_paths (optional) — comma-separated list of absolute paths to conflict resolution report files, produced by resolve-merge-conflicts. When provided and non-empty, embed a "Conflict Resolution Decisions" section in the PR body.

When to Use

  • Called by merge-prs after all PRs have been merged into the integration branch
  • Invoked via run_skill as the final step before CI watch

Critical Constraints

NEVER:

  • Create files outside temp/open-integration-pr/ (except the temp body file for gh pr create --body-file)
  • Modify any source code
  • Fail the pipeline if gh is unavailable or not authenticated — output pr_url= (empty) and exit successfully
  • Close original PRs before the integration PR is successfully created

ALWAYS:

  • Check gh auth status before attempting any GitHub operations
  • Output pr_url=<url> on the last output line (empty string when GitHub unavailable)
  • Carry forward ALL Closes #N and Fixes #N lines found in original PR bodies
  • Use gh pr create --body-file (never inline body via --body)

Workflow

Step 1: Parse Arguments

Parse four positional args: integration_branch, base_branch, pr_order_file, audit_verdict (last one may be absent or empty string). Parse the optional fifth positional argument conflict_report_paths (may be absent or empty string). Split on , to get a list of paths; filter out any empty strings. Store as conflict_report_path_list.

Step 2: Read pr_order_file

Read the JSON file. Extract: prs array (each: number, title, branch, complexity, additions, deletions, overlap_with_pr_numbers, files_changed). Also read base_branch from JSON as confirmation. Store the PR list as pr_list.

Step 3: Fetch Closes/Fixes References from Original PR Bodies

For each PR in pr_list:

bash
gh pr view {number} --json body -q .body 2>/dev/null

Extract every line matching (Closes|Fixes|Resolves)\s+#\d+ (case-insensitive). Deduplicate across all PRs. Store as closing_refs (list of strings like Closes #42). Skip gracefully if gh is unavailable — closing_refs remains empty.

Step 4: Get Changed Files

bash
git diff --name-only {base_branch}..{integration_branch}
git diff --diff-filter=A --name-only {base_branch}..{integration_branch}
git diff --diff-filter=M --name-only {base_branch}..{integration_branch}

Store as changed_files, new_files, modified_files.

Step 4b: Load Conflict Resolution Reports

  • If conflict_report_path_list is empty: skip — set conflict_resolution_table = "".
  • For each path in conflict_report_path_list:
    • Read the file.
    • Extract the ## Per-File Resolution Decisions table (all lines from the | File | header through the last table row).
  • Concatenate all extracted tables (one per report, separated by a blank line if multiple).
  • Store as conflict_resolution_table.

This step is skipped gracefully if any path is missing — log a warning and exclude that file.

Step 4c: Partition Files by Domain

bash
python3 -c "
from autoskillit.execution.pr_analysis import partition_files_by_domain
import json, sys
files = json.loads(sys.argv[1])
result = partition_files_by_domain(files)
print(json.dumps(result))
" '["path/to/file.py", ...]'

Pass changed_files as a JSON array argument. Store the parsed dict as domain_partitions. Skip entirely and set domain_partitions = {} if changed_files is empty.

Step 4d: Fetch Domain Diffs (parallel)

For each domain name D in domain_partitions where domain_partitions[D] is non-empty, run the following in parallel (issue all Bash calls in a single message):

bash
git diff {base_branch}..{integration_branch} -- {space-separated list of files in domain D}

Store results as domain_diffs: dict[str, str] mapping domain name → diff text. If a domain's diff text exceeds 12 000 characters, truncate to the first 12 000 characters and append \n... [truncated — diff exceeds 12 000 chars]. Domains with empty diffs are removed from domain_diffs.

Step 4e: Identify PRs per Domain

For each domain D in domain_partitions, find every PR in pr_list whose files_changed list intersects with domain_partitions[D].

python
domain_pr_numbers = {
    domain: [
        pr["number"]
        for pr in pr_list
        if set(pr.get("files_changed", [])) & set(domain_partitions[domain])
    ]
    for domain in domain_partitions
}

Store as domain_pr_numbers: dict[str, list[int]].

Step 4f: Fetch Domain Commits (parallel)

For each domain D in domain_diffs (domains that actually have diff content), run in parallel (all Bash calls in a single message):

bash
git log {base_branch}..{integration_branch} --oneline -- {space-separated files in domain D}

Store as domain_commits: dict[str, list[str]] (each entry is a list of "sha message" strings). Empty results are stored as empty lists.

Step 4g: Run Parallel Domain Analysis Subagents

For each domain D in domain_diffs, spawn a Task subagent (model: sonnet) in a single parallel message. Issue all Task calls in a single message to maximize parallelism. Skip domains with no diff content (not in domain_diffs) — do not spawn subagents for them.

Each subagent receives a prompt with:

  • The domain name
  • The list of files changed in the domain
  • The diff content (already truncated at 12 000 chars)
  • The PR numbers and titles for PRs touching this domain (look up titles from pr_list)
  • The commit one-liners for the domain

The subagent is instructed to return ONLY a JSON object with this exact shape:

json
{
  "domain": "Server/MCP Tools",
  "summary": "3-4 sentence description of what changed and why it matters",
  "key_changes": ["concise description of change 1", "concise description of change 2"],
  "pr_numbers": [42, 47],
  "commit_count": 5
}

Parse each subagent's output as JSON. If parsing fails for a domain, log a warning and omit that domain from domain_summaries. Store the collected results as domain_summaries: list[dict].

The 7 canonical domain names are: Server/MCP Tools, Pipeline/Execution, Recipe/Validation, CLI/Workspace, Skills, Tests, Core/Config/Infra.

Step 5: Select Arch-Lens Lenses

Spawn a subagent (Task tool, model: sonnet) with changed_files and the same lens menu as open-pr. Instruct it to return 1–3 lens names using the same development lens guard.

Step 6: Generate Arch-Lens Diagrams

For each selected lens, follow this exact sequence:

CRITICAL: Do NOT output any prose status text between lens iterations. After completing all sub-steps for one lens (including mermaid extraction and validation), immediately begin sub-step 1 (Write the PR context file) for the next lens. Progress announcements like "Diagram generated. Now calling X:" create end_turn windows that cause stochastic session termination.

1. Write the PR context to a file using the Write tool:

  • Path: temp/open-integration-pr/pr_arch_lens_context_{YYYY-MM-DD_HHMMSS}.md
  • Content: The following PR context block, with placeholders filled in:
markdown
# PR Context — Changed Files

This diagram is for a Pull Request. Focus the diagram on the areas of the codebase affected by these changes. Do not create a generic whole-project diagram.

## New files (use ★ prefix on these nodes):
{list of new_files from Step 4, or "None"}

## Modified files (use ● prefix on these nodes):
{list of modified_files from Step 4, or "None"}

## Instructions:
- Focus exploration and the diagram on the architectural areas these files belong to
- Use `★` prefix on nodes representing new files/components
- Use `●` prefix on nodes representing modified files/components
- Leave unchanged components unmarked (include them only if needed for context/connectivity)
- The diagram should help PR reviewers understand the architectural impact of these specific changes

2. Immediately call the Skill tool to load the arch-lens skill (e.g., /autoskillit:arch-lens-module-dependency). The loaded skill will read the PR context file written in step 1 above.

3. Follow the loaded skill's instructions to explore the codebase and generate the diagram.

The arch-lens skills write their output to temp/arch-lens-{lens-name}/ (relative to the current working directory). After each skill runs, read the generated markdown file and extract the mermaid code block(s).

After extracting the mermaid block, inspect its content for ★ or ● characters:

  • If the block contains at least one ★ or ● → add it to validated_diagrams.
  • If the block contains neither → discard this diagram; do not add it to the list.

Step 7: Compose PR Body

Write to temp/open-integration-pr/pr_body_{timestamp}.md. (relative to the current working directory)

markdown
## Integration Summary

Collapsed {N} PRs into `{integration_branch}` targeting `{base_branch}`.

## Merged PRs

| # | Title | Complexity | Additions | Deletions | Overlaps |
|---|-------|-----------|-----------|-----------|---------|
| #{number} | {title} | {complexity} | +{additions} | -{deletions} | {overlap_with_pr_numbers or "—"} |
...

{If domain_summaries is non-empty:}
## Domain Analysis

{For each entry in domain_summaries (ordered by domain name):}
### {entry.domain}

{entry.summary}

**Key changes:**
{For each item in entry.key_changes:}
- {item}

**Contributing PRs:** {comma-separated #{N} for each N in entry.pr_numbers, or "—" if empty}
**Commits:** {entry.commit_count} commit(s)

{If audit_verdict is non-empty:}
## Audit

**Verdict:** {audit_verdict}

{If conflict_resolution_table is non-empty:}
## Conflict Resolution Decisions

The following files had merge conflicts that were automatically resolved during pipeline integration.

{conflict_resolution_table}

{If validated_diagrams non-empty:}
## Architecture Impact

{For each validated diagram:}
### {Lens Name} Diagram

```mermaid
{diagram content}

{For each item in closing_refs:} {Closes #N}

🤖 Generated with Claude Code via AutoSkillit


### Step 8: Check GitHub Availability

```bash
gh auth status 2>/dev/null

If exit code non-zero: output pr_url= and exit successfully.

Step 9: Create Integration PR

bash
gh pr create \
  --base {base_branch} \
  --head {integration_branch} \
  --title "Integration: collapsed PRs #{numbers} into {base_branch}" \
  --body-file temp/open-integration-pr/pr_body_{timestamp}.md

{numbers} = comma-separated PR numbers (e.g., #42, #47, #51). Capture the new PR URL as new_pr_url. Extract the PR number from the URL as new_pr_number.

Step 10: Close Original PRs

For each PR in pr_list:

bash
gh pr close {number} --comment "Collapsed into integration PR #{new_pr_number} ({new_pr_url})"

Continue even if individual close operations fail (log warning, do not exit).

Output

pr_url = {new_pr_url}

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results