Skip to content

feat(preview): 统一三端任务与伙伴附件预览 - #8356

Merged
MagicLizi merged 10 commits into
makecindy:mainfrom
zqchris:attachment-preview-unified
Nov 1, 2026
Merged

MagicLizi merged 10 commits into
makecindy:mainfrom
zqchris:attachment-preview-unified

Conversation

@zqchris

@zqchris zqchris commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

这次改了什么

摘要

附件从任务、伙伴、群聊或输入区打开时,过去存在关闭/缩放按钮缺失、同类文件分散在不同弹层、Android PDF 跳出应用的问题。现在三端共用预览操作合同:文件名、常显关闭、原件操作、明确的附件集合,以及各类型的阅读/播放工具。

变更类型

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

范围

  • 关联 Issue / 需求:用户要求统一 Desktop / iOS / Android 的全部附件预览,包括任务和伙伴,保留设计还原度。
  • 本 PR 包含:公共预览外壳;图片显式缩放/适应/原尺寸;混合附件导航;视频/音频、PDF、文本、Markdown、图表和模型分派;任务/群/话题/草稿/成果/插件接线;原件保存和远程读取生命周期;产品合同与实测证据。
  • 明确不包含:服务器改动、外部 IM 客户端自身界面、插件授权协议或原生依赖升级。
  • 用户可见变化:随时可以找到关闭,关闭不移除附件;手机 PDF 可在应用内读;伙伴成果文件可直接点开;同一条消息的不同类型附件可连续查看。
  • 是否存在 breaking change:无。既有文件、插件 grant、账号授权和传输协议继续使用;未增加数据库迁移。

UI 变化

  • 引用的设计规范:docs/design-rules/DESIGN.md §2 语义颜色、§3 字体、§4 Buttons / Dialog & Modal、§5 布局;design-governance.md §13 点击目标。Desktop 使用 32px 热区/16px 图标,手机使用 48px 热区/20px 图标,标题和关闭独立于内容缩放,支持 Light / Dark。
  • 需求与设计:产品合同、布局规范。
  • 三端真实截图和入口覆盖:验收记录。
Desktop iOS Android
Desktop PDF iOS video Android PDF

以下单页检查只验证真实公共外壳的布局/主题,完整媒体运行由上面的隔离客户端与模拟器截图证明。

  • 截图来源:单页验证 pnpm ui:check --entry outputs/attachment-preview/ui-fixture.tsx --theme light,dark --locale zh-CN,en,de --viewport 800x600 --engine chromium --output outputs/attachment-preview/ui-check,macOS · Chromium 156.0.8078.79;真实组件与主题,场景数据,不是登录账号下的完整 Cindy
  • 版本:a6103784b416(含未提交改动)
  • 结果:6/6 个场景通过
  • 页面 entry:light / dark · zh-CN / en / de · 800×600
    • default:Ad-hoc entry
    • 未覆盖:No page-specific assertions; only generic checks and screenshots

单页验证截图 1/1

怎么验证的

自动验证

  • Desktop 定向 Vitest:5 文件、116 条通过(媒体原件操作、PDF、标注保护、文本与行位置);插件画廊回归通过。
  • Mobile 定向 Vitest:8 文件、206 条;首次新增集合测试用错标题字段,更正后所在文件 48 条全过。最后的群附件集合快照改动再次运行 22 条全过;缓存生命周期改动后群附件 + Android PDF 路由 23 条全过。
  • 合入最新主干后再次运行 Mobile 集合 / 群附件 / 手势标注 187 条通过;保留上游伙伴过程文案改动,设计台账重新生成。
  • pnpm --filter desktop run typecheck、pnpm --filter mobile run typecheck:通过。
  • pnpm check:i18n-glossary、pnpm check:test-hygiene、pnpm check:design-inventory、git diff --check:通过。设计台账已用正式生成器同步,没有修改测试基线。
  • 测试价值、生产入口、最小输入和各文件实际用例耗时逐项记录在验收文档。测试更新保留原手势、标注、授权、迟到结果与文本上限语义;移除的是被公共外壳替代的私有卡片源码断言。

手工验证

  • Desktop macOS 隔离测试版:原任务草稿添加 WebP / MP4 / PDF,视频真实解码 384×240,切 PDF 完整适应 74%,关闭后附件仍在。
  • iOS 27 / iPhone 18 Pro:实际六项混合消息,图片→视频→PDF,关闭回原消息;文件页的 PDF、文本查找、视频与模型,明暗主题。
  • Android API 36 arm64:从本工作树重新构建并安装 APK;同一混合集合的图片、原生视频、PDF;深色模式图片放大、画笔、未保存退出询问,放弃后保留原消息;真实 glTF 模型和 Mermaid。
  • branch/worktree:attachment-preview-unified;Metro 8081 归属于同名独立工作树,__DEV__ source 与提交对应。iOS native fingerprint 匹配,Android 使用本次 assembleDebug 输出。只操作本任务测试实例。

未执行的验证

Windows、平板/横屏/大字/读屏全矩阵、真实另一台电脑/SSH/Chat Server/插件账号来源闭环,以及所有格式的损坏/密码/超大样本未完成设备验收。核心三端已实际运行;上述补充缺项仍约束整体发布/结案,不能将本 PR 送审解释为全来源全部验收通过。完整自动套件交 CI。

风险

风险分类

  • 跨平台差异
  • 其他:公共附件入口覆盖面较大;手机增加离线 PDF/model/draw.io JS 资源,影响 JS bundle 体积。

影响与回滚

  • 影响范围:Desktop / Mobile 附件查看与原件操作;读取继续走既有来源授权,缓存副本使用生命周期保护。密码仅在本地 PDF 阅读器使用,不进入模型或消息。
  • 存量插件影响:无授权记录、指纹、manifest、安装布局或包格式改变;只替换宿主的媒体查看外壳。
  • 原生层 / fingerprint / OTA:没有新增 native dependency 或原生配置修改;离线引擎从现有 Desktop 依赖生成,iOS fingerprint 实测匹配。
  • 格式边界:FBX/未知格式保留保存或外部打开;手机 PDF 30 MB、模型 50 MB;glTF 外部资源不会绕过原授权去任意读取。
  • 回滚 / 降级方式:整体回滚此提交可恢复旧 UI;无持久数据迁移。不能通过禁用来源权限或删除用户附件来降级。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名
  • UI 改动已注明设计规范章节
  • 未提交凭证、令牌或授权文件
  • 已核对受影响文档并同步行为合同与设计台账
  • 已记录测试结果和未执行项

PR 审查修复 · c49c27d

本轮已推送 c49c27d,5 条审查意见已修复并增加最小回归。

两个 client-ci 失败 job(Desktop Git integration / verify-checks)均定位到同一个设计台账测试:它固定了旧 ImageLightbox 的圆角数量,界面调整后得到 4 而不是旧值 5。现改为经生产生成器扫描独立 JSX 样本,分别覆盖 class、camelCase 内联圆角和注释排除;定向用例通过(0.046 秒),没有修改统计器或测试基线。

本轮 Desktop 56 条 / Mobile 34 条回归、两端类型检查、测试卫生和设计台账检查通过;Desktop 的行定位/错误图表关闭/焦点,以及 iOS/Android 横屏 PDF 放大后适配已实测。新的 CI 尚待结果,原来列出的真实来源与平台补充验收边界继续保留。

实际截图、测试价值和各文件耗时见验收记录的「PR #8356 审查修复」。

2026-11-01 CI 修复补充(98d47ccc76)

核对 e57cc5e 的 Linux/Windows 四个分片,处理附件预览相关的 20 个失败测试文件。保留已批准的应用内 PDF、更多菜单、主题背板与焦点约束,更新旧断言和 Node 环境的原生替身;原件复制、标注烧录顺序、来源授权、群聊草稿与缓存索引检查仍保留。

另修复四处实质回归:图表初始焦点导致第一次 Esc 被 Tooltip 消耗;公共文本阅读器丢失原 JSON 渲染预算;大文档查找跳转被 RN FlatList 已测量范围钳制(复用已有 LegendList);电脑群附件缺少 url/path 时无反馈。图标 20px 改用既有 token,数值不变。

  • 定向验证:Desktop 6 文件 287 用例、Mobile 14 文件 450 用例通过;两个包 typecheck、design inventory、test hygiene、DCO 通过。禁用文本预算后三个原有用例失败,恢复后通过。未跑无关全量。
  • 实测:隔离 Desktop 图表打开后一次 Esc 关闭;Baguette iOS/Android 均用 10,001 行 mock 文件确认截断、查找第 10,000 行、滚动与关闭。iOS 浅色、Android 深色截图见验证记录。
  • 证据及测试价值:本轮验证记录。本任务测试实例已退出,隔离数据及登录态保留;未新建真实任务/伙伴数据。
  • Windows agent-island 另有三个 60 秒超时,文件未在本 PR 改动且明确范围外,单独跟踪 Windows CI:agent-island 三个 TTL/关闭用例各超时 60 秒 #8361;未延长超时或弱化测试。此项未解决,不能声称 Windows CI 已通过。
  • 本轮推送后等新 CI。原有 Windows/平板、真实远程/SSH/Chat Server/插件账号等补充验收缺口继续保留;缺地址群附件反馈有生产组件回归,没有真实账号群的设备实测,不宣称整体可合并。

verify-checks 守卫补充(aceaa390a9)

c49c27d 的 verify-checks 还包含三个旧守卫文件失败,本批已定向复现并处理:补回可见且已加载文本页的 filePreview.sourceReady;将非文本分派/PDF 稳定性守卫对齐实际公共阅读器;恢复历史补齐等价表达式格式,保留手势、取消、互斥和权限条件。

Desktop 3 / Mobile 50 用例、两个包 typecheck、test-hygiene、design-inventory、DCO 通过。只有 testID 元数据发生运行时改动,无布局/操作/读取变化,沿用 98d47cc 的设备验收,本轮未启动测试实例。详见验证记录“verify-checks 守卫补充”。新 head 等 CI;范围外 #8361 与原补充验收缺口保留。

当前 verify-checks 修复(8a7c11aed5)

Run 41322360581 / job 124895184630 的 3 个失败已本地复现,均为 Mobile 旧守卫精确匹配源码格式。恢复正文选择表达式的外层括号、同步恢复状态单行类型、草稿回收单参数回调的原写法,逻辑与断言均不变。

验证:两个相关文件 29 例通过(修前 3 失败 / 26 通过),运行 0.591 秒;Mobile typecheck、diff 与 DCO 检查通过。仅等价格式,不重开测试实例,沿用原实测;原补充验收缺口保留。此次未跑无关全量,未改测试或门禁。

Linux 分片 1 修复(10fc0b06ff,2026-11-02)

Run 41323484318 / job 124898531519 的 Mobile 5 例失败已复现并修复:任务页三处等价 JSX 恢复旧写法;文本公共阅读器使用 AppText.TextInput 与等宽代码 bodySmall 15/20;排版扫描仅排除准确路径的生成第三方 WebView 引擎 JS 字符串,业务阅读器和 HTML 生成器仍受扫描,不改基线。群聊阅读器原生替身补公共 TextInput 导出,原断言全保留,无新增用例。

验证:三个相关文件 35 例通过(1.48 秒,测试执行 0.969 秒),Mobile typecheck、test-hygiene、design-inventory、diff 和 DCO 通过。测试价值与扫描边界理由已写证据 README。iOS 浅色 / Android 深色在当前 worktree Metro 上实际打开 large.json、输入9999、匹配1/1、跳第10000行、关闭返回;截图在 ci-typography-*-search.jpg。两端 App、模拟器与本任务 Metro 已退出,保留数据。未跑无关全量,原补充验收缺口保留。

当前 CI 阻塞:颜色扫描超时(2026-11-02,10fc0b06ff)

Run 41325347406:四个 Linux unit 分片均 success;verify-checks 的新增颜色检查耗时约 31 分 19 秒,整个 job 达 40 分钟上限后在 Desktop typecheck 阶段取消。汇总 verify 因 VERIFY_CHECKS_RESULT=cancelled 返回失败,日志没有新测试/类型错误;未执行完的类型检查仍不能算通过。

已按本 PR 范围外只开 issue 的约定立案 8369,附实际日志时间、约 9.5 MB 生成资源输入、生产扫描入口与有界复现。扫描器位于授权范围外,未修改或降低门禁、未延长超时、未删除文档能力。本轮无代码变更/推送。需独立修复扫描耗时后重跑 verify-checks 及依赖汇总,CI 阻塞保持明确;其余原补充验收缺口不变。

合并冲突已处理(dc420ea380,2026-11-02)

纳入 upstream/main 19dad9c22542eb36b10ca31d14b61ad934068502。唯一冲突为设计台账的 GENERATED 区,用正式生成器按合并树重建;两侧人工维护区逐字保留,业务源码无手工冲突修改。

验证:生成器原文件 52 例通过(85.44 秒);连续两次生成字节一致、59 surfaces 最新、12 语言14766key结构一致、Desktop/Mobile类型检查及diff/DCO通过。本轮无新测试,无App/模拟器启动;原实测与补充缺口保留。此前颜色扫描超时 issue #8369 不因解冲突而视为已解决,新 head 的 CI 仍需真实通过。

新主干冲突处理(2283e8b9dc,2026-11-02)

纳入 upstream/main 156152364a38dfe172a1df50fca157485191b768 的群聊引用对齐与登录翻译。仅生成台账冲突,正式重建后两次字节一致、人工维护区与两parent完全一致。群聊新旧断言自动合并,未手工修改业务逻辑/样式/文案。

验证:群聊146例(4.73秒/测试1.511秒)、台账2例(0.047秒)、59surfaces台账与12语言14766key检查、Desktop/Mobile类型检查及diff/DCO通过。本轮不重复上次52例生成器全集,无新测试、无测试App/模拟器启动。原运行证据与补充缺口保留,#8369单独跟踪,新headCI仍待真实结果。

正文渲染冲突处理(84c18824ed,2026-11-02)

纳入 upstream/main db723ff786c9b5e8c9e628fab277ff01f38dc185。三处 MessageRenderer 正文冲突逐段保留主干 StaticSpan / UITextView 优化与显式字号限幅,保留本 PR 链接、文件、图片/视频及统一附件集合入口;未改变功能取舍。

180 个直接相关用例(3.64秒)、Mobile typecheck、设计台账、test-hygiene、diff/DCO通过。未新增/改写测试,无全量测试。验收前发现旧原生包不匹配,已按正式 iOS 构建入口与 Android Expo/Gradle 环境更新;整包内容与原生指纹校验通过,Metro 为本工作树 target-fresh。

iOS 浅色 / Android 深色实见正文强调、表格、行内代码;从消息打开 code.json4/7,切换到已实际加载的PDF3/7,再关闭返回来源。六张 merge3-* 截图及原生准备过程已入证据README。两端测试App、模拟器及本任务Metro已退出,保留数据。

原未完成的完整来源/环境矩阵继续保留;此前 CI 扫描性能 #8369 独立跟踪,新headCI仍需真实通过。最终合并由仓库管理负责。

当前交接状态(2026-11-02,84c18824ed)

实时回读:当前 head 的 verify-checks、verify、Linux/Windows 全部分片、Windows runner/database、Desktop Git integration、设计依据检查与 DCO 均通过;返回检查无失败或待运行项。5 条 review threads 全部 resolved,无未解决讨论。

PR 仍 OPEN / 非 Draft / MERGEABLE,GitHub 的正式审核状态为 REVIEW_REQUIRED(已有 review 均为 COMMENTED,尚无 APPROVED),mergeStateStatus 为 BLOCKED。等待仓库审核人批准,由仓库管理负责最终合并;开发 Agent 不代签或合并。

本轮仅核对状态,无新增代码、测试或推送。此前明确的补充验收缺口继续保留,CI 通过不替代完整运行验收结论;独立扫描性能 issue 不因一次 CI 通过自动标为修复。

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

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

# Conflicts:
#	apps/mobile/src/session/MessageRenderer.tsx
#	docs/design-rules/design-inventory.md
@zqchris
zqchris requested a review from a team as a code owner November 1, 2026 14:28
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 1, 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 ⚠️ Failed 2026-11-01T14:41:38.857214Z
We couldn’t complete this review. Comment @codex review to try again.
e57cc5e PR opened
ℹ️ 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.

@greptile-apps

greptile-apps Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 2/5

[High impact] The PR changes attachment previews across Desktop, iOS, and Android entry points.

建议先修复标注原图、直接音频和图表关闭这三处问题,再合并。

Findings

  1. P1 切换后旧标注无法撤销 ▶
  2. P1 直接音频无法播放 ▶
  3. P1 图表失败后无法关闭 ▶
  4. P2 集合丢失文件定位 ▶
  5. P2 PDF 适配不完整 ▶
Fix with agent prompt
### Issue 1
apps/desktop/src/renderer/components/chat/MessageStream.tsx:4119-4123
打开同一消息里的另一附件,再切到已标注图片时,集合中的 `source` 和 `annotationFallbackSrc` 都指向烧录图,但 `initialStrokes` 仍会叠加绘制。撤销笔迹去不掉底图里的旧标注,再次保存也会保留它们。

请保留 `annotationSourceUrl`,显示原图,仅在读取失败时退回烧录图。

### Issue 2
apps/mobile/src/session/MessageRenderer.tsx:7795-7799
消息中的 HTTPS 音频或 `data:audio/` 原本可以直接播放。新入口忽略了 `payload.media.previewable`,强制调用 `onResolveRemoteMedia`,而 `resolveMobileRemoteMedia` 会拒绝这些地址。用户打开音频后只会看到读取失败。

请保留直接播放地址,仅对电脑上的资源调用取件函数。

### Issue 3
apps/desktop/src/renderer/components/chat/TextLightbox.tsx:459-460
`.mmd` 或 `.mermaid` 文件读取完成后,这个提前返回会卸载带关闭按钮的外壳。但 `MarkdownMermaidBlock` 只有生成 `svg` 后才显示全屏查看器;加载期间或语法错误时,它只返回普通代码块。此时 `overlayRef.current` 为空,Esc 也无法关闭。

请让加载和渲染失败状态继续留在公共外壳内,并保留关闭入口。

### Issue 4
apps/desktop/src/renderer/components/chat/TextLightbox.tsx:115-117
多附件入口只传递集合和关闭回调,丢掉了 `initialLine` 与 `triggerRef`。从带行号的文件引用打开集合内文件时,查看器会从顶部开始;关闭后也不会回到触发按钮。现有 `MarkdownRenderer` 和文件菜单仍会传入这些参数。

请把首次打开的参数传给起始查看器,并保留关闭时的焦点归还。

### Issue 5
apps/mobile/src/session/pdfWebViewHtml.ts:30-31
手机 PDF 的缩放只按可用宽度计算,没有考虑高度;“适配”按钮也只是把 `zoom` 设回 `1`。横屏打开竖版 PDF 时,页面高度会远超阅读区域,点击“适配”仍看不到完整页面。

请同时按宽度和高度计算适配比例,让首次打开和“适配”按钮使用同一计算。

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

本 PR 为桌面、iOS 和 Android 统一附件预览外壳,并接入混合附件切换、原件操作和手机离线文档阅读器。

  • Desktop previews keep the file name and close button visible while matching tools to the attachment.
  • Mobile attachments stay in an in-app viewer with controls that fit the file type and its source.
  • Desktop viewers can save supported original files, not just images.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[任务、伙伴、群聊或草稿附件] --> B[固定本次附件集合]
  B --> C[公共预览外壳]
  C --> D[图片与视频]
  C --> E[文件类型分派]
  E --> F[既有来源授权与读取]
  F --> G[PDF、文本、图表或模型]
  C --> H[保存或分享原件]
  C --> I[关闭并返回来源]
Loading

Reviews (1) · Last reviewed commit: "Merge remote-tracking branch 'upstream/m..." · Reviewed by Greptile

@MagicLizi MagicLizi added status:ci-failed CI 失败(review-pr 自动维护,仅展示) touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:large-diff 改动量较大(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示) touches:security 改动碰到安全边界(review-pr 自动维护,仅展示) labels Nov 1, 2026
Signed-off-by: Chris <4436110+zqchris@users.noreply.github.com>
@zqchris

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

本轮已推送 c49c27d,5 条审查意见已修复并增加最小回归。

两个 client-ci 失败 job(Desktop Git integration / verify-checks)均定位到同一个设计台账测试:它固定了旧 ImageLightbox 的圆角数量,界面调整后得到 4 而不是旧值 5。现改为经生产生成器扫描独立 JSX 样本,分别覆盖 class、camelCase 内联圆角和注释排除;定向用例通过(0.046 秒),没有修改统计器或测试基线。

本轮 Desktop 56 条 / Mobile 34 条回归、两端类型检查、测试卫生和设计台账检查通过;Desktop 的行定位/错误图表关闭/焦点,以及 iOS/Android 横屏 PDF 放大后适配已实测。新的 CI 尚待结果,原来列出的真实来源与平台补充验收边界继续保留。

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

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

已合批修复并推送 98d47cc。

旧 run 的附件相关失败已按当前统一预览合同修正,保留复制原件、来源授权、键盘/焦点、草稿及缓存索引的回归检查;同时补回文本预算、修复图表第一次 Esc、长文档查找定位和缺地址群附件提示。

定向通过:Desktop 287 / Mobile 450 用例、两个包类型检查与相关设计/测试门禁。Desktop 图表单次 Esc,iOS/Android 截断与第 10,000 行查找均实际操作通过,截图与逐文件测试记录已提交。

Windows agent-island 的三个独立 60 秒超时属于范围外,另开 #8361,未改该服务或弱化测试;该项尚未解决。新 head 等 CI,合并仍由仓库管理负责,既有补充验收缺口不变。

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

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

已按 c49c27d 的 verify-checks 日志定向复现并修复,推送 aceaa39。

  • 补回文件浏览文本的 filePreview.sourceReady 标记,只在可见且已加载的阅读器上存在。
  • 旧“非文本自动外部打开”守卫改为验证已批准的应用内分派,仍保留非文本分类与全部入口检查;不恢复旧外部打开行为。
  • PDF 稳定性守卫跟随实际公共 PDF.js 组件,继续限制文档身份、缩放/翻页与重载边界;HTML/Markdown 手势归属检查保持。
  • 历史补齐的 seq 清理和类型只恢复等价格式,取消、互斥及权限检查不变。

定向验证 Desktop 3 / Mobile 50 用例通过,两端类型检查、测试卫生、设计台账检查通过。没有跑无关全量;新增的仅为 testID 元数据,沿用 98d47cc 的两端实测,未启动测试实例。新提交等 CI;原有范围外 issue #8361 和补充验收缺口保留,合并交仓库管理。

@zqchris

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

保留这两份直接关联测试,无需回退或再次申请授权。

2026-11-01 本轮用户已明确:“范围内源文件的测试/快照、CI 校验的生成台账(如 design-inventory)与随清单变动的锁文件自动视为范围内,直接改。”

  • chatMediaLightboxFocus.test.ts 验证本 PR 图片/模型预览的焦点、错误态与关闭。
  • openPathFeedback.test.ts 验证本 PR 文件预览分派、原件操作错误分类,保留系统错误透传检查。

两项的精确路径、上述当次授权原文和对应理由,已分别登记到 selfReview.scopeExpansions,并同步意图契约。98d47ccc76 与当前 aceaa39 的 PR-ENTRY-REPAIR 均已通过 scope 校验(scopeGate: anchored)。本条是较早快照的重复范围提醒,没有新增越界事实;本轮不改码、不重跑测试。当前继续等待新 CI,原补充验收缺口不变。

@zqchris

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

保留 apps/desktop/src/renderer/__tests__/unsupportedTextPreview.test.ts。它直接验证本 PR 已批准的 filePreview / TextLightbox 文件类型分派:非文本不误当文本解码,也不自动离开 Cindy。

2026-11-01 本轮用户已明确授权:“范围内源文件的测试/快照、CI 校验的生成台账(如 design-inventory)与随清单变动的锁文件自动视为范围内,直接改。”该精确路径、授权原文和上述理由已经登记在 selfReview.scopeExpansions 并同步意图契约;当前 aceaa39 的 PR-ENTRY-REPAIR 已通过 scopeGate: anchored。

因此本项按已授权关联测试处理,无需回退或重复申请授权。本轮仅回复已有证据,不新增代码或重复运行测试,继续等待 CI。

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

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

已处理当前 aceaa39 的 verify-checks 失败,修复提交 8a7c11aed5。

Run 41322360581 / job 124895184630 仅 3 个 Mobile guard 用例失败;本地复现后确认是精确源码格式匹配。恢复三处原有等价写法,保留正文可选择条件、同步退避、后续消息及附件回收逻辑,未修改测试或门禁。

  • 修前:3 失败、26 通过;修后:两个相关文件 29 例全通过,运行 0.591 秒。
  • Mobile typecheck、diff 与 DCO 检查通过;未跑无关全量。
  • 本轮没有运行行为/UI 变化,不重启测试实例;原实测及补充验收缺口继续有效。

证据更新在 docs/design-evidence/2026-11-01/attachment-preview/README.md。等待新 head CI,由仓库管理负责合并。

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

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

已处理 8a7c11ae 的 Linux unit tests (1/4),提交 10fc0b06ff 已推送。

Run 41323484318 / job 124898531519 的 5 例失败已本地复现:

  • 任务页三处仅恢复原 JSX 等价格式,保留所有断言与条件。
  • 文本阅读器接回 AppText.TextInput,恢复现有字号限幅、主题光标/选择色;代码文字采用现有 bodySmall 15/20。
  • 排版守卫只排除准确路径的生成 vendor 引擎源码字符串,业务阅读器/HTML 生成器继续扫描,规则及基线未弱化。

定向 35 例、Mobile typecheck、test-hygiene、design-inventory、diff 与 DCO 通过;未跑无关全量。iOS 浅色、Android 深色实测公共输入、1/1 匹配、第10000行跳转和关闭返回,截图与测试价值记录已补入证据 README。测试实例已退出。

等待新 head CI;原补充验收缺口保持明确,不据此宣称整体可合并。合并由仓库管理负责。

@MagicLizi MagicLizi added status:ci-running CI 还在跑(review-pr 自动维护,仅展示) and removed status:ci-failed CI 失败(review-pr 自动维护,仅展示) labels Nov 1, 2026
@zqchris

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

本次 verify 为汇总失败,没有新的附件测试断言失败。

  • Run 41325347406 的四个 Linux unit 分片全部 success。
  • verify-checks job 124904111289 的新增颜色检查耗时约 31 分 19 秒;整个 job 用满 40 分钟后,在 Desktop typecheck 阶段取消。未完成的类型检查不计通过。
  • verify job 124914346552 实见 VERIFY_CHECKS_RESULT=cancelled、LINUX_UNIT_SHARDS_RESULT=success,因此 exit 1。

已定位到设计颜色扫描处理约 9.5 MB 的离线文档引擎生成源码时耗时过长。本机生产扫描入口在有界 10 秒内未完成。扫描器 scripts/hardcoded-color-audit.mjs / scripts/shared/hardcoded-color-match.mjs 在本 PR 授权范围之外,按“范围外只开 issue”立案 https://github.com/makecindy/cindy/issues/8369,附完整复现与验收要求。

本轮未修改业务、门禁、超时或测试,没有空提交/重复推送。需独立修复扫描性能后重跑 verify-checks 及依赖汇总;当前阻塞未解除,不将此描述为 CI 通过。原补充验收缺口保持明确。

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

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

合并冲突已处理并推送 dc420ea380:将 upstream/main 19dad9c225 纳入本分支。

唯一冲突在 docs/design-rules/design-inventory.md 的 GENERATED 统计区,已用正式生成器重建;人工维护区与两个 parent 逐字一致,语言文件的非重叠条目及两侧功能均保留,没有手工修改业务逻辑。

生成器定向 52 例、连续两次生成一致、design-inventory、12 语言14766key检查、Desktop/Mobile类型检查、diff和DCO通过。本轮不重启测试App或模拟器,没有运行无关全量。证据README已更新。

此前独立的颜色扫描超时 #8369 保持未解决,不将解冲突当作CI通过。等待新head检查;最终合并由仓库管理负责。

@zqchris

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

已核对当前 dc420ea3 的 run 41333032247,与 #8369 是同一已确认阻塞,没有新的附件逻辑/测试失败。

  • 四个 Linux unit 分片全部 success。
  • verify-checks job 124927051017 的颜色检查从 17:51:50 UTC 到 18:23:10 UTC,约 31 分 20 秒。
  • 整个检查 job 达 40 分钟上限,在 Desktop typecheck 阶段取消;Mobile typecheck 等后续步骤未执行,不能计为通过。
  • verify job 124937472958 因 VERIFY_CHECKS_RESULT=cancelled、LINUX_UNIT_SHARDS_RESULT=success 汇总失败。

独立 issue #8369 当前仍 OPEN。本轮沿用已记录的范围外处置,不重开代码修复、不重复本地测试、不造提交或再次推送,也不删除资源、降低门禁或延长超时。需先修复独立扫描性能问题,再重跑检查;阻塞未解除。原补充验收缺口与最终合并归属不变。

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

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

本次新增主干冲突已处理并推送 2283e8b9dc,纳入 upstream/main 156152364a。

唯一冲突仍在设计台账 GENERATED 区,按合并树正式生成,人工区与两侧逐字一致,连续两次生成字节相同。主干群聊引用对齐、登录翻译和附件预览功能均保留;自动合并的群聊缺源反馈/取消引用不丢草稿断言保留,没有手工改业务源码或新增功能。

验证:群聊146例、台账2项定向用例、设计台账与翻译结构、两端typecheck、diff和DCO均通过。无新增测试、无无关全量、无测试App/模拟器重启。证据README已更新。

此前颜色扫描性能 #8369 单独跟踪,本轮不将它计为解决;等待新head CI,最终合并仍由仓库管理负责。

@zqchris

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

已核对 2283e8b9dc 的 pr-design-basis 取消通知:旧 run 41342511328 在 Checkout 阶段取消,尚未执行设计依据校验。

同一 head 的后续 run 41342534696 已完成并 success:https://github.com/makecindy/cindy/actions/runs/41342534696 。该工作流按 PR 设置 cancel-in-progress: true,本次为旧运行被后续运行替代,当前设计检查已通过。

没有新的设计依据缺项或源码缺陷;本轮无需改码、测试、重跑或推送,也不重复修改 PR 正文触发检查。其它 CI 状态与原验收缺口不据此自动视为通过。

@zqchris

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

已核对当前 2283e8b9dc 的 run 41342511330,仍为 #8369 的同一颜色扫描性能阻塞。

  • 四个 Linux unit 分片全部 success。
  • verify-checks job 124955432062 的颜色检查从 19:43:05 UTC 到 20:14:39 UTC,约 31 分 34 秒。
  • 整个检查 job 达 40 分钟上限,在 Desktop typecheck 阶段取消;Mobile typecheck 等后续步骤未执行,不计通过。
  • verify job 124965802088 实见 VERIFY_CHECKS_RESULT=cancelled、LINUX_UNIT_SHARDS_RESULT=success,因此汇总失败。

独立 issue #8369 当前仍 OPEN。没有新测试断言或类型错误证据;按已记录处置,不重开改码/本地测试/推送,不空提交或重复重跑同一耗时链路。需修复范围外扫描性能后重跑检查,当前门禁保持未通过,原验收缺口不变。

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

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

本次冲突已逐段处理并推送 84c18824ed,纳入 upstream/main db723ff786。

唯一源码冲突是 MessageRenderer 的三处普通文本/强调/删除线分支;保留主干 StaticSpan、原生 UITextView 与缩放限幅,保留附件预览分派和交互入口,没有回退统一集合或直接音频读取。

验证:180个相关用例、Mobile类型检查、设计台账、测试卫生、diff/DCO通过。两端旧原生包均先更新到匹配当前指纹的产物并核对安装内容;iOS浅色、Android深色实际验证强调/代码/表格、消息打开code.json4/7、切到已加载PDF3/7、关闭回到来源。截图和过程已补证据README;测试App、模拟器与本任务Metro已退出。

没有新增测试或无关全量。原完整验收矩阵缺口和独立CI扫描问题#8369继续明确,不据此宣称整体可合并;最终合并由仓库管理负责。

@zqchris

zqchris commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

已核对当前 head 84c18824ed 的实时审核状态:

  • 返回的所有 CI 均 SUCCESS:verify/checks、Linux/Windows 四分片及汇总、Windows runner/database、Desktop Git integration、设计依据与 DCO。
  • 5 条审核讨论全部 resolved,无 unresolved。
  • PR 为 OPEN / 非 Draft / MERGEABLE;正式审核仍 REVIEW_REQUIRED,已有 review 仅 COMMENTED,尚无 APPROVED,因此 GitHub 仍显示 BLOCKED。

已更新 PR 当前交接状态,等待仓库审核;最终合并由仓库管理负责。本轮没有代码修改、重复测试或推送,也未代为批准/合并。原公开补充验收缺口继续保留,不将 CI 通过等同于全部环境已验收。

@xd-bobo xd-bobo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved by compliance check: CI passed and no blocking reviews.

@MagicLizi MagicLizi removed the status:ci-running CI 还在跑(review-pr 自动维护,仅展示) label Nov 1, 2026
@MagicLizi

Copy link
Copy Markdown
Contributor

PR #8356 独立审查报告(heavy 档)— pass

head 84c18824ed59fee0882075f82eec67fb3190b35a · base db723ff786c9b5e8c9e628fab277ff01f38dc185(main)· diffHash c34d8231…c567b(144 文件 / 约 11.3k 行)

Findings

没有可证实的 P0/P1。逐项定性记录(非阻断):

  • security.softHits 4 处(apps/mobile/src/session/documentPreviewAssets.generated.ts 第 4、8 行):全部位于生成的第三方压缩代码串内部——MOBILE_PDF_JS(pdfjs-dist 5.7.284)与 MOBILE_MODEL_JS(@google/model-viewer 4.3.1 / three.js)里的 URL 特性探测(https://a@b)、着色器矩阵常量(0.7071…、-0.016493…)与分发串(three@0.149.0 的 jsdelivr 引用,被 WebView CSP connect-src data: blob: 挡住网络)。是第三方库文本/数值常量的模式误报,不是真实凭证或个人数据 → 放行。
  • security 触发的 5 处 riskyHardHits(csp-relax / dynamic-eval)逐条定性:
    • pdfWebViewHtml.ts:15 / DiagramDocumentPreview.tsx:37 / ModelDocumentPreview.tsx:51:WebView HTML 内嵌 CSP 均为 default-src 'none',仅放开 script-src 'unsafe-inline'(离线引擎自身)与 img/font/worker/connect data: blob:;无 connect-src 网络面、onShouldStartLoadWithRequest 只放行 about:blank、allowFileAccess=false、allowUniversalAccessFromFileURLs=false、javaScriptCanOpenWindowsAutomatically=false。draw.io 的 PROXY_URL=viewer.diagrams.net 默认值在 CSP 下不可达。
    • documentPreviewAssets.generated.ts 的 dynamic-eval 命中是 pdf.js / draw.io 压缩代码里的 eval/Function 构造字样;PDF 侧显式 isEvalSupported:false、useWasm:false、enableXfa:false,字体与 cMap 全部随包(MOBILE_PDF_BINARY_ASSETS)。属离线引擎固有写法,无新增可达攻击面。
  • PDF 密码:PdfDocumentPreview 只经 injectJavaScript 交给本地 pdf.js(task.onPassword),用后即清空 state,不落日志、不进模型/消息/推送,符合 PR 声明与 input-handoff 精神。
  • glTF 外部资源:ModelDocumentPreview 的 CSP 为 connect-src data: blob:,文件内容不能推导出额外网络/文件读取,与产品合同一致。
  • Desktop lightboxMediaActions(main 进程):saveAs 新增 xdt-video:// 与非图片原件支持时补了 realpath + isPathAllowed + isDangerousAttachmentName 双重校验(symlink 逃逸与危险扩展名拒绝);http 源仅把 URL basename 作为保存对话框建议名,过滤路径分隔符与控制字符,且经用户确认。未放松既有权限边界。
  • filePreview.ts 的 shouldOpenTextLightbox* 从「非文本交系统打开」改为「一律进应用内查看器」:8 个调用点(ToolCallCard、UserMessage、UserAttachmentChip、TurnChangesCard、MarkdownRenderer、AgentActionRow、GeneratedFilesCard、ComposerAttachments)都经 TextLightbox → FileLightbox 按真实类型分派到既有只读渲染器,原件操作(保存/外部打开/在文件夹显示)在查看器内显式提供,不再有静默外发打开。属产品目标本身("非文本附件不得静默离开 Cindy"),非扩范围。
  • scripts/__tests__/design-inventory.test.mjs:把钉死真实文件圆角数的断言换成隔离 fixture 测扫描器契约(class + camelCase 计数、注释排除),扫描器与基线均未弱化,属合法的测试重写而非删除覆盖。
  • UI:颜色/间距走语义 token 与 useTheme,pnpm ui:check 6/6(light + dark × zh-CN/en/de)与三端真机截图(iOS 浅色、Android 深色)证据齐备,未见硬编码颜色绕 token 或自造组件顶替设计系统。
  • bot 意见消费:Greptile 5 条(3×P1、2×P2)全部在 c49c27d 修复并在代码中核验落实(annotationSourceUrl 原图/烧录图分离 + 撤销回归、messagePayload 直连音频 previewable 分派、.mmd 失败态保留公共外壳可关闭、集合传递 initialLine/焦点归还、PDF fittedWidth 宽高同基准);Codex review 自身执行失败("We couldn't complete this review"),无待处理意见。
  • 机器人静默期超时放行:copilot-pull-request-reviewer、chatgpt-codex-connector 至今未对当前 head 表态,其意见可能在合并后到达(按 gate.botSettle 口径如实披露)。

Rule coverage — 读取的规则文件及逐项结论

  • AGENTS.md / docs/dev-rules/development-workflow.md / PR 模板:格式门通过(feat 标题、三大段齐、风险与回滚完整、DCO 检查绿);不触碰 updater / localDb schema / drizzle / server 红线路径;无受保护路径(.github、CODEOWNERS 未改)。
  • docs/dev-rules/electron-security-and-process-boundaries.md 口径(Desktop main/renderer、WebView/IPC):新增 IPC 仅 lightboxMedia 保存链路的 realpath 校验,主进程继续以 isPathAllowed 白名单兜底,renderer 不获得新权限。
  • docs/dev-rules/media-storage-and-protocols.md(媒体/附件/缓存/回收):远程读取沿用既有 resolver 与缓存租约(retainRemoteFilePreview / protectLocalFile / withDownloadedRemoteMediaFile 30MB 上限),关闭/切换 abort 并释放,未改协议与 grant。
  • docs/dev-rules/mobile-development.md 冷更边界:无 native dependency、无 config plugin、无 fingerprint 变更(离线引擎由 esbuild 从既有 lockfile 依赖与 Desktop vendor 生成的 TS 常量,sync-document-preview-assets.mjs 可复现),iOS fingerprint 实测匹配。
  • docs/dev-rules/credentials-and-local-storage.md:分享/导出走受控临时目录(downloadRemoteMediaShareTemp + 用后删除);无凭证入仓;生成资源为公开开源库代码。
  • docs/design-rules/DESIGN.md §2/§3/§4/§5 与 design-governance.md §13:32px/16px(Desktop)与 48px/20px(手机)热区、标题关闭独立于内容缩放;check:design-inventory 59 surfaces 最新;Light/Dark 双模式齐。
  • docs/product-rules/attachment-preview.md(本 PR 新增合同):描述行为要求,不改写既有判据为己开脱;与实现一致(关闭不删附件、集合定序不扫 DOM、30/50MB 上限、密码本地、glTF 不越权)。
  • i18n/GLOSSARY.md 口径:pnpm check:i18n-glossary 通过(12 语言无新增违规)。
  • 规则文档(rules 触发)由维护者 xd-bobo 以 Approve 放行;本报告核对未见以 PR 改判据自证的条目。

Verification — 实际运行的命令、结果、未执行项及原因

(worktree …/worktrees/pr-8356,HEAD 与任务 head 一致;每条均完整落盘取命令自身退出码)

  • node scripts/security-scan.mjs --base db723ff786c…:EXIT=0,ok:true。依赖漏洞扫描未执行(本 PR 无新增/升级依赖,newDependencies=[]);semgrep(p/javascript + p/nodejs,仅新增)0 条 findings;8 个含 TS 类型断言语法的测试文件 semgrep 解析失败(errors 非空),该部分不算已扫描——对应文件已人工通读,无外发/危险写法。verificationLine:依赖漏洞扫描:本 PR 未新增依赖,无需扫描;静态扫描(semgrep,仅新增):0 条。
  • pnpm check:i18n-glossary:EXIT=0(33 已裁决 / 161 待讨论,无新增违规)。
  • pnpm check:test-hygiene:EXIT=0(357 文件在基线内)。
  • pnpm check:design-inventory:EXIT=0(59 surfaces 最新)。
  • git diff --check:EXIT=0。
  • Desktop 定向 Vitest:lightboxMediaActions(50) + textLightbox(32) + TextLightboxInteraction(3) + PdfPreview(15) = 100 通过,EXIT=0。
  • Mobile 定向 Vitest:pdfWebViewHtml(2) + filePreviewAndroidPdf(1) + pdfPreviewSource(5) + messageGallery(48) + filePreviewPagerWiring(34) + botGroupAttachmentLightbox(22) = 112 通过,EXIT=0。
  • typecheck:desktop EXIT=0、mobile EXIT=0、@cindy/maker-shared EXIT=0。
  • 未执行:全量测试套件与 Windows/真机矩阵(由 CI 与 PR 验收记录覆盖;GitHub 上 client-ci 含 Linux 四分片、Windows、verify-checks、设计依据、DCO 均 success,gate.ci.status=pass);设备实测沿用 PR 验收记录,本轮未重启模拟器。
  • 证据文件:pr-8356-security-scan.json、verify-*.log(roundDir)。

Intent alignment

  • 描述来源:PR 标题/正文(2026-11-01T23:11Z 经 context 读取)——「统一 Desktop / iOS / Android 的全部附件预览(任务与伙伴),保留设计还原度」,明确不包含服务器改动、外部 IM 客户端界面、插件授权协议与原生依赖升级。
  • 初始实现 SHA:9122c27dc77e1021f2cf1fd812c4369f0d3bc46d(feat(preview): unify attachment viewing across desktop and mobile,102 文件 +7880/-2643,含共享合同、三端查看器与验收证据)。已实际读取该 revision 的关键文件并与 head 对照。
  • 待合并 head:84c18824ed59fee0882075f82eec67fb3190b35a。
原目标/初始行为 最终行为与影响 代码/提交证据 变化依据或待确认问题
三端统一预览外壳(文件名/常显关闭/原件操作/集合导航) 保留;TextLightbox/FileLightbox/PreviewChrome 与 Mobile 侧 DocumentPreviewChrome/RemoteAttachmentPreview 全部落地 head AttachmentCollection.tsx、PreviewChrome.tsx、docs/product-rules/attachment-preview.md 一致
Android 应用内 PDF(不跳应用) 保留并增强:离线 pdf.js,宽+高适配、查找、密码本地 pdfWebViewHtml.ts(initial→head 仅 7 行适配修复) Greptile P2 修复,行为仍在原目标内
非文本附件不静默离开 Cindy 保留:系统打开移入查看器显式「打开原件」 filePreview.ts + FileLightbox.tsx 一致
明确不包含:协议/授权/原生依赖变更 未触及:无协议字段、无 grant/迁移、无 native 依赖(newDependencies=[]) diff 文件清单(144 文件)核对 一致

后续 7 个 commit 全部为审查修复(5 条 thread 修复 + CI 分片/守卫/排版修复)与 3 次 upstream 合并解冲突(生成台账重建、保留主干 StaticSpan/UITextView 优化),未见删除/削弱核心功能、无关扩范围或以禁用/绕过方式消错。结论:一致,无原意偏离。

Overall

pass —— 没有 P0/P1。0 未解决 thread、维护者确认门已由 xd-bobo 的 Approve 放行(product/security/rules/arch 四类触发全部 released)、CI 全绿、stale-rebase 与受保护路径均不构成阻断。bot 静默期超时放行的两个机器人(copilot-pull-request-reviewer、chatgpt-codex-connector)意见可能合并后到达,建议合并后按 post-merge sweep 惯例关注。

@MagicLizi
MagicLizi merged commit 655962b into makecindy:main Nov 1, 2026
17 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.

3 participants