Files
aerologic-app/.claude/skills/sync-air-cargo/SKILL.md
YANG JIANKUAN 5b217ab032 feat(sync-air-cargo): 以 Synced-From trailer 记录同步点,同步后自动在 air-cargo 本地提交
- 默认区间模式:基线取 air-cargo 最近的 Synced-From,目标为 main,内容取自提交对象
- 无记录时按内容反推基线(仅预览,apply 须 --base 确认),每次预览做基线校验
- 新增三方校验,列出将覆盖的 air-cargo 侧独立修改;分支/工作区/祖先关系保护
- --worktree 同步未提交变更且不推进同步点;提交信息仅「<Label> <日期>」+ trailer,不 push
- 新增 config(main → feature/hefei,air-cargo 位于项目根目录)
- 排除清单补充 .mcp.json、.claude.*、CLAUDE.local.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:20:55 -07:00

71 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: sync-air-cargo
description: 将 aerologic-app 的变更以文件级 cp/rm 方式同步到项目根目录下的 air-cargo/ 仓库并在其本地提交(不 push)——两者是同一份源码的两个独立 git 仓库副本,分别推送到不同的远程地址。同步点记录在 air-cargo 提交信息的 Synced-From trailer 中,自动从上次同步点同步到 main 最新提交(覆盖已提交未 push、已 push 的变更),也支持只同步未提交的工作区变更。只做文件复制/删除,不对内容做任何二次编辑或转换。每当用户提到"同步到 air-cargo"、"同步到另一个仓库/项目"、"推送/复制到 cargo 项目"、"两个项目要保持一致"、"把某几个 commit 同步过去",或者在 aerologic-app 里改完代码后问要不要同步/推送到另一个仓库时,应主动使用此 skill,而不是手动逐个 cp 文件。
---
# 同步变更到 air-cargo
## 背景
`aerologic-app` 和 `air-cargo` 是同一份项目源码的两个独立 git 仓库副本,分别推送到不同的远程仓库地址。日常开发只在 `aerologic-app` 中进行,完成后把变更同步到 `air-cargo` 并在本地提交,**push 由用户自己做**。
- **位置**:`air-cargo` 在 aerologic-app 根目录下(`/Users/tim/Development/Projects/aerologic-app/air-cargo/`),已在 aerologic-app 的 `.gitignore` 中忽略
- **分支映射**(`config` 文件):aerologic-app `main` → air-cargo `feature/hefei`。air-cargo 的 `develop` 是 2023 年的旧快照,不能往上同步;当前分支不是 `feature/hefei` 时脚本直接报错
- **不参与同步**:`CLAUDE.md` / `CLAUDE.local.md`、`.claude/` 目录、根目录 `.claude.*`(如 `.claude.local.md`)与 `.mcp.json`(Claude Code 的配置/记忆),不复制也不删除。air-cargo 中不应存在任何 Claude / Agent 相关文件,其本地 `.git/info/exclude` 已屏蔽这些文件名,防止误提交
- **air-cargo 只是提交通道**:不参与本项目开发,代码扫描、功能实现、查历史时都忽略它(见 CLAUDE.md「air-cargo 目录」一节)
## 同步点:air-cargo 提交信息里的 Synced-From trailer
每次同步提交的信息只有一句带日期的通用语句加一个 trailer,**不写修改明细**:
```
Update 20261012
Synced-From: aerologic-app@388d6058696c05cfd5892018f52120880a440524
```
脚本以 air-cargo 当前分支上最近一个 `Synced-From` 作为基线,把 `基线..main` 的变更同步过去。记录跟着 air-cargo 的提交历史走,只有真正提交了才算数。
- **区间模式(默认)**:基线 = 最近的 `Synced-From`,目标 = aerologic-app `main` 最新提交。**文件内容从目标提交对象中读取**,与 aerologic-app 工作区无关,因此已 commit 未 push、已 push 的变更都用它。提交时写入新的 `Synced-From`
- **工作区模式(`--worktree`)**:同步 aerologic-app 未提交的变更。提交信息**不写** `Synced-From`,因为这份内容不对应任何提交,不能推进同步点。之后这些改动在 aerologic-app 提交后,下次区间同步会再覆盖一次(内容相同,无副作用)
- **兜底:按内容反推**:找不到 `Synced-From` 时(首次同步,或有人手工提交时丢了 trailer),在 main 的第一父链上找与 air-cargo HEAD 内容差异最少的提交作为候选基线。只用于预览,`apply` 必须显式传 `--base`
- **基线校验**:每次预览都会比较 air-cargo HEAD 和基线的内容。正常情况下只剩 air-cargo 自己的 6 个元文件:`.gitignore`(air-cargo 额外忽略 `*.jks`)、`key密码`、`CONTRIBUTING.md`、`备忘录.md`、`国际出港进港权限对照表.xlsx`、`.docs/大写字母数字输入过滤器使用指南.md`。超过 50 个会提示基线或分支可能不对
## 使用方法
```bash
cd /Users/tim/Development/Projects/aerologic-app
bash .claude/skills/sync-air-cargo/scripts/sync.sh [preview|apply] [--base <ref>] [--to <ref>] [--worktree] [--label <word>]
```
| 参数 | 说明 |
|------|------|
| `preview` / `apply` | 默认 `preview`,只打印计划;`apply` 复制/删除并在 air-cargo 本地提交 |
| `--base <ref>` | 指定基线:反推结果经确认后传入,或用来纠正错误的同步点 |
| `--to <ref>` | 指定目标提交,默认 `main`(只同步到某个较早的提交时使用) |
| `--worktree` | 工作区模式,不能和 `--base`/`--to` 同时用 |
| `--label <word>` | 提交信息的通用词,默认 `Update`。用户要求时可换成 `Fixed`、`Optimized` 等 |
### 步骤
1. **预览**:先确定模式——用户要同步已提交的代码用默认区间模式;明确说的是"没提交的改动"才加 `--worktree`。然后执行 `sync.sh`(区间模式不加参数)。
- 输出「无需同步」:直接告诉用户,结束
- 基线来源是「按内容反推」:把候选基线连同基线校验结果一起拿给用户确认(反推可能取到比预期更早的提交,例如 air-cargo 从未同步过的环境配置提交),确认后加 `--base <sha>` 再预览一次
2. **用 `AskUserQuestion` 确认**,不要只在文字里问一句。问题描述里要包含:基线 → 目标、区间提交数、待复制/待删除数量(及主要模块分布)、**「⚠ 将覆盖 air-cargo 侧独立修改」清单(逐个列出)**、提交信息。选项至少包含「确认同步并提交」和「取消」。覆盖清单不为空时要特别说明这些文件是 air-cargo 自己改过的(如 `.gitignore` 里的 `*.jks` 忽略),由用户决定。
3. **执行**:把预览时的参数原样带上,`preview` 换成 `apply`。脚本会复制/删除文件、精确暂存这些路径并提交,最后输出提交号和变更统计。
4. **不要 push**。向用户报告提交号,并说明 air-cargo 比 `origin/feature/hefei` 超前几个提交,push 由用户自己做。
### 脚本的保护措施
- air-cargo 当前分支不是 `config` 里的 `TARGET_BRANCH` → 报错
- air-cargo 工作区有本次同步范围**以外**的未提交改动 → 报错;范围内的改动(例如上次同步还没提交)允许,重跑会覆盖成相同内容
- 基线不是目标的祖先(aerologic-app 被 rebase / force-push 过)→ 报错,用 `--base` 重新指定
- 区间内只有不参与同步的文件变化 → 仍然提交一个空提交,推进同步点
## 注意事项
- 只同步 git 跟踪的内容,`.gitignore` 忽略的构建产物(`build/`、`.gradle/`)不会同步,`air-cargo/` 本身也不在变更清单里
- 不要在 air-cargo 里手动提交同步内容。如果确实手动提交了,trailer 格式必须完全一致(`Synced-From: aerologic-app@<完整 sha>`),否则下次只能走反推
- 首个同步点:2026-10-12,air-cargo `3dd792f9`,对应 aerologic-app `388d605`(基线选 `871fa4c`)。跳过的 `dda0ff8`(vfox→mise)随后在 air-cargo 单独提交 `3c76385b` 补上:删除 `.tool-versions` / `.vfox.toml` / `.vfox/`,新增与 aerologic-app 相同的 `mise.toml`。这个提交不带 trailer,同步点不变
- 两个仓库都用 mise 管理 JDK(`mise.toml`:`java = "17"`)。air-cargo 位于 aerologic-app 之下,mise 会逐级读取配置,所以 air-cargo 里不能再出现 `.tool-versions`,否则会覆盖成未安装的旧版本