Overview
This skill is used to analyze all changes in an upstream repository (such as the ant-design React version, ant-design/x React version) starting from a certain commit, filter out the PRs that need to be synced to a downstream port repository (such as the antdv-next Vue3 version, antdv-next/x Vue3 version), and output a priority-sorted sync table and a checklist template corresponding to each PR.
The current repository tracks by default ant-design/x, and the path mapping is:
packages/x→packages/xpackages/x-sdk→packages/x-sdkpackages/x-markdown→packages/x-markdownpackages/x-card→packages/x-cardpackages/x-skill→packages/x-skill
Supportsmulti-worker parallelmode: the main process is responsible for scheduling and aggregating reviews, and each worker independently handles the analysis of one upstream repository or sub-package without blocking each other.
主进程(调度 + 汇总)
├── worker-1: ant-design → packages/components
├── worker-2: ant-design-icons → packages/icons
├── worker-3: pro-components/table → packages/pro-table
└── worker-4: pro-components/form → packages/pro-form
↓ 各自独立 clone/分析,结果写入 results/
主进程:等待全部完成 → 合并 → 输出统一表格 + checklist
Step 0: Read the sync status (execute first)
Before doing anything, first check whether the downstream repository root directory contains .sync-upstream.json:
# 在下游仓库根目录执行
cat .sync-upstream.json
Case A: The file exists ✅
Read the last sync position,no need for the user to provide any parameters again。
First merge the two configuration files (if they exist):
.sync-upstream.json— team-shared, committed to git.sync-upstream.local.json— private to the current user, added to.gitignore, used to override local paths
Then determine the data source for each upstream according to the following priority:
| Priority | Condition | Behavior |
|---|---|---|
| 1️⃣ Best | After merging, local_path is valid and the directory exists |
Use the local repository directly, no network needed |
| 2️⃣ Automatic | local_path is empty or the path does not exist, and remote_url |
is available |
| 3️⃣ Fallback | Only the repo field (GitHub) is available |
Use the GitHub API |
When automatic cloning is triggered, inform the user:
🌐 The local repository is unavailable, cloning from
{remote_url}to a temporary directory, and it will be automatically cleaned up after the analysis is complete...
During normal resumption, inform the user:
📖 Sync record read, last synced to
a1b2c3d(2024-03-01), continuing the analysis from that point onward...
For the complete cloning and cleanup process, see
references/tmp-clone.md
Case B: The file does not exist ⚠️
First use, ask the user for the following information, thencreatethat file:
| Need to ask | Description |
|---|---|
| Upstream repository address | Local relative path (such as ../ant-design) or remote URL |
| Starting commit SHA | From which version to start tracking forward |
| Upstream repository name (optional) | Used for display; by default, take the last segment of the URL/path |
downstream.local_pathFixed write to"./"is sufficient, and the user does not need to provide it.
During initialization, the Skill also executes:
echo ".sync-upstream.local.json" >> .gitignore
echo ".sync-checklist-*.md" >> .gitignore
See
references/sync-state.mdfor the file format, local override mechanism, and read/write operations
Prerequisites
Mode detection (priority check)
Automatically select a mode based on the content provided by the user:
| User provides | Mode used |
|---|---|
Local repository path (/home/...、~/...、./...) |
🖥️ Local mode(git CLI, fastest) |
| Any Git remote URL (GitHub/GitLab/Gitea/self-hosted) | 🔄 Auto-clone mode(clone to tmp, delete when done) |
GitHub only owner/repo name |
🌐 Remote mode(GitHub API, fallback option) |
Priority:Local > Auto-clone > Remote API
Auto-clone supports all Git platforms; you only need to provide the URL once and write it to
.sync-upstream.json, and it will be handled automatically afterward. Seereferences/tmp-clone.md。
Parameter list
| Parameter | Local mode | Auto-clone mode | Remote API mode |
|---|---|---|---|
| Upstream repository | Local path | Any Git URL | owner/repo |
| Downstream repository | Local path | Local path | owner/repo |
start_commit |
commit SHA | commit SHA | commit SHA |
github_token |
Not required | Not required | Optional, recommended |
max_prs |
Default 50 | Default 50 | Default 50 |
Parallel-related parameters(can be written to the .sync-upstream.json of settings field):
| Parameter | Default value | Description |
|---|---|---|
parallel |
true |
Whether to enable multi-worker parallelism |
max_workers |
4 |
Maximum number of concurrent workers; excess tasks wait in queue |
results_dir |
/tmp/sync-results-{timestamp} |
Shared results directory; each worker writes {worker_id}.json, and the main process reads and merges them uniformly |
On first use, the Skill will write the upstream URL to .sync-upstream.json, and it does not need to be provided again afterward.
If the user does not provide a starting commit,first check whether Step 0 has already read it from .sync-upstream.json ; if not, ask the user., if none, ask the user.
Step 1: Main process scheduling (parallel mode entry point)
1.1 Build the worker task list
Read all upstream configurations from .sync-upstream.json and split tasks by worker_granularity :
Split by downstream subpackage (one worker per packages entry):
ant-design → worker-0(upstream: ., downstream: packages/components)
ant-design-icons → worker-1(upstream: packages/icons-vue, downstream: packages/icons)
pro-components/table → worker-2(upstream: packages/table, downstream: packages/pro-table)
pro-components/form → worker-3(upstream: packages/form, downstream: packages/pro-form)
This is the finest granularity; each downstream subpackage runs in parallel independently without blocking one another.
Multiple workers for the same upstream (such as pro-components) willreuse the same clone, without pulling repeatedly.
1.2 Concurrency control
总任务数 = N
实际并发 = min(settings.max_workers, N) # 不超过实际任务数,默认 4
超出并发上限的任务进入等待队列
有 worker 完成后立即从队列取出下一个执行
Progress is printed to the main process stdout in real time, making it easy for the user to understand the status of each worker.
1.3 Start workers
Each worker receives the following input and independently executes Steps 2-4:
{
"worker_id": "worker-C",
"upstream_name": "pro-components",
"remote_url": "https://github.com/ant-design/pro-components.git",
"local_path": null,
"upstream_path": "packages/table",
"downstream_path": "packages/pro-table",
"last_synced_commit": "c3d4e5f",
"results_dir": "/tmp/sync-results-1712345678/",
"max_prs": 50
}
After the main process starts all workers, itsuspends and waits, and after all are complete (or timed out), proceeds to Step 5 for aggregation.
For the worker's internal execution flow, see
references/worker.md
Step 2 (inside the worker): Get the commit list
🖥️ Local / Auto-clone mode (recommended)
# $UPSTREAM_DIR = upstream 的 local_path(相对路径)或 auto-clone 的 tmp 路径
git -C $UPSTREAM_DIR log <start_commit>..HEAD \
--pretty=format:"%H|%h|%s|%ad|%an" \
--date=short \
--extended-regexp \
--grep="^(fix|feat|feature|perf|revert)(\(.+\))?!?:|^Merge pull request #"
For complete commands and batch scripts, see
references/local-git.md→ Section 1 & 7
🌐 Remote mode
Get all commits after start_commit via the GitHub API:
GET https://api.github.com/repos/{upstream_repo}/commits
?sha=HEAD # 从最新往前,需要客户端过滤
&per_page=100
Filtering strategy:
- keep only
typethat arefixorfeatconventional commits - commit message pattern matching:
fix(component): ...feat(component): ...fix: .../feature: ...- PR merge commit:
Merge pull request #xxx
see
references/github-api.mdfor API call examples and pagination handling
Step 3 (in Worker): associate PR info & check sync status
🖥️ Local mode
Extract the PR number from the commit message, and check whether downstream has already synced:
# 检查下游是否已同步某个 PR
git -C $DOWNSTREAM_DIR log --oneline --grep="12345"
see
references/local-git.md→ Section 3 & 5
🌐 Remote mode
For each commit, associate the PR in the following ways:
GET https://api.github.com/repos/{upstream_repo}/commits/{sha}/pulls
Extract from the PR:
- PR number, title, URL
- Labels (used to determine priority)
- Involved file paths (to infer affected components)
- Linked issues in the PR body
- Merge time
Step 4 (in Worker): analyze impact scope
3.1 Get the list of files changed by the commit
🖥️ Local / Auto-clone mode:
git -C $UPSTREAM_DIR diff-tree --no-commit-id -r <sha> --name-only
🌐 Remote mode:GET /repos/{owner}/{repo}/pulls/{number}/files
3.2 Path mapping: upstream files → downstream subpackages
Read .sync-upstream.json for that upstream in packages mapping table, convert upstream changed file paths into downstream monorepo subpackage paths.
Mapping logic:
upstream 改动文件路径
↓
匹配 packages[].upstream_path 前缀
↓
替换为 packages[].downstream_path
↓
输出:下游子包 + 组件名
Example(pro-components → antdv-next monorepo):
上游改动文件 packages 映射 下游定位
─────────────────────────────────────────────────────────────────────────────
packages/table/src/Table.tsx → upstream: packages/table → packages/pro-table / Table
downstream: packages/pro-table
packages/form/src/Form.tsx → upstream: packages/form → packages/pro-form / Form
downstream: packages/pro-form
components/button/index.tsx → upstream: . → packages/components / Button
downstream: packages/components
site/docs/intro.md → (无匹配,标记为文档,P3)
When there is no packages field(upstream is a single-package repo, and downstream is also a single package):
- infer the component name directly by the
components/{name}/rule, without path conversion
3.3 Component name inference
After the path is determined, extract the component name from the subpath:
components/{name}/→{Name}(first letter capitalized)src/{Name}.tsx→{Name}site//docs/→ documentation category, priority is automatically loweredscripts//.github//__tests__/only → skip or P3
see
references/local-git.md→ Section 4
Step 5 (in Worker): evaluate sync priority
Score automatically according to the following rules to generate the priority:
Priority rules table
| Priority | Marker | Condition |
|---|---|---|
| P0 Urgent | 🔴 | Labels contain Security; title contains crash/security/XSS/data loss |
| P1 High | 🟠 | Bug fix affecting core components (Button/Form/Table/Select/Input); Labels contain bug+important |
| P2 Medium | 🟡 | Ordinary bug fix; feature enhancement; UX optimization; Labels contain feat |
| P3 Low | 🟢 | Documentation update; style tweak; deprecation warning; TypeScript type fix |
| Skip | ⚪ | React-specific only (e.g. ReactNode、React.forwardRef -specific changes); SSR-exclusive; test files only |
Sync difficulty assessment
| Difficulty | Condition |
|---|---|
| Low | Pure logic/style fix, no JSX-specific syntax |
| Medium | Requires React→Vue3 syntax conversion (props/emit/slots) |
| High | Involves deep Hooks refactoring, Context API, React-specific lifecycle |
Step 6 (in Worker): write results
After each worker completes analysis, write the result to results_dir/{worker_id}.json:
{
"worker_id": "worker-C",
"upstream_name": "pro-components",
"upstream_path": "packages/table",
"downstream_path": "packages/pro-table",
"latest_commit": "d4e5f6a7b8c9",
"latest_commit_short": "d4e5f6a",
"latest_tag": "v2.7.0",
"analyzed_at": "2024-03-01T12:05:00Z",
"prs": [
{
"pr_number": 8800,
"title": "fix(table): sort not reset on filter change",
"type": "fix",
"commit": "c3d4e5f",
"components": ["ProTable"],
"priority": "P1",
"difficulty": "Medium",
"upstream_url": "https://github.com/ant-design/pro-components/pull/8800",
"status": "pending"
}
],
"error": null
}
If a worker encounters an error (clone failure, network timeout, etc.), write to error field,prs is an empty array; after receiving it, the main process separately marks that worker as failed without affecting other workers' results.
Step 7 (main process): aggregate output + automatically create branches
7.1 Merge all worker results
Read results_dir/ all {worker_id}.jsonunder it, sort uniformly by priority, generate a summary table and .sync-report.md。
7.2 Automatically create sync branches (all PRs except Skip)
For all non-Skip PRs, the main process executes one by one:
每个 PR → git checkout -b sync/{upstream-name}-{pr-number} origin/{base_branch}
→ 写入 .sync-checklist-{upstream-name}-{pr-number}.md
→ git commit
→ git checkout {base_branch}
Branch naming:sync/{upstream-name}-{pr-number}, e.g. sync/ant-design-12345
Base branch:settings.base_branch, default main
Existing branchesare automatically skipped and not overwritten, protecting work in progress.
See the full implementation and git commands in
references/branch-management.md
7.3 Output format
5.1 Summary table
Output a Markdown table, sorted from high to low priority:
## 📋 同步 PR 汇总表
> 上游仓库: ant-design/ant-design
> 分析起点: commit `a1b2c3d` (2024-01-15)
> 分析范围: 从起点到最新,共 X 个 fix/feat PR
> 生成时间: YYYY-MM-DD
| 优先级 | 上游仓库 | PR # | 类型 | 标题 | 上游路径 → 下游子包 | 涉及组件 | 同步难度 | 状态 | 链接 |
| ------- | ---------------- | ------ | ---- | ---------------------- | --------------------------------------- | -------- | -------- | ---- | ------ |
| 🔴 P0 | ant-design | #12345 | fix | fix: Button crash | `.` → `packages/components` | Button | Low | ⬜ | [链接] |
| 🟠 P1 | pro-components | #8800 | fix | fix: ProTable sort bug | `packages/table` → `packages/pro-table` | ProTable | Medium | ⬜ | [链接] |
| 🟡 P2 | ant-design | #12280 | feat | feat: Input clearIcon | `.` → `packages/components` | Input | Low | ⬜ | [链接] |
| 🟡 P2 | ant-design-icons | #560 | feat | feat: add new icons | `packages/icons-vue` → `packages/icons` | - | Low | ⬜ | [链接] |
| 🟢 P3 | ant-design | #12200 | docs | docs: Form examples | `.` → `packages/components` | Form | - | ⬜ | [链接] |
| ⚪ Skip | ant-design | #12100 | fix | fix: SSR hydration | - | - | - | 跳过 | [链接] |
Status values:⬜ 待同步 / 🔄 进行中 / ✅ 已完成 / ❌ 不适用
With multiple upstreams, the table is sorted uniformly by priority; the upstream repository column makes it easy to quickly identify the source.
5.2 Per-PR Checklist template
For eachnon-SkipPR, generate the following template:
---
## ✅ 同步任务:#{PR编号} - {PR标题}
**优先级**: {🔴/🟠/🟡/🟢} {P0/P1/P2/P3}
**类型**: {fix/feat/docs}
**上游 PR**: https://github.com/{upstream_repo}/pull/{编号}
**上游 Commit**: `{sha}`
**涉及组件**: {组件名}
**同步难度**: {Low/Medium/High}
**关联 Issue**: {issue 链接,若有}
### 📖 变更摘要
{PR body 或 commit message 的简要总结}
### 🔍 Pre-sync 分析
- [ ] 阅读上游 PR 完整内容和 review 评论
- [ ] 确认 antdv-next 中是否存在相同问题/缺失相同功能
- [ ] 查看上游变更的文件列表,评估 Vue3 适配工作量
- [ ] 检查是否有相关联的其他 PR 需要一起同步
### 🛠️ 实现步骤
- [ ] 创建功能分支:`sync/ant-design-#{PR编号}`
- [ ] 实现对应的 fix/feat(参考上游代码逻辑)
- [ ] 处理 React→Vue3 差异(见下方注意事项)
- [ ] 编写/更新单元测试
- [ ] 更新组件文档(若有 API 变更)
- [ ] 本地运行测试套件确认无回归
### ⚠️ React→Vue3 差异注意事项
- [ ] `children` / `ReactNode` → `slots`
- [ ] `React.forwardRef` → `defineExpose` / `ref`
- [ ] `useEffect` → `watchEffect` / `onMounted`
- [ ] `className` → `class`
- [ ] `onChange` → `@update:value` 或 `@change`(确认 emits 声明)
- [ ] Context API → `provide` / `inject`
- [ ] `React.cloneElement` → 无直接等价,需重构
### 📦 提交与发布
- [ ] 创建 antdv-next PR,标题格式:`[sync] fix(Button): xxx (#上游PR编号)`
- [ ] PR 描述中链接上游 PR
- [ ] Code Review 通过(至少 1 人)
- [ ] CI 全部通过
- [ ] Merge 到主分支
- [ ] 确认是否需要单独发布 patch 版本
Usage example
Scenario A: First initialization (monorepo, multiple upstreams)
User input:
帮我追踪 antdv-next(/home/user/antdv-next)的上游同步,
上游有三个仓库:
- ant-design: https://github.com/ant-design/ant-design.git → packages/components
- ant-design-icons: https://github.com/ant-design/ant-design-icons.git(packages/icons-vue)→ packages/icons
- pro-components: https://github.com/ant-design/pro-components.git(packages/table → packages/pro-table,packages/form → packages/pro-form)
从各自的最新 tag 开始
Claude execution flow:
- Check
.sync-upstream.json→ does not exist, enter initialization - Create the configuration file as described by the user, writing the three upstreams'
remote_urlandpackagesmappings - Clone the three upstreams to tmp in turn, taking each current HEAD as
last_synced_commit - Clean up tmp, inform the user that configuration is complete
Scenario B: Resume sync (configuration already exists)
User input:
同步仓库
Claude execution flow:
- Read
.sync-upstream.json→ find the three upstreams and their respectivelast_synced_commit - For each upstream in turn (or in parallel): clone to tmp → analyze new commits → follow
packagesmappings to locate downstream subpackages - Merge the output into one summary table, grouped by upstream and sorted by priority
- Output a checklist for each PR, marking the affected downstream subpackage paths
- Update the three upstreams' respective
last_synced_commit, clean up tmp
Step 8 (main process): Update the sync state file
After each analysis is completed, write thelatest upstream commit analyzed this time back to .sync-upstream.json:
# 获取上游当前 HEAD commit
LATEST=$(git -C $UPSTREAM_DIR rev-parse HEAD)
LATEST_SHORT=$(git -C $UPSTREAM_DIR rev-parse --short HEAD)
LATEST_TAG=$(git -C $UPSTREAM_DIR describe --tags --abbrev=0 2>/dev/null || echo "")
NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
Update last_synced_commit to $LATEST,last_synced_at to $NOW。
Inform the user:
✅ Sync state has been updated: next time just say "continue sync", no need to provide the commit SHA.
See
references/sync-state.mdfor the complete read/write operations and multi-upstream support
Notes
- The unauthenticated GitHub API rate limit is 60 requests/hour and 5000 requests/hour when authenticated; users are advised to provide a token
- Some commits may not be associated with a PR (direct push); such commits are listed separately for manual judgment
- "Skip" PRs are still listed, making it easier to manually review whether they really do not apply
- If the number of PRs > 50, it is recommended to process in batches or split by time period
.sync-upstream.jsonAdd to version control so the team can share sync progress;.sync-upstream.local.jsonAdd to.gitignore, storing personal local paths without interfering with each other- See the detailed API call example in
references/github-api.md - Priority rules can be adjusted according to project requirements, see
references/priority-rules.md