repo-sync · diff

git:20261101.c4bb711 to git:20261102.d2bbb08

5 added, 2 removed. Audit A to A.

---
name: repo-sync
description: modelmux 仓库的收尾与同步流程:把一轮代码改动同步到 docs 文档、规划进度与 commit 历史,并在需要上线时走完分支 → PR → CI → rebase merge → 删分支的闭环。用户说「收尾」「同步文档」「更新 plan/进度」「做好 commit/PR/merge」「整理提交历史」「结项」时必须使用本技能,即使没有明确点名。
---
# repo-sync —— 仓库收尾与同步
本技能覆盖 modelmux 仓库的**一轮工作如何收尾**:代码改完 ≠ 完成。必须同步 docs、
- 规划与 commit 历史;需要推送到远端时再走 PR 闭环。规则源头是根 `AGENTS.md`,
- 本技能是**可执行的操作手册**;冲突时以 `AGENTS.md` 为准。
+ 规划与 commit 历史;需要推送到远端时再走 PR 闭环。规则源头是根 `AGENTS.md` 与
+ [docs/AGENTS.md](../../../docs/AGENTS.md),本技能是**可执行的操作手册**;冲突时以前两者为准。
## 0. 事实基线(动手前必须先跑)
```bash
git status --short # 工作树状态
git branch --show-current # 当前分支(大改造禁止在 main 上)
git fetch --prune # 先 prune,否则已删的远端分支仍会出现在 branch -a
git log --oneline -5 # 最近历史与提交风格
git rev-list --left-right --count main...origin/main # 本地与远端差多少
```
判定「大改造」(必须开分支,命中任一即算):
- 改动跨越 `packages/` 下两个及以上包;
- 涉及目录结构、包边界、`workspaces`、`tsconfig` references 的调整;
- 涉及契约(`docs/CONTRACT-TS.md`)、存储落点、池架构的规则修改;
- 对外 API 形态或模型 id 形态变更;
- 预计改动超过 20 个文件。
分支名:`feat/<模块>` / `fix/<模块>` / `refactor/<模块>`,从**最新 main** 创建。
**节奏**:大改造立即开分支并走完整 PR 流程;小改动(单包/单文件/文档/注释/UI 微调)
先在 `main` 本地攒 commit,攒够一批或需要让改动生效时再一次性走 PR —— 不要一个 commit
开一个 PR。
## 1. 文档同步矩阵(代码改了哪些地方 → 哪些文档必须跟着改)
+
+ 文档分层、事实归属与写作规则以 [docs/AGENTS.md](../../../docs/AGENTS.md) 为准;本表只列
+ 代码改动对应的文档落点。
| 改动落点 | 必须同步的文档 |
| --- | --- |
| 契约 / CLI 形态 / 模块边界 / 分层 | `docs/CONTRACT-TS.md`、根 `AGENTS.md` 的「代码约定」 |
| **代码注释(渠道包 `src/` 与共享层模块的文件头 / docstring)** | **必须对照 [`docs/MODULE-COMMENTS.md`](../../../docs/MODULE-COMMENTS.md) 校验**(见下方「注释格式检查」) |
| 池(模型池 / 账号池 / 账本 / 路由) | `docs/POOL-ARCHITECTURE.md` |
| 存储落点 / 文件命名 / 权限 | `docs/STORAGE-CONVENTION.md` |
| 进程模型 / 监督者 / 守护 | `docs/DAEMON-SUPERVISOR.md` |
| 日志落点 / 字段 / 轮转 | `docs/LOGGING.md` |
| Web 控制台(页面 / API / 主题) | `docs/WEB-CONSOLE.md` |
| 引流入口 / 安装 / 接入方式 | 根 `README.md`(全中文,GitHub 只渲染它) |
| 某渠道的协议 / 端点 / 头部 / 限制 / 实测 | `docs/channels/<cid>/PROTOCOL.md`(含「使用与实测」「参考实现」小节) |
| 新增/改名/删除任何 `docs/*.md` | `docs/README.md` 索引(同步更新) |
| 新增/改名/删除渠道目录 | `docs/README.md` 与 `docs/channels/README.md` 两张表都要登记 |
### 注释格式检查(强制)
**只要动了代码注释,收尾前逐条对照 [`docs/MODULE-COMMENTS.md`](../../../docs/MODULE-COMMENTS.md)
的三层分工** —— 注释与文档出现双份事实源是最常见的腐化路径:
1. **what 去文档**:协议事实(端点、字段、状态码、实测数字)只活在
`docs/channels/<cid>/PROTOCOL.md`。代码注释里出现同一事实的副本 = 违规 ——
删副本,留一行指针(如「端点/字段/实测见 docs/channels/<cid>/PROTOCOL.md」)。
2. **why 跟函数**:设计取舍写在被治理函数的 docstring 上。
**不写日期、不写实验记录、不写「推翻了某结论」的时间线** —— 那些属于
PROTOCOL.md 的证据等级体系;docstring 只留影响代码行为的 why。
3. **文件头只做导航(≤ 12 行)**:一句话职责 + 关键约束 ≤ 3 条 + 铁律一行(如需要)+
指引到 PROTOCOL.md。头部出现大段实测记录、多个日期 = 违规 —— 下放文档,头部瘦身。
4. 口诀:**what 去文档、why 跟函数、头部只做导航**。
落点约束(`scripts/verify-docs.mjs` 会拦):`.md` 只允许落在 `docs/`(含
`docs/channels/<cid>/`)、根 `README.md` / `AGENTS.md`、
`packages/core/channels/<cid>/AGENTS.md`、`.agents/skills/<name>/` 与
`.zcode/skills/<name>/`(后两者是**整包**,允许 `references/`、`scripts/`)。
渠道包只放实现,不再带 `docs/`。
`verify-docs` 检查的是落点、索引登记、渠道 PROTOCOL 缺失、README 样板与相对链接死链;
「文档与代码同一 commit」「中文、无 emoji」「注释同步」属于**评审约束**,它不检查。
## 2. 规划同步
- 多步任务用 `planning-with-files` 技能的 `.planning/<PLAN_ID>/`(`task_plan.md` /
`progress.md` / `findings.md`);阶段状态变化后立即更新。
- 记录踩过的错误与解决方式(防重复踩坑)。
- 结项:`.planning/` 与 `.zcode/plans/` 是过程文件(已 gitignore),任务结束删除;
需要时从 git 历史取,不设 `archive/`。
## 3. 提交规范
1. 一次逻辑变更 = 一个提交;能合并的不要拆碎。
2. 信息格式 `type(scope): 中文描述`,scope 必填,结尾不加句号;
type ∈ feat/fix/docs/style/refactor/perf/test/chore(merge 仅限合并提交)。
3. 提交信息写入 `.tmp/commit-msg.txt`,用 `git commit -F` 提交 —— 多行中文内联进 shell
会被引号与换行破坏。
4. 换行一律 LF;提交前 `git status` / `git diff` 自查,敏感信息(token/密码/密钥/
.env)绝不入库。
## 4. 分支 → PR → CI → merge(需要推送时执行)
```bash
# 1) 从最新 main 开分支并提交
git checkout main && git pull origin main
git checkout -b fix/<模块>
git add <files> && git commit -F .tmp/commit-msg.txt
# 2) 【推送前必须】本地推送门禁:与 CI 等价,全绿才推
npm run gate
# 3) 推送(.githooks/pre-push 会自动再跑一次同一门禁)
git push -u origin fix/<模块>
# 4) 建 PR(gh 优先;标题必须合规)
gh pr create --title "fix(<scope>): 中文描述" --body-file .tmp/pr-body.md
# 5) 等 CI 双绿(node 22 / node 24)再合并
gh pr checks <n>
```
- **推送前必须先 `npm run gate`**(干净 clone 里 `npm ci` + `npm test`):开发工作树与
ubuntu-latest 有真实差异(git 历史深度、平台原生依赖、未提交改动与陈旧产物),
在工作树上跑绿不代表 CI 会绿。`pre-push` 会对**所有推送**全量再跑一次 `npm test`,
它是兜底拦截,不是提前发现,也不按文件范围分流。
- **改了 `.github/workflows/**` 必须本地先跑通再推**:workflow 的失败模式通常只有真跑
产物才暴露。演示站点的 `demo-pages.yml` 要本地验三件事:`DEMO=1 DEMO_BASE=/<repo>/`
构建后资源引用带前缀、`index.html` 复制成 `404.html` 后深链能渲染、Pages 源为
`build_type: workflow`。workflow 改动仍以 `npm run gate` 为准;
本机没有 `act`,不要假设能用 act 复现。
- 合并统一用 **`gh pr merge <n> --rebase`**(保持线性历史,禁止 merge commit)。
rebase 保留分支内的各条提交信息;PR 标题只有在 squash 时才会变成提交信息
(`merge_commit_title=PR_TITLE`)。`verify:commits` 校验的是提交,不是 PR 标题。
- **禁止** `--no-verify` 绕过 pre-push;CI 红着时禁止继续推送新提交。
- 合并后:删远端分支(`gh api -X DELETE repos/bluechonk/modelmux/git/refs/heads/<branch>`)、
`git fetch --prune`、`git checkout main`、`git reset --hard origin/main`(rebase 会重写 SHA,
本地与远端分叉属正常)、删本地分支,再确认 main 的 CI 双绿。
### 4.1 发版:**只打 tag,绝不建 Release**(主人明确要求,违反即返工)
```
发版 = 改版本号落点 → chore(release) 提交 → PR 合并 → 在 main 打 vX.Y.Z tag → 停。
```
- **禁止** `gh release create` / `gh release edit` / `gh release upload`,
**禁止**用全局 `github:release` 技能,**禁止**点 GitHub 网页的「Draft a new release」。
与全局 `~/.agents/AGENTS.md`「标签与发布」里「打 tag → 出 Release」冲突时**以本仓规则为准**
(本仓细则见 [docs/WORKFLOW.md](../../../docs/WORKFLOW.md) 的「版本与发版」)。
- 为什么:本仓没有发布物 —— 没有 `npm publish`、没有产物打包 workflow、没有 exe/安装包,
发布物只有 **web 控制台 + CLI 源码**。Release 页面承载的「版本说明」的权威来源是 `git log`,
多一个页面就多一份会漂移的事实源(主人原话:「我又不做 exe,我只做 web 和 cli」)。
- 打 tag 前先过推送门禁;tag 只打在**合并后的 main** 上,不打开发分支。
- **Releases 页必须保持为空**(含 draft):`gh release list --repo bluechonk/modelmux` 要**没有输出**,
`gh api repos/bluechonk/modelmux/releases` 要是 `[]`。若发现残留(历史遗留也算),
删掉并**保留 tag**:`gh release delete <tag> --yes`(⚠ 别加 `--cleanup-tag`,那会连 tag 一起删)。
- 删除 Release 与「发布」无关,不影响 tag、不影响任何产物 —— 本仓本就没有发布物。
## 5. 收尾检查清单(一条都不能漏)
```bash
npm run build # 全仓编译(含 ui + bundle + copy-ui)
npm test # build + typecheck + 全部 verify:* + 全部包测试,必须全绿
node packages/cli/dist/cli.js restart # 改了 packages/core/** / cli / ui 必须重启
node packages/cli/dist/cli.js status # 必须不含「网关在跑旧代码」
# 真机验证:见下方分工
# 注释格式:改过注释的文件,逐条对照 docs/MODULE-COMMENTS.md(见 §1「注释格式检查」)
git status # 工作树干净(无未提交 tracked 文件)
git fetch --prune && git branch -a # 本地/远端只剩 main
gh release list --repo bluechonk/modelmux # 必须没有任何输出(含 draft;§4.1)
git tag -l # tag 才是发布物,必须都在
ls .tmp # 清理临时文件;截图与诊断产物不留仓库
```
验证分工(不要在本技能里重复展开细节):
- `mx` 命令用法与坑 → `mx-cli` 技能;
- 日志与失败码 → `log-triage` 技能;
- 渠道端到端验收 → `opencode-mx-test` 技能;
- 跨会话核对进度 → `zcode-session-archaeology` 技能。
- 涉及登录/凭据/上游的改动:必须 `mx login <cid>` → `mx status <cid>` → 真实对话。
- 双实例(如 4413 调试实例):重启后确认 `health=200`;日志按**分层目录**落
(`~/.modelmux/logs/system/<日期>/`,实例各自写自己的 `worker.log`),见
[`docs/LOGGING.md`](../../../docs/LOGGING.md) §2。
- 在 linked worktree 里收尾:先读 `AGENTS.md` 的「Worktree 约束」;删分支前先
`git worktree remove` + `git worktree prune`。
## 6. 常见错误(都真机踩过)
| 错误 | 后果 | 正确处理 |
| --- | --- | --- |
| 只 push 不建 PR / 合并后不删分支 | 分支残留、历史碎 | 走完 §4 全流程 |
| PR 标题写英文/无 scope | squash 时提交信息不合规 | 标题必须是 `type(scope): 中文` |
| 一次提交后立刻开 PR | 历史碎片化 | 小改动先本地攒批次 |
| 未提交就继续做新任务 | 改动混批、历史难看 | 每轮收尾再开工 |
| `git add -u` 漏掉新文件 | CI 构建失败(UNRESOLVED_IMPORT) | 新文件用 `git add <path>` |
| 改了代码没 restart | 验证的是旧进程 | build → restart → status 无陈旧 |
| **给本仓建了 GitHub Release**(`gh release create` / `github:release` 技能 / 网页 Draft) | 主人明确禁止:本仓发布物只有 tag,Release 页是多余事实源 | 只打 tag(§4.1);已建的要删掉并保留 tag:`gh release delete <tag> --yes` |
| 本地绿但推送门禁红 | 平台/依赖差异(如漏提交新文件) | 用门禁同款命令在干净 clone 复现 |
| `.tmp` 被删后重定向失败 | 测试没跑却以为绿了 | 先 `mkdir -p .tmp` |
| 合并后本地 `git pull` 冲突 | rebase 重写了 SHA,同内容不同源 | `git fetch --prune` 后 `git reset --hard origin/main` |
## 7. 输出要求
收尾完成后给用户一份简短清单:本轮提交(SHA + 一行说明)、PR 编号与合并方式、
CI 状态、真机验证结论、分支/工作树/临时文件状态、以及**需要用户配合的事项**
(如需要真实账号的登录验证)必须单独列出,不能混在「已完成」里。
### Agent 交付说明(每轮变更的固定格式)
除清单外,每轮代码变更附一段结构化说明 —— 便于复盘、CR 与跨会话对齐:
```text
变更范围:<packages/xxx / docs/xxx / scripts/xxx>
变更目的(Why):<解决了什么问题 / 为什么要做>
关键取舍与风险:<选了什么、放弃了什么、已知边界>
测试点:<验证了什么(命令 / 真机步骤),没验证的写明原因>
关联项:<PR / issue / 计划文件路径,无则「无」>
```