Merge upstream v2.40.0 with local fork additions preserved
Incorporates 163 upstream commits (origin/main) while preserving all local skills, agents, and commands. Metadata descriptions updated to reflect actual component counts (30 agents, 56 skills, 7 commands). file-todos/SKILL.md merged with both upstream command rename and local assessment fields. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
199
plugins/compound-engineering/skills/upstream-merge/SKILL.md
Normal file
199
plugins/compound-engineering/skills/upstream-merge/SKILL.md
Normal file
@@ -0,0 +1,199 @@
|
||||
---
|
||||
name: upstream-merge
|
||||
description: This skill should be used when incorporating upstream git changes into a local fork while preserving local intent. It provides a structured workflow for analyzing divergence, categorizing conflicts, creating triage todos for each conflict, reviewing decisions one-by-one with the user, and executing all resolutions. Triggers on "merge upstream", "incorporate upstream changes", "sync fork", or when local and remote branches have diverged significantly.
|
||||
---
|
||||
|
||||
# Upstream Merge
|
||||
|
||||
Incorporate upstream changes into a local fork without losing local intent. Analyze divergence, categorize every changed file, triage conflicts interactively, then execute all decisions in a single structured pass.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting, establish context:
|
||||
|
||||
1. **Identify the guiding principle** — ask the user what local intent must be preserved (e.g., "FastAPI pivot is non-negotiable", "custom branding must remain"). This principle governs every triage decision.
|
||||
2. **Confirm remote** — verify `git remote -v` shows the correct upstream origin.
|
||||
3. **Fetch latest** — `git fetch origin` to get current upstream state.
|
||||
|
||||
## Phase 1: Analyze Divergence
|
||||
|
||||
Gather the full picture before making any decisions.
|
||||
|
||||
**Run these commands:**
|
||||
|
||||
```bash
|
||||
# Find common ancestor
|
||||
git merge-base HEAD origin/main
|
||||
|
||||
# Count divergence
|
||||
git rev-list --count HEAD ^origin/main # local-only commits
|
||||
git rev-list --count origin/main ^HEAD # remote-only commits
|
||||
|
||||
# List all changed files on each side
|
||||
git diff --name-only $(git merge-base HEAD origin/main) HEAD > /tmp/local-changes.txt
|
||||
git diff --name-only $(git merge-base HEAD origin/main) origin/main > /tmp/remote-changes.txt
|
||||
```
|
||||
|
||||
**Categorize every file into three buckets:**
|
||||
|
||||
| Bucket | Definition | Action |
|
||||
|--------|-----------|--------|
|
||||
| **Remote-only** | Changed upstream, untouched locally | Accept automatically |
|
||||
| **Local-only** | Changed locally, untouched upstream | Keep as-is |
|
||||
| **Both-changed** | Modified on both sides | Create triage todo |
|
||||
|
||||
```bash
|
||||
# Generate buckets
|
||||
comm -23 <(sort /tmp/remote-changes.txt) <(sort /tmp/local-changes.txt) > /tmp/remote-only.txt
|
||||
comm -13 <(sort /tmp/remote-changes.txt) <(sort /tmp/local-changes.txt) > /tmp/local-only.txt
|
||||
comm -12 <(sort /tmp/remote-changes.txt) <(sort /tmp/local-changes.txt) > /tmp/both-changed.txt
|
||||
```
|
||||
|
||||
**Present summary to user:**
|
||||
|
||||
```
|
||||
Divergence Analysis:
|
||||
- Common ancestor: [commit hash]
|
||||
- Local: X commits ahead | Remote: Y commits ahead
|
||||
- Remote-only: N files (auto-accept)
|
||||
- Local-only: N files (auto-keep)
|
||||
- Both-changed: N files (need triage)
|
||||
```
|
||||
|
||||
## Phase 2: Create Triage Todos
|
||||
|
||||
For each file in the "both-changed" bucket, create a triage todo using the template at [merge-triage-template.md](./assets/merge-triage-template.md).
|
||||
|
||||
**Process:**
|
||||
|
||||
1. Determine next issue ID: `ls todos/ | grep -o '^[0-9]\+' | sort -n | tail -1`
|
||||
2. For each both-changed file:
|
||||
- Read both versions (local and remote)
|
||||
- Generate the diff: `git diff $(git merge-base HEAD origin/main)..origin/main -- <file>`
|
||||
- Analyze what each side intended
|
||||
- Write a recommendation based on the guiding principle
|
||||
- Create todo: `todos/{id}-pending-p2-merge-{brief-name}.md`
|
||||
|
||||
**Naming convention for merge triage todos:**
|
||||
|
||||
```
|
||||
{id}-pending-p2-merge-{component-name}.md
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `001-pending-p2-merge-marketplace-json.md`
|
||||
- `002-pending-p2-merge-kieran-python-reviewer.md`
|
||||
- `003-pending-p2-merge-workflows-review.md`
|
||||
|
||||
**Use parallel agents** to create triage docs when there are many conflicts (batch 4-6 at a time).
|
||||
|
||||
**Announce when complete:**
|
||||
|
||||
```
|
||||
Created N triage todos in todos/. Ready to review one-by-one.
|
||||
```
|
||||
|
||||
## Phase 3: Triage (Review One-by-One)
|
||||
|
||||
Present each triage todo to the user for a decision. Follow the `/triage` command pattern.
|
||||
|
||||
**For each conflict, present:**
|
||||
|
||||
```
|
||||
---
|
||||
Conflict X/N: [filename]
|
||||
|
||||
Category: [agent/command/skill/config]
|
||||
Conflict Type: [content/modify-delete/add-add]
|
||||
|
||||
Remote intent: [what upstream changed and why]
|
||||
Local intent: [what local changed and why]
|
||||
|
||||
Recommendation: [Accept remote / Keep local / Merge both / Keep deleted]
|
||||
Reasoning: [why, referencing the guiding principle]
|
||||
|
||||
---
|
||||
How should we handle this?
|
||||
1. Accept remote — take upstream version as-is
|
||||
2. Keep local — preserve local version
|
||||
3. Merge both — combine changes (specify how)
|
||||
4. Keep deleted — file was deleted locally, keep it deleted
|
||||
```
|
||||
|
||||
**Use AskUserQuestion tool** for each decision with appropriate options.
|
||||
|
||||
**Record decisions** by updating the triage todo:
|
||||
- Fill the "Decision" section with the chosen resolution
|
||||
- Add merge instructions if "merge both" was selected
|
||||
- Update status: `pending` → `ready`
|
||||
|
||||
**Group related files** when presenting (e.g., present all 7 dspy-ruby files together, not separately).
|
||||
|
||||
**Track progress:** Show "X/N completed" with each presentation.
|
||||
|
||||
## Phase 4: Execute Decisions
|
||||
|
||||
After all triage decisions are made, execute them in a structured order.
|
||||
|
||||
### Step 1: Create Working Branch
|
||||
|
||||
```bash
|
||||
git branch backup-local-changes # safety net
|
||||
git checkout -b merge-upstream origin/main
|
||||
```
|
||||
|
||||
### Step 2: Execute in Order
|
||||
|
||||
Process decisions in this sequence to avoid conflicts:
|
||||
|
||||
1. **Deletions first** — Remove files that should stay deleted
|
||||
2. **Copy local-only files** — `git checkout backup-local-changes -- <file>` for local additions
|
||||
3. **Merge files** — Apply "merge both" decisions (the most complex step)
|
||||
4. **Update metadata** — Counts, versions, descriptions, changelogs
|
||||
|
||||
### Step 3: Verify
|
||||
|
||||
```bash
|
||||
# Validate JSON/YAML files
|
||||
cat <config-files> | python3 -m json.tool > /dev/null
|
||||
|
||||
# Verify component counts match descriptions
|
||||
# (skill-specific: count agents, commands, skills, etc.)
|
||||
|
||||
# Check diff summary
|
||||
git diff --stat HEAD
|
||||
```
|
||||
|
||||
### Step 4: Commit and Merge to Main
|
||||
|
||||
```bash
|
||||
git add <specific-files> # stage explicitly, not -A
|
||||
git commit -m "Merge upstream vX.Y.Z with [guiding principle] (vX.Y.Z+1)"
|
||||
git checkout main
|
||||
git merge merge-upstream
|
||||
```
|
||||
|
||||
**Ask before merging to main** — confirm the user wants to proceed.
|
||||
|
||||
## Decision Framework
|
||||
|
||||
When making recommendations, apply these heuristics:
|
||||
|
||||
| Signal | Recommendation |
|
||||
|--------|---------------|
|
||||
| Remote adds new content, no local equivalent | Accept remote |
|
||||
| Remote updates content local deleted intentionally | Keep deleted |
|
||||
| Remote has structural improvements (formatting, frontmatter) + local has content changes | Merge both: remote structure + local content |
|
||||
| Both changed same content differently | Merge both: evaluate which serves the guiding principle |
|
||||
| Remote renames what local deleted | Keep deleted |
|
||||
| File is metadata (counts, versions, descriptions) | Defer to Phase 4 — recalculate from actual files |
|
||||
|
||||
## Important Rules
|
||||
|
||||
- **Never auto-resolve "both-changed" files** — always triage with user
|
||||
- **Never code during triage** — triage is for decisions only, execution is Phase 4
|
||||
- **Always create a backup branch** before making changes
|
||||
- **Always stage files explicitly** — never `git add -A` or `git add .`
|
||||
- **Group related files** — don't present 7 files from the same skill directory separately
|
||||
- **Metadata is derived, not merged** — counts, versions, and descriptions should be recalculated from actual files after all other changes are applied
|
||||
- **Preserve the guiding principle** — every recommendation should reference it
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
status: pending
|
||||
priority: p2
|
||||
issue_id: "XXX"
|
||||
tags: [upstream-merge]
|
||||
dependencies: []
|
||||
---
|
||||
|
||||
# Merge Conflict: [filename]
|
||||
|
||||
## File Info
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **File** | `path/to/file` |
|
||||
| **Category** | agent / command / skill / config / other |
|
||||
| **Conflict Type** | content / modify-delete / add-add |
|
||||
|
||||
## What Changed
|
||||
|
||||
### Remote Version
|
||||
|
||||
[What the upstream version added, changed, or intended]
|
||||
|
||||
### Local Version
|
||||
|
||||
[What the local version added, changed, or intended]
|
||||
|
||||
## Diff
|
||||
|
||||
<details>
|
||||
<summary>Show diff</summary>
|
||||
|
||||
```diff
|
||||
[Relevant diff content]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Recommendation
|
||||
|
||||
**Suggested resolution:** Accept remote / Keep local / Merge both / Keep deleted
|
||||
|
||||
[Reasoning for the recommendation, considering the local fork's guiding principles]
|
||||
|
||||
## Decision
|
||||
|
||||
**Resolution:** *(filled during triage)*
|
||||
|
||||
**Details:** *(specific merge instructions if "merge both")*
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Resolution applied correctly
|
||||
- [ ] No content lost unintentionally
|
||||
- [ ] Local intent preserved
|
||||
- [ ] File validates (JSON/YAML if applicable)
|
||||
Reference in New Issue
Block a user