Skip to content

feat(mobile): 补齐伙伴与跨电脑远程控制 - #3912

Merged
MagicLizi merged 62 commits into
makecindy:mainfrom
zqchris:mobile-remote-resources
Sep 7, 2026
Merged

feat(mobile): 补齐伙伴与跨电脑远程控制#3912
MagicLizi merged 62 commits into
makecindy:mainfrom
zqchris:mobile-remote-resources

Conversation

@zqchris

@zqchris zqchris commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

这次改了什么

摘要

手机可以在“所有伙伴”中查看多台电脑托管的伙伴,并打开其长期任务继续工作;另一台 Mac 也能从伙伴任务卡读取状态、打开子任务、停止任务和回看只读私聊。原先这些卡片操作会直接调用控制端本机接口,本次改为始终携带来源电脑,并接上对应状态推送。

Desktop 伙伴依赖 #2829 已通过主干提交 f045326f1 合入,本分支已合并该主干;依赖先后条件已满足。手机与跨电脑能力继续由本 PR 交付,PR Ready 不代表安装版或 OTA 已发布。

变更类型

  • feat 新功能
  • fix 缺陷修复
  • docs / test / chore 文档、测试或工程维护

范围

  • 关联 Issue / 需求:手机伙伴体验、远程伙伴在线离线与 Mac 到 Mac 控制。
  • 本 PR 包含:资源发现与来源电脑路由;伙伴名册的账号隔离持久缓存、离线保留和重连核实;基于来源电脑可见回复的独立未读位置;手机任务卡、停止、子任务入口与只读私聊;托管头像、成果文件入口与只读运行模型展示。
  • 明确不包含:服务端修改、自主跨电脑调度、手机作为被控主机;伙伴创建、Profile 与长期技能维护仍由托管电脑负责。
  • 用户可见变化:一台电脑掉线时,其伙伴保留并显示离线,其它电脑继续可用;后台任务卡和私聊详情不再误读本机;用户消息与内部私聊留痕不产生伙伴未读;重连或任务恢复替换后重新解析伙伴的主任务。
  • 是否存在 breaking change:无。协议只追加可选字段和通道;旧主机不支持新通道时保留普通远程任务能力。共享消息标记定义原样迁到 maker-shared,Desktop 旧导入保留兼容出口。没有改手机原生依赖或配置。

UI 变化

  • 手机伙伴列表显示真实头像、在线状态点与克制的未读点;聊天内增加后台任务卡和只读私聊回看页,恢复成果入口和模型展示。Desktop 远程伙伴也显示未读提示。
  • 引用的设计规范:docs/design-rules/DESIGN.md §2 Color Palette & Roles、§5 Layout Principles、§8 Mobile、§10 Light / Dark Dual-Mode Delivery Gate、§11 Voice & Content。颜色与圆角使用既有语义 token,手机操作触控高度至少 44;Light/Dark 均实现,但本批没有实机目检证据。

界面效果证据(伙伴界面源码基准 e4e4ca5

按本次实际组件结构与文案制作的自包含 HTML 效果稿,覆盖:手机多电脑伙伴名册(在线/离线/未读)、任务内后台任务卡及私聊入口、手机只读私聊、另一台 Mac 的任务卡/私聊留痕和只读详情。包含 Light/Dark 切换和窄屏适配;手机色值及尺寸来自当前 apps/mobile/src/theme/tokens.ts。源码对应链接也在 HTML 内。

已用独立无头浏览器目检 Light/Dark 桌面展示宽度和 390px 窄屏。这是演示数据的静态组件效果稿,非安装版截图、React Native 实机渲染或两设备联网验收。 只展示本次相关组件区域,头像用首字占位,外围审查说明不进入产品;业务按钮不调用设备。没有启动 Cindy DEV、改变产品功能或生成新代码提交。

展开完整 HTML:复制保存为 cindy-3912-ui-evidence.html,即可离线打开
<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>伙伴移动与跨电脑界面效果 · 3912</title><style>*{box-sizing:border-box}body{margin:0;background:#f8f8f6;color:#262626;font:14px/1.5 Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}.report{max-width:1260px;margin:auto;padding:24px}h1{font-size:24px;font-weight:500;margin:0 0 8px}h2{font-size:18px;font-weight:500}.intro{max-width:850px;color:#62625e}.controls{display:flex;gap:8px;margin:18px 0 24px;flex-wrap:wrap}button{font:inherit;cursor:default;color:inherit;background:transparent;border:0}.controls button{cursor:pointer;border:1px solid #d7d7d4;border-radius:9999px;padding:9px 16px;min-height:44px}.controls button[aria-pressed=true]{background:#e5e5e5}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}figure{margin:0;min-width:0}figcaption{font-weight:500;margin-bottom:8px}.caption{font-size:12px;color:#686862;margin:8px 0 20px;line-height:1.6}.phone{width:100%;max-width:390px;min-height:490px;overflow:hidden;border:1px solid var(--border);border-radius:12px;background:var(--surface);color:var(--textPrimary)}.mobile small{font-size:13px;color:var(--textSecondary)}svg{width:18px;height:18px;flex-shrink:0;vertical-align:middle}.apphead{display:flex;align-items:center;gap:8px;padding:14px 12px;border-bottom:1px solid var(--border);min-height:70px}.apphead b{font-size:19px;font-weight:600;display:block}.apphead small{display:block}.back{width:32px;display:grid;place-items:center}.list{display:flex;flex-direction:column;gap:8px;padding:12px}.row{display:flex;align-items:center;gap:12px;min-height:78px;padding:8px 12px;border:1px solid var(--border);border-radius:12px;background:var(--surfaceListRow)}.avatar{position:relative;border-radius:9999px;display:grid;place-items:center;width:44px;height:44px;flex-shrink:0;background:var(--surfaceChip);font-size:19px}.presence{position:absolute;width:8px;height:8px;border-radius:9999px;bottom:0;right:0;background:var(--statusReady)}.presence.off{background:var(--textTertiary)}.rowbody{min-width:0;flex:1}.rowtitle{display:flex;align-items:baseline;gap:8px}.rowtitle b{font-size:19px;font-weight:600;flex:1;min-width:0}.rowtitle time{font-size:13px;color:var(--textTertiary);white-space:nowrap}.unread{width:7px;height:7px;flex-shrink:0;border-radius:9999px;background:var(--statusAwaiting)}.preview{font-size:16px;color:var(--textSecondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:4px 0}.rowbody>small{color:var(--textTertiary);display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chevron{color:var(--textTertiary);flex-shrink:0}.conversation{padding:12px}.sample-message{font-size:16px;line-height:1.6;margin:2px 0 14px}.mcard{margin:8px 0;padding:12px;border:1px solid var(--border);border-radius:12px;background:var(--surfaceElevated);display:flex;flex-direction:column;gap:4px;font-size:16px}.actions{display:flex;flex-wrap:wrap;gap:8px}.actions button{min-height:44px;padding:0 8px;color:var(--textSecondary);font-size:13px}.private-mobile{padding:16px;display:flex;flex-direction:column;gap:16px}.private-mobile p{margin:0;background:var(--surfaceElevated);padding:12px;font-size:16px;line-height:1.6}.wide{grid-column:1/-1}.desktop{--surface:#f8f8f6;--chip:#e5e5e5;--subtle:#f1f1ee;--border:#d7d7d4;--primary:#262626;--secondary:#6b6b66;--tertiary:#787872;--info:#3b82f6;--success:#16a34a;display:grid;grid-template-columns:1fr 1fr;border:1px solid var(--border);border-radius:12px;background:var(--surface);color:var(--primary);overflow:hidden;min-height:350px}.dark .desktop{--surface:#1f1f1e;--chip:#3c3c3a;--subtle:#2c2c2a;--border:#3c3c3a;--primary:#ededeb;--secondary:#a3a3a3;--tertiary:#989891;--info:#60a5fa;--success:#4ade80}.desktop-main,.desktop-private{padding:20px;min-width:0}.desktop-private{border-left:1px solid var(--border);display:flex;flex-direction:column}.dlabel{font-size:11px;color:var(--tertiary);margin-bottom:16px}.task-card{max-width:560px;margin:8px 0;padding:12px 16px;border:1px solid var(--border);border-radius:12px;background:var(--chip);font-size:12px}.task-top{display:flex;gap:12px;align-items:flex-start}.task-top>div{flex:1;min-width:0}.desktop small{font-size:11px;color:var(--tertiary)}.task-title{font-size:14px;font-weight:500;margin-top:2px}.status{border-radius:9999px;padding:4px 10px;background:var(--subtle);font-size:11px;color:var(--info);white-space:nowrap}.status.done{color:var(--success)}.tracked{display:flex;align-items:center;gap:8px;border-top:1px solid var(--border);padding-top:10px;margin-top:10px;color:var(--tertiary)}.tracked i{width:7px;height:7px;border-radius:9999px;background:var(--tertiary)}.tracked span{flex:1}.tracked time{font-size:11px}.dactions{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}.dactions button{display:flex;align-items:center;gap:6px;border:1px solid var(--border);border-radius:8px;padding:4px 10px;font-size:11px;color:var(--secondary)}.dactions svg{width:11px;height:11px}.trace{display:flex;align-items:center;gap:12px;padding:8px 0}.trace>i{height:1px;flex:1;background:var(--border)}.trace button{display:flex;align-items:center;gap:6px;border:1px solid var(--border);border-radius:9999px;padding:4px 10px;font-size:11px;color:var(--secondary)}.trace svg{width:12px;height:12px}.tiny-avatar{width:24px;height:24px;display:inline-grid;place-items:center;background:var(--chip);border-radius:9999px;flex-shrink:0;font-size:11px}.trace .tiny-avatar{width:18px;height:18px}.dm{display:flex;gap:10px;margin:10px 0;align-items:flex-start}.dm>div{max-width:74%;min-width:0}.dm.own{justify-content:flex-end}.dm.own small{display:block;text-align:right}.dm p{border:1px solid var(--border);border-radius:12px;background:var(--chip);padding:10px 14px;margin:4px 0;font-size:14px;line-height:1.6}.desktop footer{margin-top:auto;padding-top:14px;display:flex;justify-content:center;align-items:center;gap:8px;border-top:1px solid var(--border)}.desktop footer button{border:1px solid var(--border);border-radius:9999px;padding:7px 12px;font-size:11px}.desktop footer svg{width:12px;height:12px}.notes{border-top:1px solid #d7d7d4;padding-top:16px;color:#62625e;font-size:13px}.notes a{color:inherit;overflow-wrap:anywhere}.theme[hidden]{display:none}@media(max-width:700px){.report{padding:16px}.grid{grid-template-columns:1fr}.phone{max-width:none;min-height:440px}.desktop{grid-template-columns:1fr}.desktop-private{border-left:0;border-top:1px solid var(--border);min-height:320px}.desktop-main,.desktop-private{padding:14px}h1{font-size:20px}}@media print{.controls{display:none}.theme[hidden]{display:block}.theme{break-before:page}}.light .mobile{--surface:#EDEDED;--surfaceElevated:#F8F8F8;--surfaceListRow:#F6F6F6;--surfaceChip:#F1F1F1;--border:#C6C9CE;--textPrimary:#3C3F43;--textSecondary:#8C8E94;--textTertiary:#686B72;--statusReady:#19D2C1;--statusAwaiting:#19D2C1}.dark .mobile{--surface:#2A2828;--surfaceElevated:#312F2F;--surfaceListRow:#312F2F;--surfaceChip:#2F2D2D;--border:#434343;--textPrimary:#D4D4D4;--textSecondary:#6F6F6F;--textTertiary:#BFC1C4;--statusReady:#19D2C1;--statusAwaiting:#19D2C1}</style><body><main class="report"><h1>伙伴 · 手机与跨电脑界面效果</h1><p class="intro">当前代码 <code>e4e4ca57</code> 的静态 HTML 效果稿。采用演示数据,按实际组件结构、文案与主题 token 复刻,用于审核布局和信息层级;不是安装版截图或联网操作验收。外层标题、主题切换与说明属于证据页,不进入产品。</p><nav class="controls" aria-label="效果稿主题"><button data-mode="light" aria-pressed="true">Light</button><button data-mode="dark" aria-pressed="false">Dark</button><button data-mode="both" aria-pressed="false">同时查看两种模式</button></nav><section class="theme light" data-theme="light" ><h2>Light</h2><div class="grid"><figure><figcaption>手机 · 伙伴名册</figcaption><div class="phone mobile"><header class="apphead"><span class="back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg></span><div><b>所有伙伴</b><small>2 台电脑</small></div></header><div class="list"><div class="row" role="button" aria-disabled="false"><span class="avatar">C<i class="presence "></i></span><div class="rowbody"><div class="rowtitle"><b>Cindy</b><i class=unread></i><time>14:32</time></div><div class="preview">已整理好周报,可以查看了。</div><small>已启用 · 办公室 Mac</small></div><span class="chevron"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></span></div><div class="row" role="button" aria-disabled="false"><span class="avatar">D<i class="presence "></i></span><div class="rowbody"><div class="rowtitle"><b>Dash</b><time>14:28</time></div><div class="preview">正在核对本周的关键进展。</div><small>已启用 · 办公室 Mac</small></div><span class="chevron"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></span></div><div class="row" role="button" aria-disabled="true"><span class="avatar">L<i class="presence off"></i></span><div class="rowbody"><div class="rowtitle"><b>LiZi</b><time>昨天</time></div><div class="preview">上次的评审结论已整理。</div><small>离线 · 家里的 Mac</small></div><span class="chevron"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></span></div></div></div><p class="caption">在线与离线来自来源电脑;未读使用独立位置。离线行不可打开。</p></figure><figure><figcaption>手机 · 伙伴任务内卡片</figcaption><div class="phone mobile"><header class="apphead"><span class="back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg></span><div><b>Cindy</b><small>办公室 Mac</small></div></header><div class="conversation"><p class="sample-message">我会继续核对资料,结果会回到这里。</p><section class="mcard"><small>后台任务</small><div>核对周报中的数据</div><small>运行中</small><div class="actions"><button>查看任务</button><button>停止任务</button></div></section><section class="mcard"><div>与 LiZi 的私聊</div><small>请帮我复核这一段结论。</small></section><section class="mcard"><small>后台任务</small><div>整理上周的会议记录</div><small>已完成</small><small>会议纪要已整理,可回看完整过程。</small><div class="actions"><button>查看任务</button></div></section></div></div><p class="caption">任务卡有查看/停止入口;私聊入口保持独立。这里的内容为演示数据。</p></figure><figure><figcaption>手机 · 私聊回看</figcaption><div class="phone mobile"><header class="apphead"><span class="back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg></span><div><b>Cindy · LiZi</b><small>仅供查看</small></div></header><div class="private-mobile"><p>Cindy<br>请帮我复核这一段结论。</p><p>LiZi<br>已核对,结论与原始记录一致。</p></div></div><p class="caption">按来源电脑读取参与者消息。只读页面没有输入框。</p></figure><figure class="wide"><figcaption>另一台 Mac · 远程任务卡、私聊留痕与只读回看(组件区域)</figcaption><div class="desktop"><div class="desktop-main"><div class="dlabel">远程伙伴任务中的消息区域</div><div class="task-card"><div class="task-top"><div><small>后台任务</small><div class="task-title">核对周报中的数据</div></div><span class="status">正在做</span></div><div class="tracked"><i></i><span>独立运行并自动回传结果</span><time>2 分钟</time></div><div class="dactions"><button><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="2"/></svg>停止任务</button><button><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 3h6v6M10 14 21 3M10 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5"/></svg>看工作过程</button></div></div><div class="trace"><i></i><button><span class="tiny-avatar">L</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16l-4-4M20 17H4l4 4"/></svg>已发消息给 LiZi<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></button><i></i></div><div class="task-card"><div class="task-top"><div><small>后台任务</small><div class="task-title">整理会议纪要</div></div><span class="status done">已完成</span></div><div class="tracked"><i></i><span>独立运行并自动回传结果</span><time>3 分钟</time></div><p>会议纪要与待办已整理完成。</p><small>会议纪要.html</small><div class="dactions"><button><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 3h6v6M10 14 21 3M10 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5"/></svg>看工作过程</button></div></div></div><div class="desktop-private"><div class="dlabel">私聊详情中的消息区域</div><article class="dm own"><div><small>Cindy · 14:30</small><p>请帮我复核这一段结论。</p></div><span class="tiny-avatar">C</span></article><article class="dm"><span class="tiny-avatar">L</span><div><small>LiZi · 14:31</small><p>已核对,结论与原始记录一致。</p></div></article><footer><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5" y="10" width="14" height="11" rx="2"/><path d="M8 10V6a4 4 0 0 1 8 0v4"/></svg><small>此对话仅供查看</small><button>关闭对话</button></footer></div></div><p class="caption">保持现有卡片外观;读取、停止、打开子任务和私聊均沿来源电脑路由。图中不额外增加设备徽标或产品提示。</p></figure></div></section><section class="theme dark" data-theme="dark" hidden><h2>Dark</h2><div class="grid"><figure><figcaption>手机 · 伙伴名册</figcaption><div class="phone mobile"><header class="apphead"><span class="back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg></span><div><b>所有伙伴</b><small>2 台电脑</small></div></header><div class="list"><div class="row" role="button" aria-disabled="false"><span class="avatar">C<i class="presence "></i></span><div class="rowbody"><div class="rowtitle"><b>Cindy</b><i class=unread></i><time>14:32</time></div><div class="preview">已整理好周报,可以查看了。</div><small>已启用 · 办公室 Mac</small></div><span class="chevron"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></span></div><div class="row" role="button" aria-disabled="false"><span class="avatar">D<i class="presence "></i></span><div class="rowbody"><div class="rowtitle"><b>Dash</b><time>14:28</time></div><div class="preview">正在核对本周的关键进展。</div><small>已启用 · 办公室 Mac</small></div><span class="chevron"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></span></div><div class="row" role="button" aria-disabled="true"><span class="avatar">L<i class="presence off"></i></span><div class="rowbody"><div class="rowtitle"><b>LiZi</b><time>昨天</time></div><div class="preview">上次的评审结论已整理。</div><small>离线 · 家里的 Mac</small></div><span class="chevron"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></span></div></div></div><p class="caption">在线与离线来自来源电脑;未读使用独立位置。离线行不可打开。</p></figure><figure><figcaption>手机 · 伙伴任务内卡片</figcaption><div class="phone mobile"><header class="apphead"><span class="back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg></span><div><b>Cindy</b><small>办公室 Mac</small></div></header><div class="conversation"><p class="sample-message">我会继续核对资料,结果会回到这里。</p><section class="mcard"><small>后台任务</small><div>核对周报中的数据</div><small>运行中</small><div class="actions"><button>查看任务</button><button>停止任务</button></div></section><section class="mcard"><div>与 LiZi 的私聊</div><small>请帮我复核这一段结论。</small></section><section class="mcard"><small>后台任务</small><div>整理上周的会议记录</div><small>已完成</small><small>会议纪要已整理,可回看完整过程。</small><div class="actions"><button>查看任务</button></div></section></div></div><p class="caption">任务卡有查看/停止入口;私聊入口保持独立。这里的内容为演示数据。</p></figure><figure><figcaption>手机 · 私聊回看</figcaption><div class="phone mobile"><header class="apphead"><span class="back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg></span><div><b>Cindy · LiZi</b><small>仅供查看</small></div></header><div class="private-mobile"><p>Cindy<br>请帮我复核这一段结论。</p><p>LiZi<br>已核对,结论与原始记录一致。</p></div></div><p class="caption">按来源电脑读取参与者消息。只读页面没有输入框。</p></figure><figure class="wide"><figcaption>另一台 Mac · 远程任务卡、私聊留痕与只读回看(组件区域)</figcaption><div class="desktop"><div class="desktop-main"><div class="dlabel">远程伙伴任务中的消息区域</div><div class="task-card"><div class="task-top"><div><small>后台任务</small><div class="task-title">核对周报中的数据</div></div><span class="status">正在做</span></div><div class="tracked"><i></i><span>独立运行并自动回传结果</span><time>2 分钟</time></div><div class="dactions"><button><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="2"/></svg>停止任务</button><button><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 3h6v6M10 14 21 3M10 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5"/></svg>看工作过程</button></div></div><div class="trace"><i></i><button><span class="tiny-avatar">L</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16l-4-4M20 17H4l4 4"/></svg>已发消息给 LiZi<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></button><i></i></div><div class="task-card"><div class="task-top"><div><small>后台任务</small><div class="task-title">整理会议纪要</div></div><span class="status done">已完成</span></div><div class="tracked"><i></i><span>独立运行并自动回传结果</span><time>3 分钟</time></div><p>会议纪要与待办已整理完成。</p><small>会议纪要.html</small><div class="dactions"><button><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 3h6v6M10 14 21 3M10 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5"/></svg>看工作过程</button></div></div></div><div class="desktop-private"><div class="dlabel">私聊详情中的消息区域</div><article class="dm own"><div><small>Cindy · 14:30</small><p>请帮我复核这一段结论。</p></div><span class="tiny-avatar">C</span></article><article class="dm"><span class="tiny-avatar">L</span><div><small>LiZi · 14:31</small><p>已核对,结论与原始记录一致。</p></div></article><footer><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5" y="10" width="14" height="11" rx="2"/><path d="M8 10V6a4 4 0 0 1 8 0v4"/></svg><small>此对话仅供查看</small><button>关闭对话</button></footer></div></div><p class="caption">保持现有卡片外观;读取、停止、打开子任务和私聊均沿来源电脑路由。图中不额外增加设备徽标或产品提示。</p></figure></div></section><section class="notes"><p>界面稿的边界:只展示本次接入的组件区域,省略系统状态栏、完整任务输入区及外围侧栏;头像使用姓名首字占位,时间与消息为固定示例。卡片上的业务按钮仅展示外观,不调用设备接口。两端文案、布局、字号刻意按各自现有实现展示。</p><p>源码依据:</p><ul><li><a href="https://github.com/makecindy/cindy/blob/e4e4ca5721d5fa2d02c032b2c57818de531bb182/apps/mobile/app/resources/[collectionId].tsx">apps/mobile/app/resources/[collectionId].tsx</a></li><li><a href="https://github.com/makecindy/cindy/blob/e4e4ca5721d5fa2d02c032b2c57818de531bb182/apps/mobile/src/session/CompanionMessageCard.tsx">apps/mobile/src/session/CompanionMessageCard.tsx</a></li><li><a href="https://github.com/makecindy/cindy/blob/e4e4ca5721d5fa2d02c032b2c57818de531bb182/apps/mobile/app/companions/direct/[threadId].tsx">apps/mobile/app/companions/direct/[threadId].tsx</a></li><li><a href="https://github.com/makecindy/cindy/blob/e4e4ca5721d5fa2d02c032b2c57818de531bb182/apps/mobile/src/theme/tokens.ts">apps/mobile/src/theme/tokens.ts</a></li><li><a href="https://github.com/makecindy/cindy/blob/e4e4ca5721d5fa2d02c032b2c57818de531bb182/apps/desktop/src/renderer/features/bots/BotCollaborationCard.tsx">apps/desktop/src/renderer/features/bots/BotCollaborationCard.tsx</a></li><li><a href="https://github.com/makecindy/cindy/blob/e4e4ca5721d5fa2d02c032b2c57818de531bb182/apps/desktop/src/renderer/features/bots/BotDirectMessageCard.tsx">apps/desktop/src/renderer/features/bots/BotDirectMessageCard.tsx</a></li><li><a href="https://github.com/makecindy/cindy/blob/e4e4ca5721d5fa2d02c032b2c57818de531bb182/apps/desktop/src/renderer/features/bots/BotDirectMessageView.tsx">apps/desktop/src/renderer/features/bots/BotDirectMessageView.tsx</a></li><li><a href="https://github.com/makecindy/cindy/blob/e4e4ca5721d5fa2d02c032b2c57818de531bb182/docs/design-rules/DESIGN.md">docs/design-rules/DESIGN.md</a></li></ul><p>行为证据仍以对应回归测试为准:来源电脑路由、断线后状态、停止归属、隐藏伙伴拒绝访问和已读时机,不由本静态稿证明。本页不增加、删减或改变伙伴定稿。</p></section></main><script>function mode(v){document.querySelectorAll("[data-theme]").forEach(e=>e.hidden=v!=="both"&&e.dataset.theme!==v);document.querySelectorAll("[data-mode]").forEach(e=>e.setAttribute("aria-pressed",String(e.dataset.mode===v)))}document.querySelectorAll("[data-mode]").forEach(e=>e.onclick=()=>mode(e.dataset.mode));if(["dark","both"].includes(location.hash.slice(1)))mode(location.hash.slice(1));</script></body></html>

怎么验证的

自动验证

  • pnpm test:unit:related:共享 package exports 变化触发完整单测,最后一轮完整通过(含 Desktop、Mobile 与 maker-core)。
  • pnpm --filter desktop run --if-present typecheckpnpm --filter mobile run --if-present typecheck:通过。其余涉及 package 按约定执行 --if-present typecheck,未定义脚本的自动跳过。
  • pnpm --filter @cindy/device-link run build:通过。
  • 新增集成回归覆盖来源电脑读取/停止/打开、另一 peer 推送隔离、重连更新、账号与连接代际丢弃旧回复、冷启动缓存、可见回复未读、只读私聊;相关 Desktop 与 Mobile 定向测试通过。
  • pnpm --filter mobile run test:scopepnpm --filter mobile run test:smoke(2 项)、pnpm check:i18n-glossary、设计清单生成与 diff 检查:通过。
  • ci-fingerprint.mjs compute:与 Desktop 依赖基线比较,iOS 均为 96e76c9f4cb4fd4c990fb09e631e8ab42d61583e,Android 均为 20a7dee6fb588f451c59b37deec3faf7e37a8b41;原生配置文件与 main 无差异。
  • 附加检查 pnpm --filter @cindy/maker-shared run build 有基线既存错误(composerPalette fixture 的 name 字段与 workRunGrouping 的 ES lib 配置);在未改的 Desktop 依赖 worktree 复现同样错误,相关文件与 main 一致。本次没有改这些范围来制造绿灯;Desktop/Mobile 消费者类型检查通过。
  • 完整单测中曾遇到未修改的 CustomProviderDialogAccessibility 悬停 tooltip 用例偶发失败;该套单独复跑 27 项通过,记录保留。

手工验证

本批没有启动 Desktop DEV、Mobile DEV、Metro 或正式版,也没有连接真实 iPhone。工作分支 mobile-remote-resources,worktree 为同名独立目录;无 Metro 归属与 DEV build label,因此没有手机实机验收结论。

未执行的验证

两台安装版 Mac 的实际联网控制、iPhone Light/Dark 实机与商店/OTA 发布未执行。Windows 数据库回归已在上一 head 3bd1572e 的 CI 重跑通过;当前新 head 等待本轮 CI。模拟传输集成测试不代表安装版本已经端到端联通;电脑与手机需包含对应接口后才可交付该能力。

本轮审查修复(2026-09-06)

  • 隐藏/归档伙伴的已知任务 ID 在远程任务/消息读取、发送/steer、active 列表及推送边界统一校验;缓存和断线暂存回复发送前复查,手机收到资源 NOT_FOUND 时离开缓存任务页。本机管理与历史读取保留。
  • 新建伙伴 ID 使用跨平台目录安全格式,并拒绝与存量伙伴目录发生归一化/大小写别名碰撞;存量目录映射不迁移、不删除。
  • 后台任务与 Skill 的真实调用方解析同时要求伙伴启用、任务启用且关联未归档,暂停后进程尚未退出也不能继续发起工作。
  • 数据库测试改用独立系统临时目录和哈希账号目录;Linux / Windows CI 第一分片显式执行伙伴数据库回归,覆盖普通 unit tier 原本排除的 localDb 测试。Windows 实际通过证据已取得:上一 head 3bd1572e 的重跑 job 101451325869 中数据库回归步骤 SUCCESS;新 head 仍需本轮 CI。
  • 可读复审第 5 项已补修:列表点击仅导航,只有目标任务已完成本连接代内容同步、已展示消息且页面聚焦时才写已读;主任务替换须等新任务进入并同步。覆盖资源读取/链接/Session 读取/断线失败、列表点击及替换任务的回归。
  • 已补第 3/4 项的目录删除隔离、legacy 路径归一化碰撞,以及真实 pause 流程中关闭延迟/失败的权限回归。
  • 第 2 项不采纳删掉普通 Session 控制 DTO 目录字段的建议:系统路径禁令适用于资源响应,该响应和委派成果投影保持不含绝对路径;普通远程 Session 的工作目录是手机发送、附件及成果浏览依赖的既有控制契约。本批不以删除既有能力或另造协议来满足该建议。

风险

风险分类

  • SQLite / migration(继承 Desktop 依赖,本次没有新增或修改 migration)
  • system prompt(继承 Desktop 依赖的伙伴工具面收口)
  • 协议兼容
  • 权限 / 安全 / 用户数据
  • 跨平台差异
  • 原生层 / fingerprint / OTA

影响与回滚

  • 影响范围:伙伴的手机与远程 Desktop 投影。调用仍由同账号、已授权设备互联入口进入;停止校验任务归属,私聊校验参与者。远端任务列表使用明确字段投影,不返回数据库行、权限或运行时快照。
  • 故障半径:单次查询或单个 peer 失败只影响该来源;整条 relay 断线才使全部来源离线。远程伙伴可见性在主机数据库中校验;推送发送前按 peer 有界排队,缓存回复及断线暂存回复重发前重新检查,不重跑原来的操作。恢复不重启 relay、不清除其它 peer;两控制端回归覆盖单个 peer 发送失败时另一个仍按序收到消息。晚到结果受账号和连接代际约束。
  • 存量插件影响:无,没有改批准、安装布局或凭证。手机与 Desktop 缓存按账号隔离且不缓存在线授权结论。
  • 回滚 / 降级方式:回退手机资源和跨电脑卡片接线,普通远程任务继续使用原接口;不要删除伙伴数据表或回退历史 migration。旧主机能力缺失时相应卡片显示无法核实/重试,不降级调用本机。

提交前检查

  • 已 review 完整 diff,逐文件核对 Desktop 依赖来源及本次集成差异
  • 每个 commit 都带 DCO 签名(git commit -s
  • UI 改动已注明引用的设计规范章节
  • 未提交凭证、令牌或授权文件
  • 已补充必要文档
  • 已确认测试结果并说明未执行范围

受保护 CI 路径的人工处理

本 PR 修改了 .github/workflows/ci.yml,auto-review 已通知停止自动审查与自动合并,需 Lizi / 维护者人工处理。

这处改动仅在现有 Linux、Windows 单测矩阵的首个分片追加 botCanonicalSession.test.tsbotRemoteResourceProvider.test.ts 两个数据库回归套件,补足常规 unit tier 排除 localDb 的覆盖缺口。保留现有 required checks 与测试断言;不移除覆盖来绕过受保护路径门禁。伙伴定稿和跨设备功能范围保持不变。

本地全量单测、Desktop/Mobile typecheck 及定向回归已通过;本机未运行 Windows,Windows 执行结果以当前 head 的 CI 为准。请求人工核对该 CI 改动并完成本轮复审。

与最新主干同步后的冲突处置

已将 d36a78ddc 合入当前 head 3bd1572e70cfe43aa4c5b9a7bb8b0a283959ae5d,解决 Desktop dispatch 与 device-link allowlist 冲突。保留伙伴定稿、资源通道与主干手机弱网正文恢复;新增的订阅及延迟正文快照也经过既有 DB 伙伴可见性检查及每个控制端的发送队列,维持旧增量 → 快照 → 新增量顺序,异步发送失败沿既有恢复路径重试。

故障半径:处理单个控制端的队列背压或快照发送失败,只暂存该控制端对应任务的恢复;不重建共享 relay。保留主干多控制端拥塞隔离回归,并新增异步可见性检查、隐藏伙伴的订阅/恢复快照拒绝和异步发送失败恢复用例。

验证:pnpm test:unit:related(自动退回全量)通过;Desktop/Mobile typecheck、手机 scope、设计清单与 DCO 通过。推送定向 38 项、伙伴数据库 114 项通过。未启动客户端或在本机执行 Windows;Windows 以当前 head CI 为准。受保护 .github/workflows/ci.yml 的人工审核门继续保留,尚未合并发布。

删除失败的状态保护补齐

当前 head 797de0c2e5ad8703a94895289a06358e564b6b14 同步 PC 分支 019d212b9a6b6afeb769b0e2b8f20d1c0e682411 的四文件修复:删除前调用 bots.assertNoSharedHistory,已有共享委派或私聊历史时,在暂停、归档、关闭和取消任务之前拒绝。最终删除事务继续复用相同检查,保护检查期间新增的引用。没有删改伙伴定稿。

服务层四种共享历史回归验证被拒后 Profile、canonical Session、link 完全不变,没有 close/cancel/delete 副作用,仍能正常暂停和恢复。129 项定向回归、Desktop typecheck、pnpm test:unit:related(全量回退)及 DCO 通过。

Windows 验证记录已核实更新:上一 head 3bd1572e 的重跑 job 101451325869Run companion database regressions 确实 SUCCESS;不再视为 Windows DB 未执行。本次新 head 的 CI 尚待运行结果。受保护 CI 路径仍需维护者人工处理,尚未合并发布。

最新主干合并与提示词确认记录

当前 head 26aab5c53eedfcdb07b39f8c0436dca4cda8bc52 已合入主干 5fc588110,保留删除预检修复 797de0c2e、伙伴记忆/权限配置与主干模型窗口配置,并重新生成设计清单。合并后本地完整 pnpm test:unit:related、Desktop/Mobile typecheck、129 项伙伴/数据库回归、手机 scope、设计清单及 DCO 全部通过。依赖安装仅按现有锁文件补齐工作区连接,无客户端启动。

维护者明确确认“伙伴专属提示词不会注入普通任务或 Reviewer 任务”,已同步为 PC 伙伴 PR 的公开记录。该确认仅覆盖提示词注入范围。删除与私聊写入竞态已在下述共享锁修复中补齐;当前版本缓存命中率对照仍需独立实测证据,不能用旧 usage 记录代替。受保护 CI 路径及人工复审门继续保留,尚未合并发布。

活动推送背压遗漏同步修复

当前 head ab6ee936bd7e41efe241899951e5e5124d3d4f3c 已核实并同步 PC 伙伴分支转交的最小修复:异步伙伴可见性检查队列满时,同步 BACKPRESSURE 不再删除尚未发送的活动状态,保留暂存并沿现有按控制端重试。异步失败仍不覆盖同一任务较新的暂存状态;权限校验、账号/连接代际、队列上限与断线清理保持不变。

真实 dispatch 回归挂起 DB lookup,连续发送 65 个不同任务的 completed 活动,再释放 lookup:修复前稳定只有 64 条,修复后 65 条全部送达且最后一条正确。整套 dispatch 回归 39 项、Desktop typecheck、pnpm test:unit:related(完整单测回退)、DCO 与 diff 检查通过。本轮仅两文件变更,未调整或删减伙伴定稿;未启动客户端。新 head 的外部 CI 与人工复审待处理,受保护 CI 路径的人工门继续保留。

删除与私聊写入竞态补齐

当前 head 00b032dd8f6a57422ace6ef016f023f89a8e0898,对应 PC 修复提交 d137fb77a82f5027afeab7b8f8e5a03f0b1a2e85;三个产品文件逐一比对一致。

已核实并同步 PC 伙伴分支转交的删除/私聊写入竞态修复。

删除预检通过后,晚到私聊曾可继续写入共享记录,导致最终删除失败而伙伴已暂停、归档。本轮将现有去重生命周期动作和私聊写入纳入同一组按 Bot ID 排序的锁;私聊取得双方锁后重新读取 active/canonical/unarchived 状态再写入。保留提前检查及最终数据库 guard,不新增 schema、migration 或 wire,不调整或删减伙伴定稿。

真实 SQLite 与两个服务的双顺序回归:旧实现 delete-first 失败;修复后删除先开始时晚到私聊拒绝、没有共享记录写入;私聊先写入时删除拒绝,Profile/Session/link 不变,没有关闭副作用,仍可 pause/resume。

验证:真实数据库/私聊/生命周期 154 项(115 + 24 + 15)通过,Desktop typecheck 通过,pnpm test:unit:related 完整复跑通过,DCO 与 diff 检查通过。首次完整单测曾出现未改动的 codexAuthBindingClaim.test.ts 5 秒超时和 cindySubagentForeground.test.ts 提前停止时序失败;分别原样复跑 9 项、4 项通过,随后重新运行完整门禁通过。没有提高超时、跳过或弱化测试;未启动客户端。

新 head 的 Windows/Linux CI 与人工复审仍需各自结果;.github/workflows/ci.yml 受保护路径人工门继续保留。伙伴提示词范围沿用已公开确认,缓存命中率对照尚未完成。本轮没有新增可 Resolve 的独立讨论线程,不代替维护者解除整体 CHANGES_REQUESTED;尚未合并发布。

PC 伙伴合入主干后的冲突处置

此前 head e4e4ca5721d5fa2d02c032b2c57818de531bb182 已合并主干 f045326f1(包含 Desktop 伙伴 #2829)。此次冲突来自共享伙伴文件在主干以 squash 方式新增;逐项比对双方后,保留手机分支的来源电脑路由、远程停止/子任务/只读私聊、离线缓存、独立未读位置、共享类型出口与安全投影。主干新增的已发现伙伴 ID 隐藏/归档后拒绝访问、暂停后 Skill 写入拒绝及 paused-main 私聊拒绝回归同时保留。

手机源码、活动背压、DB 远程可见性与删除/私聊共享锁相对合并前未变;主干 Library 合同与键帽规范原样接入,设计清单从合并结果重新生成。没有调整或删减伙伴定稿。

验证:pnpm test:unit:related(完整回退)全部通过;Desktop/Mobile typecheck、156 项伙伴数据库/资源/私聊/生命周期回归、手机 scope、设计清单及 DCO 通过。未启动客户端或改手机原生配置。新 head 外部 CI 与人工复审仍待结果;受保护 CI 路径人工门继续保留,手机 PR 尚未合并发布。

再次同步主干后的冲突处置(2026-09-06)

此前 head 9f93cef06442fae302910dae4d829fa7cc573df7 已合并主干 ea5f9d1b4c83f7adb92e1f021ae709a6cce4d608。唯一文本冲突是自动生成的设计清单,已保留双方一致的人工维护部分,按合并后源码重新生成;register.ts 中主干的插件任务权限审查接线及空草稿保护自动合入并逐项复核。其他传入文件与主干一致。

手机伙伴、来源电脑路由、在线/离线缓存、远程控制、伙伴界面及共享安全修复与此前 head 保持一致,没有增删或调整定稿需求。上方 HTML 的伙伴界面源码基准仍为 e4e4ca57,此次合并没有改动其展示的伙伴组件,因此效果证据继续适用;它仍仅是静态界面证据,不能替代真机或双 Mac 联调。

验证:根 pnpm test:unit:related(自动回退全量)通过;Desktop/Mobile typecheck 通过;伙伴数据库与生命周期/私聊定向 156 项通过;移动端 scope、设计清单、diff 与 DCO 检查通过。maker-core 无 typecheck script,不把 --if-present 跳过记作类型检查通过。当前 head 的外部 CI 与人工审核继续由既有跟进处理;受保护 CI 路径的人工门保持不变。

已读恢复时序与远程私聊查看者检查(2026-09-06)

当前 head 02402586e0c26853fb3ab7572369e5e657abe414 处理 review 5125634447 的两项原目标内缺陷:

  • 手机伙伴已读门增加非空 contentRecoveryKey === contentSyncedKey 检查。订阅 ACK 前的旧快照、ACK 已到但补拉尚未落地、旧 ACK 的快照均不能清伙伴未读;当前 ACK 对应的内容同步完成后才恢复原有已读流程。
  • maker:bot-direct-message-thread:get 在现有远程边界按第二个参数 viewerBotId 查询 Bot 可见性,不再把 opaque thread ID 当成 Session ID。隐藏、归档或已删除的查看者被拒;既有参与者校验保留,正常可见伙伴和本地 Desktop 阅读规则不变。该边界复用于调用前后及缓存/排队响应投递,避免隐藏后重放旧私聊响应。

先在旧代码上复现未读提前清除、不可见查看者被放行和缓存重放泄漏,再验证修复。定向测试:Mobile 39 项、Desktop 分发/私聊 56 项、真实 SQLite 伙伴库 115 项通过;根 pnpm test:unit:related 全量通过,Desktop/Mobile typecheck、移动端 scope、diff 与 DCO 检查通过。

不新增 schema、wire 字段、allowlist 能力或界面,不调整定稿需求。恢复动作只约束当前任务的伙伴已读时点,不改变重试、link 或 relay 生命周期,不扩大其它控制端的故障范围。界面效果证据保持适用,仍未启动 DEV 或做真机/双 Mac 联调。受保护 CI 路径的人工审查门保持不变。

zqchris and others added 19 commits September 2, 2026 22:22
伙伴是永久 Profile + 可替换物理 Session 的两层结构:SOUL/记忆/自有技能落在
账号隔离的 Bot Home,canonical 卷每日 04:00 CAS 换代并归档,模型走 1-5 项
候选链,只有「候选不可用」才推进。运行时按 allowlist 装配能力:不继承
Cindy 全局 Skill/MCP/项目上下文;pi 关闭原生 subagent 扩展并传
--no-context-files,codex 置 project_doc_max_bytes=0,显式挂载 docs 工具集
时 cindy_docs 才进入 MCP allowlist —— 提示词承诺与工具面同进同退。
数据库为 6 张只增量新表(migration 0101)。

Signed-off-by: zqchris <chrisz83@gmail.com>
协作只有一个直接入口 collaborate_with_bot:status 查空闲,notify 发不追踪
的消息,delegate 委派给另一个伙伴,start_task 把大活开成一条真正的 Cindy
任务(出现在主任务列表、走自己的权限门)。两种委派共用同一张 bot_delegations
表(target_bot_id 为空即 Cindy 任务)、同一张实时协作卡与同一条完成信号。

完成信号重做:不再往时间线落机读文本,改为 synthetic-trigger 隐藏行 ——
对模型是接手指令,对用户不可见,可见终态由协作卡承载;发起方父卷被每日
换卷归档时改投该伙伴当前 canonical 卷,不静默丢失。委派服务不再依赖
automation 上下文、token 预算层、投递 outbox 与 IM 路由。

Signed-off-by: zqchris <chrisz83@gmail.com>
左侧伙伴名册(IM 式未读)、复用真实任务与 ChatInput 的聊天面、@伙伴结构化
引用,以及只剩三页的设置(成长/模型/维护)。创建收敛成「名字 + 自动色相
头像 + 人设文本」,不暴露 Session、压缩、fallback 等工程概念;记忆与自学
技能在设置页可见、可删。五语言 i18n 同步。

Signed-off-by: zqchris <chrisz83@gmail.com>
《Cindy 伙伴运行时》契约与工程完成矩阵按 v1 范围重写:Bot Home 权威边界、
每日换卷、模型候选链、能力 allowlist、委派与完成信号的呈现契约;设计规范
登记伙伴头像色相与未读徽章的窄作用域 token,并把头像图收敛为保留命名空间。

Signed-off-by: zqchris <chrisz83@gmail.com>
worktree 回收器与通用任务生命周期入口跳过 source='bot' 的会话 —— 伙伴卷的
归档与替换只归 Bot Renew 管;崩溃恢复快照剥离 Bot 宿主瞬态引用。

Signed-off-by: zqchris <chrisz83@gmail.com>
术语表移除已退出 v1 的「作品」「日程」两条,Teammate 描述收敛到当前范围;
botPersona 不再引用已删除的模板文件。

Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
# Conflicts:
#	apps/desktop/src/main/localDb/ipc/sessions.ts
#	docs/design-rules/design-inventory.md
#	packages/maker-core/src/agents/claude-code/index.ts
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>

# Conflicts:
#	apps/desktop/drizzle/meta/0101_snapshot.json
#	apps/desktop/drizzle/meta/_journal.json
#	docs/design-rules/design-inventory.md
#	i18n/GLOSSARY.md
@zqchris
zqchris force-pushed the mobile-remote-resources branch from 4d5d3b6 to fc2279e Compare September 4, 2026 09:16
zqchris and others added 10 commits September 4, 2026 17:23
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>

# Conflicts:
#	apps/desktop/drizzle/meta/0101_snapshot.json
#	apps/desktop/drizzle/meta/_journal.json
#	apps/desktop/src/main/localDb/client/tx/types.ts
#	apps/desktop/src/main/localDb/worker/opHandlers/tx.ts
#	apps/desktop/src/main/maker-ipc/register.ts
#	apps/desktop/src/renderer/themes/__tests__/fixtures/desktop-color-defaults.json
#	docs/design-rules/design-inventory.md
#	i18n/GLOSSARY.md
#	packages/maker-core/src/agents/codex/index.ts
Signed-off-by: zqchris <chrisz83@gmail.com>
Signed-off-by: zqchris <chrisz83@gmail.com>

# Conflicts:
#	apps/desktop/src/renderer/components/new-chat/UnifiedModelPanel.tsx
#	apps/desktop/src/renderer/components/new-chat/UnifiedModelRow.tsx
#	docs/design-rules/design-inventory.md
Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
@zqchris

zqchris commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

已核实并同步遗漏修复,推送 797de0c2e5ad8703a94895289a06358e564b6b14。复用了 PC 分支 019d212b9a6b6afeb769b0e2b8f20d1c0e682411 的四文件改动,没有另造实现或删减伙伴定稿。

删除请求现在先执行 bots.assertNoSharedHistory;已有共享委派/私聊历史时,在暂停、归档、关闭或取消任务之前拒绝,最终删除事务仍重复相同检查。四种共享历史回归确认 Profile、canonical Session、link 不变,没有关闭/取消/删除副作用,之后仍能正常暂停和恢复。

验证:129 项定向回归、Desktop typecheck、本地 pnpm test:unit:related(全量回退)、DCO 均通过。已核实上一 head 3bd1572e 的 Windows 重跑 job 101451325869Run companion database regressions 步骤均 SUCCESS;本次新提交等待新一轮 CI。

受保护 .github/workflows/ci.yml 的人工审核门继续保留,请维护者复审本次补齐。该问题通过原会话转交,没有对应新增 GitHub review thread 可 Resolve。尚未合并发布。

@MagicLizi

Copy link
Copy Markdown
Contributor

@zqchris 👋 这个 PR 目前与 main 有合并冲突,auto-review 因此暂时跳过、没法继续审查 / 合并。

请在本地 merge 最新的 origin/main 解决冲突后推送;冲突解除后,下一轮 auto-review 会自动重新处理这个 PR。

@MagicLizi MagicLizi added the status:conflict 与目标分支有冲突(review-pr 自动维护,仅展示) label Sep 6, 2026
Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
@zqchris

zqchris commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

已推送 26aab5c53eedfcdb07b39f8c0436dca4cda8bc52,在删除预检修复 797de0c2e 之后合入最新主干 5fc588110,解决 Codex 配置和生成设计清单冲突。伙伴记忆、权限、手机已读与远程可见性保持不变,主干模型窗口设置也已保留。

合并后:完整 pnpm test:unit:related、Desktop/Mobile typecheck、129 项伙伴/数据库回归、手机 scope、设计清单、DCO 全部通过。初次类型检查发现本地缺少主干新增的工作区依赖,按锁文件离线安装后重跑通过,没有改版本或放宽检查。上一 head 3bd1572e 的 Windows DB 重跑已核实 SUCCESS;当前提交等待新 CI。

用户对提示词范围的确认已公开同步至 #2829 (comment) ,本 PR 正文也已引用。删除并发竞态与当前版本缓存对照仍不能标为完成;共享历史预检只解决已存在共享历史时的前置副作用。保留受保护路径人工审核门,不删减需求、不提前解除未完成项。

… full

Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
@zqchris

zqchris commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

已在当前分支独立复现并同步 PC 伙伴 owner 转交的活动推送遗漏,提交 ab6ee936bd7e41efe241899951e5e5124d3d4f3c

  • 复现:悬挂 DB 可见性 lookup,连发 65 个不同任务的 completed 活动,释放后只收到 64 条。
  • 修复:同步 BACKPRESSURE 时保留暂存项并沿现有重试;异步失败仍保留较新的同键状态。仅 dispatch 及一个回归测试变更,没有调整或删减伙伴需求。
  • 验证:修复后 65/65;dispatch 套件 39 项、Desktop typecheck、pnpm test:unit:related(全量回退)、DCO 全部通过。未启动客户端。

本次为跨分支补丁同步,没有新增可 Resolve 的 review thread;不代替维护者解除整体 CHANGES_REQUESTED。删除并发竞态、当前版本缓存命中率对照及受保护 CI 路径人工处理仍按各自证据跟进。本轮提交后的 CI 交给已有 PR 跟踪员,尚未合并发布。

Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
@zqchris

zqchris commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

已推送删除/私聊写入竞态修复 00b032dd8f6a57422ace6ef016f023f89a8e0898,同步 PC 提交 d137fb77a82f5027afeab7b8f8e5a03f0b1a2e85,三个产品文件一致。

已核实并同步 PC 伙伴分支转交的删除/私聊写入竞态修复。

删除预检通过后,晚到私聊曾可继续写入共享记录,导致最终删除失败而伙伴已暂停、归档。本轮将现有去重生命周期动作和私聊写入纳入同一组按 Bot ID 排序的锁;私聊取得双方锁后重新读取 active/canonical/unarchived 状态再写入。保留提前检查及最终数据库 guard,不新增 schema、migration 或 wire,不调整或删减伙伴定稿。

真实 SQLite 与两个服务的双顺序回归:旧实现 delete-first 失败;修复后删除先开始时晚到私聊拒绝、没有共享记录写入;私聊先写入时删除拒绝,Profile/Session/link 不变,没有关闭副作用,仍可 pause/resume。

验证:真实数据库/私聊/生命周期 154 项(115 + 24 + 15)通过,Desktop typecheck 通过,pnpm test:unit:related 完整复跑通过,DCO 与 diff 检查通过。首次完整单测曾出现未改动的 codexAuthBindingClaim.test.ts 5 秒超时和 cindySubagentForeground.test.ts 提前停止时序失败;分别原样复跑 9 项、4 项通过,随后重新运行完整门禁通过。没有提高超时、跳过或弱化测试;未启动客户端。

当前版本缓存命中率对照仍未完成;提示词范围继续沿用 Chris 已公开确认。此转交对应 PC 的 review,没有本 PR 独立线程可 Resolve;不代替维护者解除整体审查状态。新 head CI 交由现有跟踪员跟进,受保护 CI 路径人工门保留,尚未合并发布。

@MagicLizi MagicLizi added status:awaiting-bot-review 等外部审查机器人表态(review-pr 自动维护,仅展示) and removed status:conflict 与目标分支有冲突(review-pr 自动维护,仅展示) labels Sep 6, 2026
Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
@zqchris

zqchris commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

PC 伙伴合入主干后的冲突处置

当前 head e4e4ca5721d5fa2d02c032b2c57818de531bb182 已合并主干 f045326f1(包含 Desktop 伙伴 #2829)。此次冲突来自共享伙伴文件在主干以 squash 方式新增;逐项比对双方后,保留手机分支的来源电脑路由、远程停止/子任务/只读私聊、离线缓存、独立未读位置、共享类型出口与安全投影。主干新增的已发现伙伴 ID 隐藏/归档后拒绝访问、暂停后 Skill 写入拒绝及 paused-main 私聊拒绝回归同时保留。

手机源码、活动背压、DB 远程可见性与删除/私聊共享锁相对合并前未变;主干 Library 合同与键帽规范原样接入,设计清单从合并结果重新生成。没有调整或删减伙伴定稿。

验证:pnpm test:unit:related(完整回退)全部通过;Desktop/Mobile typecheck、156 项伙伴数据库/资源/私聊/生命周期回归、手机 scope、设计清单及 DCO 通过。未启动客户端或改手机原生配置。新 head 外部 CI 与人工复审仍待结果;受保护 CI 路径人工门继续保留,手机 PR 尚未合并发布。

本次为合并冲突处理,没有对应的独立 review thread 可 Resolve;不代替维护者解除整体审查状态。后续交由已有跟踪员按新 head 继续。

@MagicLizi MagicLizi removed the touches:redline 改动碰到红线路径(updater / DB schema 等,review-pr 自动维护,仅展示) label Sep 6, 2026
@MagicLizi

Copy link
Copy Markdown
Contributor

命中 UI 路径(apps/desktop/src/renderer/components/chat/SystemCard.tsx / apps/desktop/src/renderer/features/bots/BotCollaborationCard.tsx / apps/desktop/src/renderer/features/bots/BotDirectMessageCard.tsx 等)但 description 未附界面效果证据——建议补充改动后效果:截图/录屏,或改动后界面的 HTML 页面(```html 代码块、.html 附件或在线预览链接),便于确认界面符合 DESIGN.md 设计规范

@zqchris

zqchris commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

已按这条意见补充 PR description 的「界面效果证据」:内附可直接复制保存的完整自包含 HTML,覆盖手机伙伴名册、后台任务/私聊卡片,以及远程 Mac 的任务卡和只读私聊详情,含 Light/Dark 与 390px 窄屏展示。

已在独立无头浏览器目检,明确标注为当前 e4e4ca5721d5fa2d02c032b2c57818de531bb182 的演示数据静态效果稿,不冒充安装版截图、React Native 实机或联网验收。源码依据、展示范围和证据限制均在正文及 HTML 中说明。

本轮只补公开界面证据,未更改代码、产品需求或 CI;head 不变。原意见为 issue comment,没有可 Resolve 的 inline thread,不代替维护者作视觉通过结论。

@MagicLizi MagicLizi removed the status:awaiting-bot-review 等外部审查机器人表态(review-pr 自动维护,仅展示) label Sep 6, 2026
Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
@zqchris

zqchris commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

已在 9f93cef06442fae302910dae4d829fa7cc573df7 合并主干 ea5f9d1b4 并解决冲突。唯一冲突是设计清单的生成内容;保留人工维护区后按合并源码重新生成。主干权限接线自动合入并已逐项核对。手机伙伴、在线/离线缓存、Mac-to-Mac 控制及既有安全修复保持原样,没有增删定稿需求。

验证:根 pnpm test:unit:related 全量通过,Desktop/Mobile typecheck 通过,伙伴定向回归 156 项通过,移动端 scope、设计清单、diff 与 DCO 检查通过。PR 正文中的完整 HTML 界面证据已保留,此次合并未改变所展示的伙伴组件;仍明确标为静态效果证据,不冒充真机或双 Mac 联调。

本条冲突通知是 issue comment,没有对应 inline thread 可 Resolve。当前 head 的 CI 和人工审查交由既有跟进处理,受保护 CI 路径的人工门不变。

@MagicLizi MagicLizi added status:awaiting-bot-review 等外部审查机器人表态(review-pr 自动维护,仅展示) and removed status:awaiting-bot-review 等外部审查机器人表态(review-pr 自动维护,仅展示) labels Sep 6, 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.

???? head 9f93cef06442fae302910dae4d829fa7cc573df7 ???? 2 ?????????? P1?

  1. [P1] apps/mobile/app/sessions/[sessionId].tsx:2104 ? ???? ACK ???????????????????
    ?? canMarkRead ?????????readAckSyncedKey ????? loading/hold????????? session:<id> ?? ACK ???contentKeyAtStart ?? null????????? 3400 ??? readAckSyncedKey?? contentSyncedKey ?? null??? apps/mobile/src/session/useRemoteResourceSession.ts:33-46 ???????????? lastReplyAt ????????? 3433-3440 ?? post-ACK ???????????????????????
    ??????????????? contentRecoveryKey / contentSyncedKey???????????????????????????????pre-ACK snapshot ? gap reply ? ACK ? recovery ??? mark read??

  2. [P1] packages/device-link/src/allowlist.ts:438 / apps/desktop/src/main/maker-ipc/register.ts:9006 ? ?????????????? ID ?????????
    ??????? [threadId, viewerBotId]?? apps/desktop/src/main/device-link/remoteBotSessionBoundary.ts:18-25 ??????? threadId ? Session ID ?????????? Bot ID???? apps/desktop/src/main/maker-ipc/botDirectMessageService.ts:329-378 ??? viewer ? thread participant????? Profile ?? hiddenAt/status??????? delivered ???????? lookup ? hidden-bot ?? hidden?????? ALLOWED?
    ?????/?? handler ???? viewer ??????????? opaque thread ID ?????????????/?????????????/?? participant ???????????

?? CI?DCO???????????????????????????

Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
@zqchris

zqchris commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

针对 review https://github.com/makecindy/cindy/pull/3912#pullrequestreview-5125634447,两条均确认属于原目标内缺陷,已在 02402586e0c26853fb3ab7572369e5e657abe414 修复,没有增删或调整定稿需求。

  1. 伙伴已读恢复时序:在原页面门槛中补上非空 contentRecoveryKey === contentSyncedKey。订阅 ACK 前的快照、ACK 到达但补拉未应用、旧 ACK 快照都不能清伙伴未读。回归执行实际页面传给 hook 的表达式和真实 hook:旧代码在 pre-ACK 阶段已经写入最新回复 200 的已读位置;修复后直到匹配的 post-ACK 快照落地才写一次。
  2. 私聊远程查看者可见性:在现有 DB-backed 远程边界按第二个参数 viewerBotId 查询 Bot,不把 opaque thread ID 当 Session ID。仅放行 visible,隐藏/归档或不存在均返回 NOT_FOUND;原服务参与者检查及本地 Desktop 查看保持不变。既有 dispatch 在调用前后及缓存/排队投递时复用此检查。真实 dispatch 新增回归在旧代码上出现 3 项失败,修复后验证了不可见查看者在 handler 前被拒、可见查看者正常阅读、隐藏后缓存响应不再泄漏且不重复执行 handler。

验证:根 pnpm test:unit:related 全量通过;Desktop/Mobile typecheck 通过;Mobile 定向 39 项、Desktop 分发/私聊 56 项、真实 SQLite 伙伴数据库 115 项通过;scope、diff、DCO 通过。未改 schema、wire、allowlist、UI 或连接恢复动作,未启动 DEV。当前 head 的外部 CI 与人工复审仍由既有跟进接续。

已核对本轮为整体 review,没有对应新 inline thread 可 Resolve;此前唯一 inline thread 已解决,未重复操作。请按当前 head 复审以上两项。

@MagicLizi MagicLizi added status:awaiting-bot-review 等外部审查机器人表态(review-pr 自动维护,仅展示) touches:security 改动碰到安全边界(review-pr 自动维护,仅展示) and removed status:awaiting-bot-review 等外部审查机器人表态(review-pr 自动维护,仅展示) labels Sep 6, 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.

Final re-review of head 02402586: no remaining P0/P1.

The previous Mobile pre-ACK companion read-cursor race and hidden/archived private-thread viewer authorization gap are both fixed. Verified the production paths, targeted Mobile/Desktop regressions, both typechecks, current CI/DCO, and resolved review threads. The dynamic-eval scanner hit is confined to a test harness over repository-controlled source and does not enter the product runtime.

@MagicLizi
MagicLizi merged commit 96e1202 into makecindy:main Sep 7, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:large-diff 改动量较大(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示) touches:security 改动碰到安全边界(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants