Repository navigation
feat(worktree): 分支胶囊支持手动对齐远程分支 - #7059
Conversation
主会话和 Worker 共用分支刷新按钮、状态提示与远程分组;仅执行显式拉取和快进。保留创建路径及分支列表懒加载,通过状态 IPC 识别旧被控端,并补充真实 Git 和界面回归测试。 Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 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".
[Medium impact] 本轮改动看起来可以合并,未发现需要阻止合并的新问题。
|
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
|
@codex review @greptileai 请复审。 上一轮的 3 条意见已处理(最新提交
每一条都补了真实 Git 回归测试,branchSync 真实 Git 用例 16/16 通过;typecheck、i18n、test-hygiene、DCO 也都通过。 |
There was a problem hiding this comment.
💡 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".
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
|
@codex review @greptileai 请复审。 第二轮的 2 条意见(最新提交
branchSync 真实 Git 回归 16/16、handlers 7/7、typecheck、DCO 均已通过。 |
There was a problem hiding this comment.
💡 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".
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>
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
|
@codex review @greptileai 请复审。 PR 已转回 ready。上次复审(
本轮没有改动主进程。BranchWorktreeChip 10/10、typecheck、i18n 检查通过,ui:check 全语言双主题 60/60 通过。 |
There was a problem hiding this comment.
💡 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".
MagicLizi
left a comment
There was a problem hiding this comment.
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 清单:- Renderer 新增能力仅为两条 IPC(只读状态查询 + 用户显式触发的拉取/快进),无新特权数据(回传的
checkoutPath与既有worktree:list-branches口径一致,属用户自有目录信息); - 不涉及 BrowserWindow / WebView;
- preload 只暴露两个固定方法、不透传 Electron event;
- IPC 校验齐全:本地调用
assertTrustedAppRendererEvent,device-link 来源走 invoke 白名单 +worktree:sync-branch的baseRepo路径守卫(PATH_GUARDED_CHANNELS);payload 用requireObject/requireString,绝对路径、长度、NUL/控制字符、-前缀、..、字符类拒绝后再check-ref-format复核,杜绝 option 形参;错误不回传 Git 原始输出(远程 URL 可能含凭证); - 不涉及 URL / 导航 / 下载 / 自定义协议;6) CSP / Fuses 未放宽;
- 新边界有测试锁住:
deviceLinkHostDispatch.test.ts参数化覆盖worktree:create/worktree:sync-branch的路径守卫放行与拒绝。
- Renderer 新增能力仅为两条 IPC(只读状态查询 + 用户显式触发的拉取/快进),无新特权数据(回传的
docs/dev-rules/engineering-conventions.mdReview 清单:无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(CIclient-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。
|
@/tmp/pr7059-thanks.md |
这次改了什么
摘要
手动新建 worktree(主会话新建任务、创建 Worker 面板)时,源分支一直直接用本地分支、从不联网。本地
main落后远程时,新 worktree 就从旧代码开始,只能自己去终端git fetch/git pull。本 PR 在分支胶囊上加一个手动刷新按钮,让用户在不拖慢创建的前提下把源分支对齐到远程最新:[分支 ⟳ │ ☑ worktree],Worker 面板[分支 ⟳]),两处共用BranchWorktreeChip。点击只拉取选中分支对应的远程分支(按branch.<b>.remote+branch.<b>.merge,未配置时用origin同名分支;显式 refspec,30 秒上限,不等待凭证输入),然后只快进本地分支:update-ref(带旧值校验);main):在该目录git merge --ff-only --no-autostash;允许存在不相关的未提交改动,Git 会拒绝覆盖未提交改动;Spinner)/ 完成后 ✓ 约 2 秒并说明结果(已更新 N 个提交、已是最新、无需更新)/ 失败可重试并弹 toast。分叉、改动冲突、远程没有该分支、没有远程仓库时按钮变灰,变灰时仍可悬停看到原因;用户点击后才发现被拒时弹 warning。变灰判断只读本地 Git,不联网;缺少本地 tracking 缓存不视为远程没有该分支(仍可点击拉取确认)。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文档、测试或工程维护范围
freshBase(fix(desktop): 自动 worktree 改用 fetch 后的远端默认分支为基底 #1376),本 PR 不改它们。worktree:branch-sync-status(只读本地)/worktree:sync-branch(拉取并快进)两个 IPC、preload、device-link 白名单与sync-branch的 baseRepo 路径守卫;worktree:list-branches响应可选追加remoteDefaultBranch;胶囊按钮、状态行、远程分组;五种语言文案;协议兼容文档。upstream远程(fork 场景)的分组;手机端入口;Agentcreate_worker工具。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 同一渲染内核);真实组件与主题,场景数据,不是登录账号下的完整 Cindyf512dea3d61abranch-sync:light / dark · zh-CN / en · 560×400 / 360×400default:Main-task capsule, selected-branch details, remote group and successful fetchworker:Compact Worker branch-only capsuleunchecked:Unchecked main-task worktree excludes remote sourcesconflict:Disabled sync remains focusable and explains overlapping changesdiverged:Diverged branches keep local source and explain why sync is unavailableold-host:Old controlled host has neither refresh button nor remote group其余语言:
pnpm ui:check --page branch-sync --case all --theme all --locale all60/60 通过(zh-TW / ja / ko 已目检两段提示、分叉状态行与换行)。引用的设计规范:
--create-agent-control-bg-hover/pressed,常规用sidebar-item-hover,聚焦用--focus-ring),不新增颜色aria-activedescendant结构,新增分组标题与状态行只用既有文字色Spinner(HTML 外层旋转、--motion-spinner-cycle、减少动态效果时静止)i18n/GLOSSARY.md:worktree 保持英文小写怎么验证的
自动验证
新增 / 改写测试(engineering-conventions §3.2):
main/worktree/__tests__/branchSync.git-integration.test.ts(新)origin/HEAD缺失或悬空兜底、拉取期间并发写入main/worktree/__tests__/branchSyncHandlers.test.ts(新)renderer/components/new-chat/__tests__/BranchWorktreeChip.test.tsx(新)main/__tests__/worktreeReveal.test.ts(改)worktree:list-branches:远程主分支补充成功;探测超时不影响本地分支列表main/__tests__/deviceLinkHostDispatch.test.ts、packages/device-link/.../allowlist.test.ts(改)sync-branch纳入白名单与 baseRepo 路径守卫renderer/features/cc-agent/__tests__/CreateWorkerPopover.test.tsx(改)手工验证
macOS,隔离开发实例(独立用户数据目录),远程全部是临时目录里的本地裸仓库;agent-browser 为主、computer use 补充,主会话与 Worker 面板两个入口逐项执行。41 个逻辑用例:
origin/HEAD有效 / 缺失 / 悬空、main / master 兜底;不刷新直接创建取本地缓存;拉取被人为阻塞时创建照常完成(0.55–2.60s),起点为拉取前的完整提交,无锁冲突;路径含空格与中文;转圈连续动画与 ✓ 约 2 秒;变灰原因悬停;点击后被拒弹 warning、初始检查不弹;主会话 Escape 关闭下拉;浅色 / 深色动态状态。bce8ecf5ed,旧版为改动前的124508423d;在同一台 Mac 上起独立实例、登录同一账号,代替两台物理电脑):git-upload-pack的父进程是被控实例),无关的未提交改动和 stash 完整保留。通过 device-link 传入不存在的目录、文件路径、不可访问的目录时,分别被REMOTE_WORKDIR_NOT_FOUND/REMOTE_WORKDIR_NOT_DIRECTORY/REMOTE_WORKDIR_UNAVAILABLE拒绝。未执行的验证
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 改动范围内,未另建基线复跑。风险
风险分类
影响与回滚
sync-branch走 baseRepo 路径守卫,单次预留 90 秒、失败不重放),worktree:list-branches响应只追加可选字段。新控制端连旧被控端时,状态查询返回DEVICE_LINK_CHANNEL_NOT_ALLOWED即隐藏按钮、缺字段即不显示远程分组,选分支与创建保持原行为;旧控制端忽略新字段。提交前检查
git commit -s,见 DCO)