Merge step (f/g/h): retire todo system, retool pr-comments-review, rewrite ce-upstream-merge
Some checks failed
CI / pr-title (push) Has been cancelled
CI / test (push) Has been cancelled
Release PR / release-pr (push) Has been cancelled
Release PR / publish-cli (push) Has been cancelled

Applies triage doc 021 in full. Legacy file-based todo system is gone; the
two local workflows that depended on it are retooled around platform-
native task tracking and ce-code-review-style walkthrough patterns.

Deletions:
- commands/resolve_todo_parallel.md — obsolete; ce-pr-comments-review now
  orchestrates resolution inline
- commands/pr-comments-to-todos.md — replaced by ce-pr-comments-review skill
- skills/ce-upstream-merge/assets/merge-triage-template.md — template now
  lives inline in SKILL.md since decisions live in the task tracker

Retool:
- New skill skills/ce-pr-comments-review/SKILL.md: fetch PR comments,
  pressure-test each via validator agent, walk through with AskUserQuestion
  (Fix now / Clarify / Push back / Skip), dispatch ce-pr-comment-resolver
  for accepted fixes. Uses TaskCreate instead of todos/*.md.

Rewrite:
- skills/ce-upstream-merge/SKILL.md: drops the "create todos in todos/"
  pattern entirely. Phase 2 builds a platform-task decision set instead.
  Phase 3 walks through with AskUserQuestion. Phase 4 splits execution
  into 7 named checkpoints (b-h) so the user can inspect and course-
  correct mid-flight. Adds explicit "hidden conflicts" detection in
  Phase 1 (upstream rename of file local deleted, upstream deletion of
  file local depends on, structural refactors).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
John Lamb
2026-04-24 14:01:15 -05:00
parent 4d4586d4a8
commit 9b690499ab
5 changed files with 232 additions and 558 deletions

View File

@@ -1,199 +1,160 @@
---
name: ce-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.
description: "Incorporate upstream git changes into a local fork without losing local intent. Analyzes divergence, surfaces file-level and hidden conflicts, walks you through a per-finding decision (Accept remote / Keep local / Merge both / Keep deleted), then executes resolutions in a structured multi-step pass with checkpoints. 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.
Incorporate upstream changes into a local fork without losing local intent. The flow mirrors `ce-code-review`'s shape: analyze, walk through per-finding with the user, then execute with checkpoints.
## Prerequisites
Before starting, establish context:
Before starting:
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.
1. **Identify the guiding principle** — ask the user which local intent must survive. Every decision reads against this principle.
2. **Confirm remote**`git remote -v` should show the intended upstream.
3. **Fetch latest**`git fetch origin`.
## Phase 1: Analyze Divergence
## Phase 1: Analyze divergence
Gather the full picture before making any decisions.
**Run these commands:**
Gather the full picture:
```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 rev-list --count HEAD ^origin/main
git rev-list --count origin/main ^HEAD
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:**
File-level buckets:
```
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)
```
| Bucket | Meaning | Default action |
|--------|---------|----------------|
| **Remote-only** | Changed upstream, local untouched | Accept automatically |
| **Local-only** | Changed locally, upstream untouched | Keep as-is |
| **Both-changed** | Modified on both sides | Decision required |
## Phase 2: Create Triage Todos
**Also surface hidden conflicts.** File-level bucketing misses three common patterns that still matter:
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).
- **Upstream rename of a file local deleted** (remote-only deletion + remote-only creation under a new path, but local intent was to drop it). Check by diffing the set of deleted paths against any new creations at parallel paths.
- **Upstream deletion of a file local depends on** (remote-only deletion, but local skills/commands reference the deleted thing). Grep the local tree for names of upstream-deleted skills, agents, and commands.
- **Structural refactors** (massive renames, namespace changes, convention shifts) where every file "looks fine" individually but the project no longer fits together. Scan the remote-only diff for patterns that affect many files consistently.
**Process:**
Present the summary to the user with real counts, real examples, and flagged hidden conflicts.
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`
## Phase 2: Build the decision set
**Naming convention for merge triage todos:**
Create one platform task (`TaskCreate` in Claude Code; `update_plan` in Codex) per decision that actually needs user input:
```
{id}-pending-p2-merge-{component-name}.md
```
- Each both-changed file that survives on both sides (content conflict).
- Each local-kept / remote-deleted file (keep local with rename, or follow upstream's removal).
- Each hidden conflict surfaced in Phase 1.
Examples:
- `001-pending-p2-merge-marketplace-json.md`
- `002-pending-p2-merge-kieran-python-reviewer.md`
- `003-pending-p2-merge-workflows-review.md`
Do **not** create tasks for:
**Use parallel agents** to create triage docs when there are many conflicts (batch 4-6 at a time).
- Trivially-resolved both-changed cases (e.g., both-deleted — keep deleted).
- Pure remote-only files where local has no dependency on them (auto-accept).
- Pure local-only files untouched upstream (auto-keep).
**Announce when complete:**
**Task subject format:** `<short-filename>: <conflict shape>` (e.g., `ce-brainstorm/SKILL.md: content merge`). **Task description:** include file paths, both intents, a recommendation, and acceptance criteria. Keep it under ~40 lines so the walk-through stays readable.
```
Created N triage todos in todos/. Ready to review one-by-one.
```
Use parallel agents to draft descriptions when there are many decisions (batch 4-6 at a time). No file writes to `todos/` or anywhere else — the platform's task tracker is the source of truth.
## Phase 3: Triage (Review One-by-One)
Announce when the decision set is built: `Decision set: N items. Ready to walk through.`
Present each triage todo to the user for a decision. Follow the `/triage` command pattern.
## Phase 3: Walk-through (one decision per finding)
**For each conflict, present:**
Present each task one at a time using the platform's blocking question tool. In Claude Code, `AskUserQuestion` (call `ToolSearch` with `select:AskUserQuestion` first if not loaded); in Codex, `request_user_input`; in Gemini, `ask_user`; in Pi, `ask_user` via the `pi-ask-user` extension. Fall back to numbered options in chat only when no blocking tool is available.
```
---
Conflict X/N: [filename]
For each finding, show:
Category: [agent/command/skill/config]
Conflict Type: [content/modify-delete/add-add]
- The file (or group of files if related).
- The conflict shape (content / rename / modify-delete / hidden).
- Both intents in one sentence each.
- The recommendation and the reasoning tied to the guiding principle.
- The diff summary when it's short enough to be useful.
Remote intent: [what upstream changed and why]
Local intent: [what local changed and why]
Then ask:
Recommendation: [Accept remote / Keep local / Merge both / Keep deleted]
Reasoning: [why, referencing the guiding principle]
**Stem:** `How should the merge resolve this?`
---
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
```
**Options (match the decision vocabulary):**
**Use AskUserQuestion tool** for each decision with appropriate options.
1. `Accept remote` — take upstream's version as-is.
2. `Keep local` — preserve local as-is; discard upstream's change.
3. `Merge both` — combine; specify the merge shape (e.g., upstream structure + local content hunks).
4. `Keep deleted` — file stays gone regardless of upstream's continued version.
**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 findings** — e.g., all files in a renamed skill dir, or all files in a cohesive upstream refactor. Group decisions reduce fatigue and catch inconsistency.
**Group related files** when presenting (e.g., present all 7 dspy-ruby files together, not separately).
**Track progress:** show `X/N decided` before each question. Update the corresponding task's status to `completed` as decisions land.
**Track progress:** Show "X/N completed" with each presentation.
## Phase 4: Execute in checkpoints
## Phase 4: Execute Decisions
Never apply all decisions silently in one commit. Break into checkpoints so the user can inspect and course-correct mid-flight.
After all triage decisions are made, execute them in a structured order.
### Step 1: Create Working Branch
### Setup
```bash
git branch backup-local-changes # safety net
git checkout -b merge-upstream origin/main
git branch backup-local-<date> main # safety net
git checkout -b merge-upstream-<date> origin/main
```
### Step 2: Execute in Order
All subsequent work lands on the new branch. The backup branch is the escape hatch.
Process decisions in this sequence to avoid conflicts:
### Checkpoint sequence
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
1. **(b) Carry in local-only files** — `git checkout backup-local-<date> -- <file>` for each local-only addition. Exclude files that need special handling (e.g., a locally-modified agent that upstream renamed — port that in step c.5). Commit.
2. **(c) Rename / restructure to upstream convention** — move local custom agents to flat `ce-<name>.agent.md`, rename local custom skill dirs to `ce-<name>/`, delete upstream's renamed versions of locally-deleted items, update frontmatter `name:` fields. Commit.
3. **(d) Content merges** — apply each `Merge both` decision. Commit per-file or per-skill for clean review.
4. **(e) Ports across rename boundaries** — e.g., when upstream renamed a skill and local had modifications under the old path, port the modifications into the new path. Commit.
5. **(f) Deletions + retools** — apply `Keep deleted` and `Accept remote` deletion decisions. If a local skill's purpose survives but its mechanism was deprecated, retool it into the new pattern (don't just delete). Commit.
6. **(g) Reference sweep** — grep for old namespace references, old agent names, old slash commands; replace with new equivalents. Commit.
7. **(h) Metadata refresh** — recompute agent/skill counts in `README.md`, plugin.json descriptions, marketplace catalogs. Never hand-bump release-owned versions. Commit.
### Step 3: Verify
At each checkpoint, ask the user before proceeding: `Checkpoint N/7 complete. Proceed to <next>, hold for inspection, or revise?`
### Validate before merging
```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
bun run release:validate
bun test
grep -r "compound-engineering:" plugins/ | grep -v "docs/\|specs/\|\.md:" | head
```
### Step 4: Commit and Merge to Main
Expected: tests pass (or match baseline pre-merge state), release validator passes, no stray old-namespace agent refs remain in skill/agent/command content.
### Merge to main
Ask before merging: `All checkpoints applied and verified. Merge to main now?`. On yes:
```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
git merge merge-upstream-<date>
```
**Ask before merging to main** — confirm the user wants to proceed.
## Decision heuristics
## Decision Framework
When making recommendations, apply these heuristics:
| Signal | Recommendation |
|--------|---------------|
| Signal | Default 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 |
| Remote structural improvements + local content changes | Merge both: remote structure + local content |
| Both changed same content differently | Merge both: pick the side that serves the guiding principle; port the minimum set of hunks from the other |
| Remote renames what local deleted | Keep deleted (drop the renamed upstream version too) |
| File is metadata (counts, versions, descriptions) | Defer to the metadata-refresh checkpoint — recalculate from actual files |
| Upstream removed a skill local depends on (hidden conflict) | Fix local references AND accept the removal, OR retool local to not need the removed thing |
## Important Rules
## 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
- **No file-based state.** The decision set lives in the platform's task tracker, not in a `todos/` directory. Prior versions of this skill wrote `todos/NNN-*.md`; that pattern is retired.
- **Never auto-resolve content conflicts.** Every `Merge both` / `Keep local` / `Accept remote` call is the user's, not the agent's.
- **Checkpoint, don't mega-commit.** Seven small commits read better than one 400-file mega-commit.
- **Stage explicitly.** Prefer `git add <paths>` over `git add -A` so private files and stale scratch never sneak in.
- **Group related findings during walk-through.** A 7-file rename is one decision, not seven.
- **Metadata is derived, not merged.** Component counts, descriptions, and version strings are computed after all other work lands.
- **Preserve the guiding principle.** Every recommendation should reference it; every decision should be defensible against it.

View File

@@ -1,57 +0,0 @@
---
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)