Skip to content

feat(worktree): 分支胶囊支持手动对齐远程分支 - #7059

Merged
MagicLizi merged 11 commits into
mainfrom
feat/worktree-branch-align-remote
Oct 24, 2026
Merged

MagicLizi merged 11 commits into
mainfrom
feat/worktree-branch-align-remote

Conversation

@fmfsaisai

@fmfsaisai fmfsaisai commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

这次改了什么

摘要

手动新建 worktree(主会话新建任务、创建 Worker 面板)时,源分支一直直接用本地分支、从不联网。本地 main 落后远程时,新 worktree 就从旧代码开始,只能自己去终端 git fetch / git pull。本 PR 在分支胶囊上加一个手动刷新按钮,让用户在不拖慢创建的前提下把源分支对齐到远程最新:

  • 刷新按钮(RefreshCw):位于胶囊内分支名右侧(主会话 [分支 ⟳ │ ☑ worktree],Worker 面板 [分支 ⟳]),两处共用 BranchWorktreeChip。点击只拉取选中分支对应的远程分支(按 branch.<b>.remote + branch.<b>.merge,未配置时用 origin 同名分支;显式 refspec,30 秒上限,不等待凭证输入),然后只快进本地分支:
    • 分支未在任何目录检出:祖先校验后 update-ref(带旧值校验);
    • 分支在某个目录检出(常见是主仓库停在 main):在该目录 git merge --ff-only --no-autostash;允许存在不相关的未提交改动,Git 会拒绝覆盖未提交改动;
    • 本地领先保留本地;分叉、或未提交改动与远程更新涉及同一批文件时不更新。绝不做非快进合并、rebase、reset、stash 或切换分支。
  • 按钮状态与悬停提示(文案参考 GitHub Desktop,动词开头、只说这次做什么):可更新时提示「拉取 origin/master 的最新提交」;分支在某个目录检出时再加一段「会同步更新当前分支已提交的文件,未提交的改动会保留」;拉取中转圈(共享 Spinner)/ 完成后 ✓ 约 2 秒并说明结果(已更新 N 个提交、已是最新、无需更新)/ 失败可重试并弹 toast。分叉、改动冲突、远程没有该分支、没有远程仓库时按钮变灰,变灰时仍可悬停看到原因;用户点击后才发现被拒时弹 warning。变灰判断只读本地 Git,不联网;缺少本地 tracking 缓存不视为远程没有该分支(仍可点击拉取确认)。
  • 分支下拉:选中分支下显示一行状态(如「落后 origin/main 3 个提交 · 未提交 3 个文件」;两边都有新提交时合并为「领先 1、落后 1 个提交(origin/main)· 未提交 2 个文件」);勾选 worktree 后(Worker 面板的源分支下拉本就只在新建 worktree 时出现)在最上方单独列出远程主分支 origin/main(或 master),选中后以完整引用 refs/remotes/origin/main 作为源,从远程最新提交创建,胶囊显示 origin/main。远程主分支只读本地判断:origin/HEAD(并确认目标存在)→ origin/main → origin/master。
  • 创建流程不变:createWorktree、listBranches()、发送路径与 freshBase 自动路径均未改动;创建不等待拉取,拉取进行中照常可以发送,用的是当时的选择与本地状态。

变更类型

  • feat 新功能
  • fix 缺陷修复
  • refactor / perf 重构或性能优化
  • docs / test / chore 文档、测试或工程维护
  • 其他:

范围

  • 关联 Issue / 需求:手动新建 worktree 时源分支落后远程的问题;自动创建 worktree 的定时任务等路径已有 freshBase(fix(desktop): 自动 worktree 改用 fetch 后的远端默认分支为基底 #1376),本 PR 不改它们。
  • 本 PR 包含:worktree:branch-sync-status(只读本地)/ worktree:sync-branch(拉取并快进)两个 IPC、preload、device-link 白名单与 sync-branch 的 baseRepo 路径守卫;worktree:list-branches 响应可选追加 remoteDefaultBranch;胶囊按钮、状态行、远程分组;五种语言文案;协议兼容文档。
  • 明确不包含:创建时自动拉取或「落后就改用远程」的隐藏规则;upstream 远程(fork 场景)的分组;手机端入口;Agent create_worker 工具。
  • 用户可见变化:分支胶囊多一个刷新按钮;分支下拉多状态行和「远程 / 本地分支」分组;点击后可能更新本地分支以及检出该分支目录里的文件(仅快进)。
  • 是否存在 breaking change:无。

UI 变化

  • 截图来源:单页验证 pnpm ui:check --page branch-sync --case all --theme all --locale zh-CN,en,macOS · Electron 42.11.12(Chromium 148.0.7778.280,与 Cindy 同一渲染内核);真实组件与主题,场景数据,不是登录账号下的完整 Cindy
  • 版本:f512dea3d61a
  • 结果:24/24 个场景通过
  • 页面 branch-sync:light / dark · zh-CN / en · 560×400 / 360×400
    • default:Main-task capsule, selected-branch details, remote group and successful fetch
    • worker:Compact Worker branch-only capsule
    • unchecked:Unchecked main-task worktree excludes remote sources
    • conflict:Disabled sync remains focusable and explains overlapping changes
    • diverged:Diverged branches keep local source and explain why sync is unavailable
    • old-host:Old controlled host has neither refresh button nor remote group
    • 未覆盖:Git processes, device-link transport and native task creation; covered by unit and Git integration tests

单页验证截图 1/4
单页验证截图 2/4
单页验证截图 3/4
单页验证截图 4/4

  • 其余语言:pnpm ui:check --page branch-sync --case all --theme all --locale all 60/60 通过(zh-TW / ja / ko 已目检两段提示、分叉状态行与换行)。

  • 引用的设计规范:

    • DESIGN.md §4 Buttons:刷新按钮作为胶囊内的独立点击区(32px 宽、胶囊全高),悬停 / 按下 / 聚焦环沿用同一胶囊里分支段与 worktree 段的 token(compact 用 --create-agent-control-bg-hover/pressed,常规用 sidebar-item-hover,聚焦用 --focus-ring),不新增颜色
    • DESIGN.md §4 Select & Dropdown:分支下拉沿用既有搜索框、键盘选择与 aria-activedescendant 结构,新增分组标题与状态行只用既有文字色
    • DESIGN.md §4 Toast:失败用 error、点击后被拒用 warning,沿用全局 toast
    • DESIGN.md §14.4 Motion:转圈复用共享 Spinner(HTML 外层旋转、--motion-spinner-cycle、减少动态效果时静止)
    • DESIGN.md §5 Spacing:两段提示之间用 8px 段间距
    • DESIGN.md §3 桌面 UI 字号白名单:新增文字只用 text-12 / text-13
    • DESIGN.md §2 双模式:全部走语义 token,浅色 / 深色均已截图检查
    • i18n/GLOSSARY.md:worktree 保持英文小写

怎么验证的

自动验证

(以下均在 rebase 到 origin/main 1f528830cb 后的 bce8ecf5ed 上执行)
pnpm --filter desktop run --if-present typecheck
结果:通过

vitest:branchSyncHandlers、BranchWorktreeChip、CreateWorkerPopover、newMakerProjectPicker、
worktreeManagerCreate、deviceLinkHostDispatch、worktreeReveal、useWorktreeQueries
结果:8 files / 250 tests 通过(20.96s)

vitest --project git-integration branchSync.git-integration.test.ts
结果:13 tests 通过(8.40s)

packages/device-link allowlist.test.ts   结果:通过
pnpm check:test-hygiene / check:i18n / check:i18n-glossary / check:dev-docs / check:dco
结果:均通过(i18n 仅既有告警)
pnpm ui:check --page branch-sync --case all --theme all   结果:12/12 通过

(review 修复 c5766f9531 之后)
vitest --project git-integration branchSync.git-integration.test.ts   结果:16 tests 通过
branchSyncHandlers + BranchWorktreeChip   结果:16 tests 通过
typecheck / check:i18n / check:i18n-glossary / check:test-hygiene / check:dco   结果:通过

(第三轮 review 与文案调整之后,f512dea3d6)
BranchWorktreeChip   结果:10 tests 通过(单跑 1.69s)
branchSync git-integration 16/16、handlers 7/7(91244119ff 之后无主进程改动)
typecheck / check:i18n / check:i18n-glossary / check:dco   结果:通过
pnpm ui:check --page branch-sync --case all --theme all --locale all   结果:60/60 通过

新增 / 改写测试(engineering-conventions §3.2):

测试文件 被测入口与可观察结果 依据 / 覆盖缺口 tier 单独运行耗时
main/worktree/__tests__/branchSync.git-integration.test.ts(新) 真实临时仓库 + 本地裸远程:检出 / 未检出 / linked worktree 快进、无关未提交改动保留、分叉与改动重叠与未跟踪覆盖被拦且现场不变、本地领先、无远程与远程缺分支、tracking 异名映射、origin/HEAD 缺失或悬空兜底、拉取期间并发写入 新增同步逻辑,需要真实 Git 行为 git-integration 13 例约 7.6–8.4s
main/worktree/__tests__/branchSyncHandlers.test.ts(新) IPC 边界:参数校验、错误只回传分类(Git 原文可能含带凭证的远程地址)、device-link 调用路径 新 IPC 边界 unit 7 例 1.19s
renderer/components/new-chat/__tests__/BranchWorktreeChip.test.tsx(新) 胶囊:状态行、远程分组显示条件、旧被控端隐藏且不调用新 IPC、重复点击抑制、变灰提示与悬停重查、失败 toast、点击后被拒 warning(初始检查不弹)、迟到结果丢弃、远程缺分支在本次选择内保持变灰、两边都有新提交时状态行合并 新 UI 行为 unit 10 例 1.69s
main/__tests__/worktreeReveal.test.ts(改) 真实注册的 worktree:list-branches:远程主分支补充成功;探测超时不影响本地分支列表 防止 UI 补充影响列表 unit 并入既有文件
main/__tests__/deviceLinkHostDispatch.test.ts、packages/device-link/.../allowlist.test.ts(改) sync-branch 纳入白名单与 baseRepo 路径守卫 协议 / 权限边界 unit 并入既有文件
renderer/features/cc-agent/__tests__/CreateWorkerPopover.test.tsx(改) Worker 面板打开下拉前不拉分支列表;远程分组与显示名 懒加载约定与新字段 unit 并入既有文件

手工验证

macOS,隔离开发实例(独立用户数据目录),远程全部是临时目录里的本地裸仓库;agent-browser 为主、computer use 补充,主会话与 Worker 面板两个入口逐项执行。41 个逻辑用例:

  • 通过 35:未检出 / 主目录检出 / linked worktree 快进;暂存、未暂存、未跟踪改动逐字节保留;改动重叠四类、未跟踪覆盖、分叉均拦截且 HEAD / 暂存区 / 工作区 / stash 不变;tracking 异名、其他远程、无缓存但远程存在、只拉目标分支;origin/HEAD 有效 / 缺失 / 悬空、main / master 兜底;不刷新直接创建取本地缓存;拉取被人为阻塞时创建照常完成(0.55–2.60s),起点为拉取前的完整提交,无锁冲突;路径含空格与中文;转圈连续动画与 ✓ 约 2 秒;变灰原因悬停;点击后被拒弹 warning、初始检查不弹;主会话 Escape 关闭下拉;浅色 / 深色动态状态。
  • 首轮发现 1 个问题(点击后被拒没有 toast),已在第二个提交修复并复测通过。
  • 跨设备与辅助功能补测(新版实例为 bce8ecf5ed,旧版为改动前的 124508423d;在同一台 Mac 上起独立实例、登录同一账号,代替两台物理电脑):
    • 新版控制旧版:通过。没有远程分组,刷新按钮最终隐藏;搜索、选分支、创建 worktree 正常,新 worktree 的 HEAD 等于所选分支。按钮从出现到隐藏约 220ms,胶囊宽度收缩一次(32px),仅作记录。
    • 新版控制新版:通过。远程分组和状态行正常;点击后快进发生在被控端(git-upload-pack 的父进程是被控实例),无关的未提交改动和 stash 完整保留。通过 device-link 传入不存在的目录、文件路径、不可访问的目录时,分别被 REMOTE_WORKDIR_NOT_FOUND / REMOTE_WORKDIR_NOT_DIRECTORY / REMOTE_WORKDIR_UNAVAILABLE 拒绝。
    • 旧版控制新版:通过。选分支和创建正常,没有兼容错误。
    • 真实键盘:通过。用真实按键操作,上下键可在远程组和本地组之间切换并首尾循环,Enter 选中,Escape 关闭并把焦点还给触发按钮;用 Tab 能聚焦到变灰的按钮并显示原因(Worker 面板中有一次聚焦时没截到提示,悬停时的提示上一轮已验证)。
    • 未覆盖:真实读屏(没有开 VoiceOver,系统无障碍树里读不到网页内的元素);真实中文输入法组合态(切换到已启用的拼音输入法后,测试环境没有产生组合事件,没有用合成事件冒充);SSH 运行设备(本机没有 SSH 服务,也没有为此开启)。

未执行的验证

  • Windows 实机未验证。
  • 整仓 pnpm test:unit:related:白名单改动会选中 Desktop / Mobile 全量;Mobile、device-link 通过,Desktop 全量在约 131s 后 SIGSEGV 退出,其间 remote-agent/executor/__tests__/executor.test.ts 有两条失败,单独重跑同样失败,与本 PR 改动无关(未改该路径)。
  • 整站 pnpm ui:check --changed:语言文件改动会选中 131 个页面,781/790 通过;失败的 8 个 subscription-fast 与 1 个 voice-settings 场景不在本 PR 改动范围内,未另建基线复跑。

风险

风险分类

  • 无已知风险
  • SQLite / migration
  • system prompt
  • 协议兼容
  • 权限 / 安全 / 用户数据
  • 存量插件兼容(批准状态 / 指纹 / manifest 校验 / 安装布局 / 包格式)
  • 原生层 / fingerprint / OTA
  • 跨平台差异
  • 其他:

影响与回滚

  • 影响范围:
    • 协议:新增两个 device-link channel(sync-branch 走 baseRepo 路径守卫,单次预留 90 秒、失败不重放),worktree:list-branches 响应只追加可选字段。新控制端连旧被控端时,状态查询返回 DEVICE_LINK_CHANNEL_NOT_ALLOWED 即隐藏按钮、缺字段即不显示远程分组,选分支与创建保持原行为;旧控制端忽略新字段。
    • 用户数据:仅在用户点击时修改本地分支引用,以及检出该分支目录里的文件,且只做快进;未提交改动由 Git 自身保护,冲突时拒绝且现场不变。Git 原始输出不回传到界面,避免泄露远程地址中的凭证。
  • 回滚 / 降级方式:直接 revert 本 PR 即可;无数据库、配置或持久化数据变化,回滚后按钮和分组消失,创建流程本来就未改动。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名(git commit -s,见 DCO)
  • UI 改动已在「UI 变化」注明引用的设计规范章节(不涉及 UI 则跳过)
  • 未提交凭证、令牌或授权文件
  • 已核对受影响的文档,行为变化涉及的旧结论已同步修订(不涉及则无需修改文档)
  • 已确认测试结果或说明未执行原因

主会话和 Worker 共用分支刷新按钮、状态提示与远程分组;仅执行显式拉取和快进。保留创建路径及分支列表懒加载,通过状态 IPC 识别旧被控端,并补充真实 Git 和界面回归测试。

Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
@fmfsaisai
fmfsaisai requested a review from a team as a code owner October 24, 2026 12:39
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-24T15:28:15.188794Z f512dea Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bce8ecf5ed

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/desktop/src/main/worktree/branchSync.ts
@greptile-apps

greptile-apps Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] 本轮改动看起来可以合并,未发现需要阻止合并的新问题。

Summary

本 PR 为分支胶囊增加手动拉取与快进,并支持选择远程主分支。

  • Branch capsules can refresh a selected branch without making worktree creation wait.
  • Worktree branch menus can offer the remote default as a separate source.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[用户选择源分支] --> B[读取本地分支状态]
  B --> C[胶囊显示提示与状态]
  C --> D[用户点击刷新]
  D --> E[拉取指定远程分支]
  E --> F{是否可快进}
  F -->|可以| G[更新分支并返回结果]
  F -->|不可以| H[保留本地状态并说明原因]
  A --> I[创建 worktree,不等待刷新]
Loading

Reviews (4) · Last reviewed commit: "fix(worktree): 完善刷新文案复数与分叉状态说明" · Reviewed by Greptile

Comment thread apps/desktop/src/main/worktree/branchSync.ts Outdated
Comment thread apps/desktop/src/main/worktree/branchSync.ts Outdated
@fmfsaisai

Copy link
Copy Markdown
Collaborator Author

@codex review

@greptileai 请复审。

上一轮的 3 条意见已处理(最新提交 c5766f9531):

  • 同一分支在多个目录同时检出(Codex P1):会收集全部检出目录,超过一个就返回 multiple-checkouts,不做任何写入。
  • 被忽略的文件可能被覆盖(Greptile P1):快进合并加上了 --no-overwrite-ignore,被拒时归为 conflict,现场保留。
  • 状态查询之后、写入之前分支被检出(Greptile P1):未检出分支改用不带 + 的本地 git fetch . <sha>:refs/heads/<branch> 写入,由 Git 在写入那一刻拒绝非快进以及已检出的分支。

每一条都补了真实 Git 回归测试,branchSync 真实 Git 用例 16/16 通过;typecheck、i18n、test-hygiene、DCO 也都通过。

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5766f9531

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/desktop/src/main/worktree/branchSync.ts
Comment thread apps/desktop/src/main/worktree/branchSync.ts
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
@fmfsaisai

Copy link
Copy Markdown
Collaborator Author

@codex review

@greptileai 请复审。

第二轮的 2 条意见(最新提交 91244119ff):

  • 写操作被 5 秒探测超时中途中断(Codex P1):已修复,merge 和本地 fetch 写入不再设置超时,并禁用交互式提示;只读探测仍为 5 秒。
  • 检出分支的确认与 merge 之间的切换窗口(Codex P1):暂不修改,原因已在该讨论中说明(毫秒级窗口、Git 没有对应的原子命令,硬做的改动面大于收益)。

branchSync 真实 Git 回归 16/16、handlers 7/7、typecheck、DCO 均已通过。

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91244119ff

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/desktop/src/renderer/components/new-chat/WorktreeChipsRow.tsx Outdated
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
@fmfsaisai
fmfsaisai marked this pull request as draft October 24, 2026 14:49
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
@fmfsaisai
fmfsaisai marked this pull request as ready for review October 24, 2026 15:24
@fmfsaisai

Copy link
Copy Markdown
Collaborator Author

@codex review

@greptileai 请复审。

PR 已转回 ready。上次复审(91244119ff)之后的改动,最新提交为 f512dea3d6:

  • 转圈动画(Codex P2):已修复,改用共享的 Spinner,遵循 DESIGN.md §14.4。
  • 交互确认后精简了文案:悬停提示参考 GitHub Desktop,改为动词开头;分支在某个目录检出时,加一段「会同步更新当前分支已提交的文件,未提交的改动会保留」,两段之间留 8px 间距;英文补齐单复数;两边都有新提交时,状态行合并为一段。
  • 刷新提示改为按完整单词换行(只覆盖该 Tooltip,共享组件不变)。

本轮没有改动主进程。BranchWorktreeChip 10/10、typecheck、i18n 检查通过,ui:check 全语言双主题 60/60 通过。

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f512dea3d6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/desktop/src/main/worktree/branchSyncHandlers.ts
@MagicLizi MagicLizi added touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示) labels Oct 24, 2026

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #7059 独立代码审查报告(heavy 档)

审查对象:feat(worktree): 分支胶囊支持手动对齐远程分支,head f512dea3d61a661f616577357ce9e7c4a5739862,base 1f528830cb08faa25580f3e019b57ee75622fc2d(main),diff 30 文件 / 1813 行。

Findings

  • 没有 P0/P1。

Rule coverage

  • AGENTS.md、docs/dev-rules/development-workflow.md、.github/PULL_REQUEST_TEMPLATE.md:描述三大段与验证口径齐全,diff 与描述一致(详见 Intent alignment)。
  • docs/dev-rules/electron-security-and-process-boundaries.md §8 清单:
    1. Renderer 新增能力仅为两条 IPC(只读状态查询 + 用户显式触发的拉取/快进),无新特权数据(回传的 checkoutPath 与既有 worktree:list-branches 口径一致,属用户自有目录信息);
    2. 不涉及 BrowserWindow / WebView;
    3. preload 只暴露两个固定方法、不透传 Electron event;
    4. IPC 校验齐全:本地调用 assertTrustedAppRendererEvent,device-link 来源走 invoke 白名单 + worktree:sync-branch 的 baseRepo 路径守卫(PATH_GUARDED_CHANNELS);payload 用 requireObject/requireString,绝对路径、长度、NUL/控制字符、- 前缀、..、字符类拒绝后再 check-ref-format 复核,杜绝 option 形参;错误不回传 Git 原始输出(远程 URL 可能含凭证);
    5. 不涉及 URL / 导航 / 下载 / 自定义协议;6) CSP / Fuses 未放宽;
    6. 新边界有测试锁住:deviceLinkHostDispatch.test.ts 参数化覆盖 worktree:create / worktree:sync-branch 的路径守卫放行与拒绝。
  • docs/dev-rules/engineering-conventions.md Review 清单:无 console.log;新 handler 用 throwIpcError + IpcErrorCode(INVALID_PARAMS / INTERNAL + branch-sync: 原因前缀约定),未见 as 强转解码;createBranchSyncHandlers(deps) 依赖注入、免 Electron 可测,主路径 + 关键错误路径均有测试;测试用临时真实 Git 仓库,无外网/固定端口/共享临时路径;UI 文案全部走 t(),五语言(en/ja/ko/zh-CN/zh-TW)齐全一致;常驻动画复用共享 Spinner(HTML wrapper 旋转、响应 prefers-reduced-motion,符合 DESIGN §14.4)。
  • docs/dev-rules/architecture-invariants.md:main 无运行时动态 import(),无反向依赖,未改布局树。
  • docs/dev-rules/remote-and-mobile-adaptation.md:新 invoke 已登记 packages/device-link 白名单(worktree:branch-sync-status / worktree:sync-branch)并同步 INVOKE_TIMEOUT_OVERRIDES_MS(90s)与协议文档;手机端明确不提供入口;失败不重放写请求、不动 peer/relay,恢复半径未扩大。
  • docs/dev-rules/protocol-compatibility.md(本 PR 修改,rules 触发):新增章节为追加式契约(remoteDefaultBranch 可选字段、旧被控端 DEVICE_LINK_CHANNEL_NOT_ALLOWED 降级、缺字段不显示远程分组),不改既有语义、不放宽校验,属文档性新增,非借改判据为自己开脱。
  • DESIGN.md / cindy-design-system.md:胶囊按钮沿用既有语义 token(text-muted-foreground、bg-accent、hover:bg-sidebar-item-hover、--focus-ring),无硬编码颜色、无自造组件顶替设计系统组件;check:design-colors 仅对既有的 rounded-[8px](分支选项行,机械搬迁非新增)提示「未登记」,非本 PR 引入。
  • i18n/GLOSSARY.md:check:i18n-glossary 通过,无新增术语违规。

Verification

(命令在 PR head 检出的独立 worktree 运行,均记录命令自身退出码)

  • pnpm --filter desktop run typecheck → EXIT=0。
  • pnpm --filter desktop exec vitest run src/main/worktree/__tests__/branchSync.git-integration.test.ts src/main/worktree/__tests__/branchSyncHandlers.test.ts src/main/__tests__/deviceLinkHostDispatch.test.ts src/main/__tests__/worktreeReveal.test.ts → EXIT=0,54 passed(真实 Git 回归 16/16、handlers 7/7、dispatch 21、reveal/list-branches 10)。
  • pnpm --filter desktop exec vitest run src/renderer/components/new-chat/__tests__/BranchWorktreeChip.test.tsx src/renderer/features/cc-agent/__tests__/CreateWorkerPopover.test.tsx → EXIT=0,103 passed。
  • pnpm --filter @cindy/device-link exec vitest run src/__tests__/allowlist.test.ts → EXIT=0,53 passed。
  • pnpm check:i18n → EXIT=0(五语言 13545 key 一致);pnpm check:i18n-glossary → EXIT=0;pnpm check:dco → EXIT=0(base..head 11 个 commit 全部 Signed-off-by);pnpm check:design-colors → EXIT=0。
  • heavy 档安全扫描 security-scan.mjs --base 1f528830:无新增/升级第三方依赖(audit 按规则跳过);semgrep(p/javascript + p/nodejs,仅新增)0 条 finding。⚠️ 如实说明:semgrep 对 3 个 TS/TSX 文件解析失败(vite-env.d.ts、preload.ts、CreateWorkerPopover.test.tsx),这部分不能算已扫描;对应 diff 已人工通读,未见危险写法。新增的危险写法面(Git 子进程调用)全部经既有 gitExec(execFile 参数数组、无 shell)执行,探测 5s / 网络 30s / 写操作不设超时但 GIT_TERMINAL_PROMPT=0,无数据外发、无凭证落盘或回传。
  • pnpm check:test-hygiene → EXIT=1:报 plugin-oauth/__tests__/runtimePrompt.test.ts、voice-input/__tests__/MacModifierShortcutListenerStartRace.test.ts 两个存量测试超过基线;两文件与 scripts/test-hygiene-baseline.json 均不在本 PR diff(git diff --name-only base..head 核对),系 main 存量基线漂移(#4813 一带合入),非本 PR 引入,不按 P0/P1 计入本 PR。
  • 未执行:ui:check 实机渲染复跑(PR 正文已附 --theme all 双主题截图证据,按规则不强制逐项对照);未跑全量 pnpm test:unit(CI client-ci / pr-design-basis 全绿兜底)。
  • 机器人静默期:copilot-pull-request-reviewer 超过 20 分钟未表态,按超时放行;其意见可能在合并后才到。

Intent alignment

描述来源:PR 正文(2026-10-24 多轮更新)。原目标:手动新建 worktree 时源分支落后远程、只能去终端手拉,为此在分支胶囊加手动刷新按钮,按 tracking 配置拉取对应远程分支并只快进本地分支;创建流程不变、不做任何隐藏自动拉取。

初始实现:c07afaf0 + bce8ecf5(基线 1f528830),已读该 revision 的 branchSync.ts 等实现。待合并 head:f512dea3。

原目标/初始行为 最终行为与影响 代码/提交证据 变化依据或待确认问题
手动拉取 + 只快进(fetch + merge --ff-only / update-ref) fetch + merge --ff-only --no-autostash --no-overwrite-ignore;未检出分支改用不带 + 的本地 fetch 写入(写入时拒绝非快进与已检出分支);多检出直接拒绝 c5766f95、91244119,branchSync.ts Codex/Greptile 三条 P1 的修复,均有真实 Git 回归用例,同一目标内加固
写操作受 5s 探测超时约束 写操作不设超时(GIT_TERMINAL_PROMPT=0),只读探测仍 5s、网络拉取 30s 91244119 Codex P1(慢 smudge filter 中断检出)修复
刷新按钮自绘转圈动画 复用共享 Spinner(wrapper 旋转 + reduced-motion) 661ba8fe Codex P2,DESIGN §14.4
悬停提示/状态行文案 参考 GitHub Desktop 改动词开头、补复数与分叉说明、两段间距 f5322e66…f512dea3 交互确认后的纯文案调整
创建流程不变 createWorktree、listBranches()、发送路径、freshBase 自动路径零改动(worktree:list-branches 仅响应可选追加 remoteDefaultBranch) diff 文件清单核对 与正文承诺一致

已 Resolve 的 Codex / Greptile 意见逐条回看:3 条 P1 已修(多检出、忽略文件覆盖、检出后写入守卫);2 条作者明确「暂不修改」并给出依据,本次独立复核同意按 P2 处理、不构成阻断——
① branchSync.ts:213 检出确认与 merge --ff-only 之间的切分支竞态:毫秒级窗口、需用户在同一目录并发切分支,与用户自行 git pull --ff-only 同一模型,Git 无对应原子命令,且 reflog 可恢复、merge 只快进不覆盖未提交改动;
② branchSyncHandlers.ts:23 XSS 下任意 baseRepo:前置是主渲染器已被攻破,既有 worktree:create 与任务内命令的同等暴露更大,本接口仅拉取与快进(不丢提交、冲突由 Git 拒绝),且 device-link 侧已有路径守卫;宜与全部 worktree IPC 统一做授权收敛,属架构层面后续项。

结论:一致,无偏离。核心目标(手动对齐远程分支、只快进、创建流程不变、不隐藏自动拉取)在最终 diff 中全部成立;多轮修复均为围绕同一目标的安全加固与文案打磨,无删除/削弱/反转原承诺,无无关扩范围,无未裁定的核心方向问题。

Overall

pass —— 没有 P0/P1。

@MagicLizi
MagicLizi merged commit 315a72f into main Oct 24, 2026
27 checks passed
@MagicLizi

Copy link
Copy Markdown
Contributor

@/tmp/pr7059-thanks.md

@fmfsaisai
fmfsaisai deleted the feat/worktree-branch-align-remote branch October 27, 2026 07:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants