OpenProgram / Runtime 操作 / 规范设计

文件修改、Review 与历史恢复

本页统一定义文件归因、单轮 Undo、历史 Revert、多轮 Rewind、对话 Branch、Review scope、冲突处理和恢复存储。聊天视觉规范只负责外观;任何实现、测试和宣传口径均以本页语义为准。

当前实现 · 统一文件窗口与历史本地资源 · 预览与编辑范围 · App / Web / TUI / runtime

返回刚才浏览的位置

文件夹 A → 子文件夹 B → 文件 1 → 文件 2。后退逐步返回此前的位置,前进恢复后续的位置;后退后打开其他位置会替换原来的前进记录。文件夹恢复路径、展开状态与滚动位置,文件保持既有自动保存行为。

列表加载下一页、后台刷新与文件大小更新保留当前视口。只有用户主动定位、搜索跳转或导航恢复可以改变浏览位置。

实现状态与边界

导航与滚动稳定性及打开文件时保持会话路由已通过功能复核、质量复核与完整验证。当前项目保留最近 100 个浏览位置,导航记录仅保留在当前窗口内。复用现有标签和导航入口;不修改磁盘文件,不新增轮询,不将导航历史混入文件版本 History。

在同一个窗口查看、编辑和找回文件版本

打开文件先预览,进入编辑后自动写入。History 显示人工与模型修改,恢复前检查当前版本。下方是交互设计演示,格式引擎与保存流程仍在实现验收中。

Proposal.docx

修改后切换标签

最近修改先保存在本地草稿,后台写入文件。回到标签时继续编辑;不需要 Save,也不常驻显示 Saved。

另一个程序也修改了文件

显示“文件已被其他操作修改”。保留当前草稿,可查看磁盘版本或另存副本;不自动覆盖。

打开旧版本

使用与当前文件相同的预览器。恢复是一次新的有记录操作,保留恢复前内容,支持重新应用。

常见格式的实际目标与复用方案

文本、代码、Markdown:预览、源码编辑和自动保存。DOCX、PPTX、XLSX:本地完整引擎预览与编辑,必须通过真实文件的打开、修改、导出和重新打开验证;不能以提取文字替代页面或幻灯片预览。旧 DOC/PPT/XLS 与 ODT/ODS/ODP 纳入兼容测试,若引擎只能转换则明确另存新格式,不覆盖原格式。CSV/TSV 至少可表格预览和文本编辑。PDF:分页、缩放和搜索,批注或编辑按组件实际能力开放。PNG/JPEG/WebP/BMP/GIF/SVG/TIFF:预览;静态位图提供裁剪、旋转与标注,动画或矢量不得在普通保存时静默栅格化。PSD:合成图和图层信息预览,保留原始 PSD;只有通过无损回写验证的操作才能启用原格式编辑。音频与视频复用本地 HTML 播放器。无法解析、加密、超限或尚不支持的文件有明确状态与下载入口。

候选 Office 方案包括 ONLYOFFICE Docs、OnlyOffice browser/WASM 与 LibreOffice WASM。默认方案必须本地可部署,不要求用户上传文档到第三方网站。完整服务器方案保留为可配置适配器候选,不能作为默认安装缺失时唯一能力。

PDF.js 是 PDF 浏览候选;TOAST UI Image Editor 是位图编辑候选,关闭 usageStatistics 并自带资源;ag-psd 是 PSD 预览候选,其色彩模式、文字图层与效果限制要求保留原文件。Photopea 支持嵌入但属于第三方托管页面,不默认加载或传入本地文件。最终选型以固定版本源码与本地样例验证为准。

统一打开、编辑和版本协议

文件引用包含稳定的项目或会话归属及相对路径,显示路径不是权限凭证。能力识别先核实扩展名、类型和文件内容,再选择预览或编辑适配器。适配器只获得该文档的内容与版本,不获得任意磁盘权限;统一导出 bytes/Blob、修改事件、错误事件和销毁方法。Office 与图片大资源只在打开相关文件时加载,不能拖慢聊天首屏。

人工编辑与模型写入共享版本校验、完整文件发布和 immutable before/after 存储原则。既有 project_file_write 的幂等记录只有操作结果与指纹,不等于可恢复的文件版本;本次补齐实际版本保存。人工修改记录 actor=user,模型修改关联 session/turn,不伪造聊天轮次,也不把人工历史变成侧栏会话。History 按文件汇集来源,模型本轮 Review 继续保留其归属语义。

版本数据按归属保留:项目中的人工编辑历史归项目,模型记录仍关联实际会话与轮次;汇总索引只引用已有版本,不另复制来源文档。归档会话仍可打开原记录;彻底删除会话后,其入口与归属版本按现有删除规则清理,汇总页不得用缓存重新显示原文。Memory 中残留来源仅标记“原会话已删除”或移除链接,不为此建立来源副本。项目文件及其独立人工历史不因删除一段聊天而一并删除。

自动保存和版本归档分开:编辑器正常撤回处理即时修改;草稿先持久保存,文件在有修改事件后的短暂合并窗口自动发布;History 默认按连续编辑时段归档,间隔约五分钟形成版本,切换文档、结束编辑或恢复操作也完成归档。文件内容不等待五分钟才保存。每次发布校验读取时的 revision,重复请求幂等,乱序响应不能覆盖新草稿;保存失败保留草稿并显示可重试错误。重启后读取持久记录,不根据当前文件补造过去版本。

富文档编辑器的生命周期独立于标签视图。切换标签时先隐藏视图,仍在导出的引擎继续保留;最新内容进入持久草稿后才能释放引擎。Office iframe 在同一文档会话中不因 React 重新挂载或 DOM 移动而重建。关闭、重命名和版本恢复均先等待最终导出,失败保留编辑器和草稿。预览与编辑复用同一实例;只读历史实例不能回写当前文件。

论文阅读与批注

上游查看器样式表及其根变量都限定在 PDF 阅读器范围内。例如以下通用名称: .sidebar 不得改变外层应用界面。

PDF 工作区遵循提供的 PDF Expert 参考中的紧凑阅读布局:现有 OpenProgram 文档标签页位于扁平工具栏上方,可折叠左侧栏包含缩略图与文档大纲,其余空间连续显示 PDF 页面。阅读控件提供页面导航、适应宽度/页面与数值缩放、文本选择、文档内链接和搜索结果高亮。只显示已实现的阅读与批注工具;原文编辑、OCR、页面结构操作与格式转换不在本轮范围内。

视觉系统继承 OpenProgram 字体与浅色/深色主题变量:中性工具栏、白纸、深色阅读背景、低对比分隔线与蓝色选择强调。参考配色:正文 #202124、工具栏 #27272a、画布 #151517、纸张 #ffffff、分隔线 #414145、焦点 #4a90e2。工具栏标签使用13px应用字体,控件高32px。桌面端使用单一阅读工具栏与上下文批注行;窄面板中控件换行,不覆盖文档文字。侧栏宽180px且可隐藏。使用真实渲染页面,不提供占位内容或装饰性仪表盘元素。

使用已固定的 PDF.js 6.3.289 legacy 查看器库、文本层、链接服务、搜索控制器与批注编辑器,保留本地模块/worker 兼容性与生产 CSP。上游 查看器源码 定义生命周期与编辑器 API。PDF Expert 的 Mac 功能参考 提供阅读与批注对照。备选的 EmbedPDF 查看器 本轮不采用:所需阅读、高亮与文字批注能力不需要替换解码器或引入第二个渲染引擎。

复制 PDF 文本层选区时自动合并排版换行。保留段落换行与原始标点,连接 CJK 文本时不插入空格,保留普通连字符并移除可选软连字符。这仅是本地剪贴板转换,不编辑 PDF,也不作用于搜索框、批注文字编辑器或其他应用内容。可见复选框允许保留原始换行。

项目 PDF 通过 PDF.js 支持高亮与自由文本批注,使用现有 DocumentController 富编辑器租约、持久草稿存储与乐观版本检查保存标准 PDF 批注。防抖导出、显式保存、关闭、历史恢复与重命名沿用 Office/位图文档的控制器归属。更新草稿字节不得重建活跃查看器或丢失撤销栈。历史快照与附件保持只读。不启用 PDF 自带脚本或外部文档上传;保留原始字节、输入与画布限制、错误处理和下载。

验收通过真实 FileViewer/DocumentWindow 入口,在生产 CSP 与桌面兼容 API 下执行。验证连续非空页面与可选文本,涵盖普通文本/CJK/段落的剪贴板内容,页面/侧栏/大纲/缩放/搜索行为,只读历史/附件,高亮与批注创建,真实 PDF 字节的保存及关闭/重开,通过独立解码器验证持久批注,失败保留和禁止过期编辑器发布。仍须执行现有文件/历史/控制器、完整 Web、仓库契约、浏览器与文档检查,之后进行两项独立审查与已安装 App 检查。

PDF 运行时兼容性

本地 PDF 解码器固定为 PDF.js 6.3.289。主模块与 worker 使用匹配的 legacy/build 发行构建,通过现有同源 /document-assets/pdfjs/ URL 提供。上游 浏览器支持指南 与包 README 要求缺少较新 JavaScript API 的环境采用此构建。现代构建要求 Uint8Array.prototype.toHex,桌面 Electron 37 / Chromium 138 运行时缺少该 API。Legacy 配对在两个执行上下文都提供上游兼容代码;仅主页面的 polyfill 无法修复 worker。

保留已审查解码器版本、本地 CMaps、字体、WASM、许可证清单、延迟加载、64 MiB 输入上限、画布限制、禁用脚本和原文件下载。本次修复不升级 Electron,也不添加应用自有全局 polyfill。生成的 manifest 同时标明版本与构建类型。只读 PDF 能力保持不变。

应用界面允许 connect-src 'self' blob: ,使解码器可通过对象 URL 读取保留的本地文件版本。这只扩展本地字节读取;外部 HTTP/WebSocket 目标仍被阻止,不启用 blob 脚本、eval、对象或第三方框架。PDF 验收将真实应用策略用于测试页,包含外部请求被拒绝的探测。宽松独立浏览器测试不能证明已安装 App 行为。

验收使用公开 FileViewer 入口验证非空页面渲染、导航、缩放、文本搜索、无效输入恢复与无运行时错误的关闭/重开。在主页面与 worker 缺少原生 toHex 和 Math.sumPrecise 时执行相同检查,并在已安装桌面端使用报告中的 PDF 检查。资产 manifest 必须标识实际暂存模块与 worker 字节。这些检查补充完整 Web、仓库契约、浏览器与文档检查。

可选 Office 安装

Office 文档支持是演示文稿、文字处理文档与电子表格共用的可选本地组件。默认 App、runtime 与 Python 构建不包含其资产,也不下载。打开尚不支持的 Office 文档时只检查本地可用性;缺失时文档界面说明支持格式、约699 MiB下载、本地处理和 ONLYOFFICE 许可证,并提供“安装”与“取消”。取消只关闭安装选择,不下载,之后可再次选择。PDF 查看保持独立。

只有经 owner 认证的本地来源 POST 可从固定发布 URL 与固定归档 SHA-256 启动安装。安装器限制下载与解压,拒绝不安全归档路径和链接,验证完整 Office manifest,并将资源包原子发布到 profile 缓存。并发请求共享一次安装。失败保留此前选定资源包并删除临时下载。安装完成后,当前 worker 无需重启即可提供父模块与隔离宿主,文档自动打开。关闭文档会停止其 UI 请求;已明确请求的安装可继续完成以供其他文档使用。

此前安装的 profile 资源仍可使用,旧发布随 App 打包的资源不再被选用。开发暂存仍是编辑器测试的显式独立命令;普通构建忽略过期暂存包。不引入通用扩展注册表、自动更新、卸载控件或第三方文档上传。

Office 加载

Office 启动时,在居中且适配主题的加载浮层下保留完整尺寸渲染区域。状态遵循应用语言,区分资源加载与文档打开,不使用模拟百分比。启动错误替换状态并提供明确重试入口。

适配器使用固定上游 mount/activate API,关闭正在加载的文档会立即销毁待处理宿主。AbortSignal 取消可用性请求与待处理激活;有界启动期限从激活前开始。失败或取消的实例不附加到文档控制器。预览/编辑切换保留已有编辑器与原生撤销。独立 Office origin、资产身份检查与持久化回调保持不变。这减少不必要的并发启动工作;原生冷转换耗时与加载展示分别测量。

Office 在独立来源加载本地固定版本资源,只开放该资源树的 GET/HEAD,不开放主应用 API、认证和 WebSocket。父子页面同时校验来源、实例和消息请求,宏默认禁用。大型资源由用户确认后单独安装到本地缓存;打开文件仅检查安装状态,不自动下载;远程部署没有配置独立资源来源时明确显示不可编辑,不转交第三方网站。PDF、图片与媒体按需加载,保持聊天首屏资源预算。文件窗口只在打开文件时加载;KaTeX 保留完整 WOFF2 字体,不再重复引用面向旧浏览器的 WOFF/TTF 回退。资源检查保留 2 MiB 首屏压缩传输与 350 KiB 单块压缩脚本上限。

大型二进制通过受限字节上传或本地暂存传输,不编码到普通聊天消息。边读边检查体积,取消时清理临时文件;引擎消息校验来源、实例和请求 ID。文档脚本、宏、HTML/SVG 活动内容不获得主窗口权限;第三方服务仅在用户主动配置并知悉文件将送往该服务时使用。原格式不支持安全写回时,提供明确的导出副本,而不是把 PNG 或 OOXML 内容写进其他扩展名。

完整交付与验收,不以部分格式通过替代整体完成

工作顺序:验证复用引擎;完成统一文件版本与二进制发布接口;接入格式预览和编辑;统一预览优先、自动保存和 History;验证历史恢复、窗口切换、重启与错误状态;执行独立规范与质量审查及组合版本全量检查;最后更新默认 App。每个适配器都需要真实有效文件,不用伪造二进制证明格式支持。

验收逐项覆盖 Word、PPT、表格、图片、PSD、PDF、文本与媒体。可编辑格式须实际修改内容、写回、重新打开并验证版本恢复;只读格式须实际渲染并明确能力。包含并发外部修改、写入中断、损坏文件、超大文件、取消、断网、项目路径变化和旧历史兼容。所有可见支持状态、源代码、测试与安装版本一致后才标记完成。

一个模型,四种操作

四个词不能互换。操作名称直接表达修改代码还是对话、作用于一轮还是一段历史。点击左侧操作查看完整影响。

操作
四种语义不是四个同级按钮。Turn card 只显示当前适用的 Undo 或 Revert;user checkpoint 进入 Restore sheet;assistant message footer 才提供 Branch。成功 Undo 后,严格预检可用时在 UI 显示 Redo;历史 Revert 的反向操作显示 Reapply。两者都执行新的 reapply transaction,不维护独立线性 redo 栈。

文件版本的完整生命周期

同一个历史入口处理文本、Word、PPT 和后续文档工具。完整文件负责恢复;文本或格式预览只是显示方式,不改变原始版本。以下展示使用状态,内部实现展开后查看。

连续修改同一份文件

Proposal.docx
第一轮:原文 → 修改后
同轮继续修改:更新最终版本

历史仍保留原文;新版本提交成功才替换记录

保存途中中断

Proposal.docx
文件写入结果尚未确认

重新打开可看到未完成状态,不显示为“没有修改”或允许不确定恢复

历史文件损坏

无法读取文件修改记录

保留原记录并报告错误,不重建空历史,不继续覆盖目标文件

正常保存、失败重试与旧版本保护

每份 before/after 使用独立且完整写入的版本文件。持久化顺序是版本内容、校验、版本目录,再发布 manifest。更新 manifest 失败时,前一份成功记录引用的内容仍完整。失败尝试不覆盖已发布版本。只有尚未成功的尝试被明确取消后,重试才以重新读取的当前文件建立 before;已成功修改始终保留本轮最初 before。

准备记录与提交记录分开。未完成的写入保留待确认标记,历史投影显示不可精确恢复,不能推断脚本成功,也不能用当前磁盘内容补造 after。取消且确认没有成功提交的尝试不展示为已修改。损坏或不支持的 manifest 返回明确错误;仅真正缺失的 manifest 表示没有记录。旧版本 manifest 和旧 blob_ref 继续可读,无批量重写迁移。

DeepSeek 与 Codex 的源码依据

DeepSeek 的 JSONL 持久化 使用同步临时文件、独占发布与目录同步,并明确区分损坏记录和缺失记录;会话修复 把中断工具标为结果未知,而不自动补造成功。采用这两项原则保护版本内容与中断状态。其 fs-local 提供目标锁、版本条件检查和文本写入结果,但未提供完整文件 undo/reapply 或 Office 版本管理;因此保留 OpenProgram 现有恢复事务,不把会话日志恢复等同于文件恢复。Codex 的 exact delta 归因继续保留,不把任意 Bash 操作视为精确修改。

新工具如何接入,哪些能力不属于本次实现

本地生成器统一调用 write(file_path, source_path=...) 发布完整文件。文本工具保留 write/edit/apply_patch 入口,共享 checkpoint 的 prepare/commit/abort 合同。不能只提交模型声称的“修改成功”,也不能执行任意 Bash 后扫描目录并归因。状态存储由 CheckpointStore 管理,Review 和会话摘要只作投影,不另建版本副本。未来 Office 语义差异只读取不可变版本,不承担撤销;远端存储需要条件写入和可验证版本标识,在具备这一能力前不宣称支持精确恢复。

本次保留现有单轮聚合、会话分支和恢复事务;不新增全盘扫描、定时轮询、通用插件注册框架、Office 修订视图或远端存储实现。已丢失的历史不能补回。系统崩溃与不遵守文件锁的外部程序仍可能造成待人工处理状态;系统保留证据并拒绝不确定覆盖,不承诺所有外部修改都能自动恢复。

实现与验收计划

先复现连续写入提交失败、失败后重试和损坏记录覆盖;再修复共享历史存储及未完成记录投影。通过注册工具、重新打开会话、Review 与恢复入口验证,最后进行独立规范审查、质量审查和全量检查。该节对应共享历史存储、会话摘要与 Review 投影已实现;独立规范和质量审查、故障回归及全量测试均通过。

文档修改与版本恢复

Word、PPT、PDF 与图片使用完整文件版本。打开这一轮的文件记录可确认修改的文档;撤销恢复修改前的文件,重新应用恢复修改后的文件。重启后仍读取同一份持久记录。

修改完成

Proposal.docx · 文件内容已更新

查看文件记录 · 撤销本轮修改

重新打开会话

同一轮仍显示 Proposal.docx,历史版本不依赖脚本输出或内存缓存。

查看记录 · 重新应用

文件后来又被修改

撤销前检查当前文件。内容与已保存版本不一致时阻止恢复,保留后续修改。

文件已变化,未执行恢复

实现方式与范围

脚本将结果写到独立临时文件,再通过现有 write(file_path, source_path=...) 发布。content 与 source_path 必须且只能指定一个。source_path 是本地普通文件,受读取权限限制;目标继续执行写权限、读取基线与审批文件指纹检查。来源和目标均纳入审批等待时的文件指纹;发布前复核。工具在目标目录生成临时文件,完整写入后替换目标,失败清理临时文件,并保留原目标。工具按原始字节写入,记录 before/after,不将文档转成文本保存。源与目标相同、目录、链接、超限或不可读取的来源在修改目标前失败。来源读取有 64 MiB 上限。已有目标在 advisory lock 下复核打开的文件句柄、内容和路径;这只能串行化遵守该锁的写入,不能阻止外部程序在最终校验与替换之间写入。Windows 在替换前关闭不共享删除权限的句柄并再次校验,因此不承诺操作系统级条件替换。

参考 Codex TurnDiffTracker 的 exact delta 检查与 shell 快照 的暂存、验证、替换流程;后者保存 shell 环境,不是文档版本。沿用 Codex 的明确修改操作归因:通用 Bash、后台进程与外部编辑器不自动成为本轮精确修改。脚本不能直接覆盖最终目标后再补写历史。保留既有文本 write 参数、失败语义、回退事务、分支归属及持久会话布局。文档格式、图片和排版均由完整字节版本恢复;当前不提供 Word 修订标记或 PPT 视觉差异。

读取基线必须先建立:模型先用 read 读取原文件,再生成暂存版本。二进制读取返回文件类型与字节数,不向模型输出乱码。新文件不要求先读。脚本工具说明明确这一流程,无额外保存按钮,无全盘扫描与轮询。

验收经注册 write 工具、会话重新打开及公开历史操作完成:创建和覆盖 DOCX/PPTX 后保存版本;撤销及重新应用逐字节一致;外部更改导致冲突;失败不替换目标;旧文本写入仍有效。

当前实现与必须修复的缺口

以下均由当前源码确认。它们解释了十几万行误统计、响应慢和多轮恢复可能产生部分成功的原因。

当前路径现状风险目标
agent_loop._snapshot_cwdBash 前后 cwd 扫描、候选预复制和执行器调用已删除。普通 Bash、后台日志和外部写入不再进入 turn mutation。完成 仅 trusted file mutator 生成 receipt。
_checkpoint_changed_files该路径已删除;prepared receipt 明确区分 regular before image 与 absent。超过统计预算的既有文件保持 modify,stats 为 unknown,不再按新文件整量新增。完成 baseline 缺失不编码成 absent。
CheckpointStore.restore_turn单轮入口使用全量 plan、profile-stable lock、durable intent、条件式 leaf mutation、verify 与 rollback;legacy 方法只保留给迁移测试,生产 revert_turn 不再调用。冲突、缺 blob、stale plan 均零写入;外部 pathname/open-fd race 保留外部内容并进入 recovery_required。完成 单轮与多轮均使用事务式 apply。
rewind_to使用 active suffix 一次规划、同路径折叠、dirfd/no-follow 条件写、durable intent、文件验证后 HEAD CAS;不逐轮 revert 或改写旧节点。文件、plan、父目录、HEAD 或 branch version 变化均阻止提交;mixed crash state 在启动时安全回滚或进入 recovery_required。完成 WS 默认只返回 plan,apply 必须携带 plan hash 与幂等键。
rewind_to + 调用方子树同 session、非 worktree、带显式 origin 的 owned child 递归纳入 causal closure;每个 receipt 带持久单调 mutation_sequence,同路径按实际 workspace 顺序折叠。running owned 或同 workspace linked actor 阻止恢复;completed/cancelled/errored 且有 durable head 的 owned change set 进入同一事务,legacy ambiguous job 不获得恢复权限。完成 linked peer/cross-session 与 worktree 只报告影响,不并入父 change set。
/api/chat/checkout以一次 HEAD CAS 同步写入 workspace mismatch;连续 checkout 保留真正物化文件所属的 source head。下一次 mutating turn 在明确选择 Keep current files 或 Restore branch code 前被阻止;两个决定均绑定 source/target,stale 请求不能采用新 checkout。完成 Restore 复用事务式 preflight、幂等键、rollback 与 crash recovery,且不移动 conversation HEAD。
ProjectGit.revert_agent_commit已从单轮 Undo/Revert 生产路径移除 ProjectGit 调用。单轮历史恢复不再 reset/revert 用户 Git,不读取或修改 index/commit。完成 Workspace Git 操作保留独立入口。
ShadowGitStoreTurn/Branch Review 与 diff 只读 exact mutation journal;Workspace Review 只读 Git status/numstat。Shadow Git 不再是 Review 事实源。legacy shadow commit 路径仍存在,但不再影响文件卡、Review 或恢复资格。Review 降级完成 后续可独立清理 legacy cache。
检查点回收 / 未知轮次plan 必须证明目标 turn、全部 actions 与 recovery blob 可用;unknown、expired、corrupt 或不精确 receipt 不显示可执行历史 action。Review metadata 仍可读,但 code restore 返回 unavailable;不会写 Reverted metadata或移动 HEAD。完成 Expired 只允许只读 Review。
分支元数据统一 restore transaction、HEAD/version CAS、branch refs、writer epoch 与 checkout workspace alignment;source leaf 保留,旧 conversation 节点不因 Rewind 被全局隐藏。checkout、Keep、Restore 都绑定 expected source/target;并发 HEAD 或文件变化返回 blocked、rolled_back 或 recovery_required。完成 branch projection 与 Review 使用同一 mutation sequence。
TurnFilesChips聚合值与前三个文件随 assistant metadata 持久化;legacy 仅在进入视口后查询。卡片最多挂载 20 行,不再挂载 diff。Review 文件列表每页 100,diff 每页最多 200 行 / 256 KiB,并用 request id + snapshot 防止旧响应和跨 scope 读取。完成 点击文件或 Review 打开确定性的 center Review tab。
Web / TUI / Python CLIWeb WS 与 Python CLI 统一使用只读 plan、显式 confirm/apply、plan hash、幂等键和结果状态;Web center Review 已接入三个 scope。Web diff/payload 有界且 actor/producer/linked impact 可见;TUI/CLI 保持同一恢复协议,不复制 Web center pane。协议与 Web Review 完成
项目文件浏览器目录按展开时加载;搜索只在已加载目录的节点中进行。未展开目录中的文件不会被搜索到;目录结果没有可复用的稳定 snapshot/cursor 合同。待实现 project-scoped 后端搜索、目录分页与稳定 cursor。
文件 WebSocket 生命周期部分 Review 请求已回显 request_id;项目文件请求仍依赖按响应 type 的全局串行队列,list_turn_files 没有 request id。并发时不能由每个调用独立认领响应;全局串行会把无关的文件加载相互阻塞。待实现 所有文件相关 WS action 强制 request_id 并按该 id 关联响应。
读取缓存与草稿读取缓存和未保存草稿均无容量上限;草稿只在页面内存中保存。长期使用会累积内存;刷新页面可能丢失 dirty draft。待实现 有界 LRU read cache 与独立、持久化的 dirty draft store。
审查筛选与分页Review 先取一页文件,再在客户端按 Code/Tests/Docs/Large 分类。分类结果只代表当前页;不同页和 workspace 变化之间不能形成稳定的筛选视图。待实现 server 先筛选与排序,再对固定 snapshot 分页。
官方参考、采用与边界
系统确认行为采用不采用或未知
Claude Code 检查点每个 user prompt 建 checkpoint;只跟踪 Write/Edit/NotebookEdit,明确不跟踪 Bash。可分别恢复代码、对话或两者;无 tracked edit 时不显示代码恢复。除前台 context: fork skill 外,其他 subagent 修改不恢复;symlink/hardlink/non-regular path 会跳过并警告,因此可能部分恢复。每 session 最近 100 个文件 checkpoint;checkpoint 随 session 保存并受默认 30 天、可配置 cleanupPeriodDays 清理。采用 prompt checkpoint、分离恢复选项、明确 unavailable。调整 OpenProgram 对任一路径失败执行整体阻止或事务回滚,不接受 skipped 后整体成功。超过 100 后旧 prompt 是否仍支持 conversation-only rewind 未获官方保证。
Claude Code 分支/branch 与 SDK fork 把 conversation 复制到新 session,原 session 保留;明确不复制或回退 filesystem。VS Code 另行提供 Fork conversation and rewind code。调整 OpenProgram 保留同-task Branch,并新增 source-preserving new-task Fork;with-files 在 Git 项目用隔离 worktree。不采用 fork 后默认复用当前 files 却不说明。
Claude Desktopsession diff 入口;左文件列表、右单文件 diff;支持行级评论和 Review code。采用 独立 Review、单文件按需 diff、结构化行级反馈。不复制 品牌、图标、尺寸、工具栏顺序和 PR 控件。
Claude Web确认 session diff、左右布局、行评论和 Create PR;官方页面没有确认 Review code。采用 Review 与聊天分离。未知 不把 Desktop 的 Review code 能力推定到 Web。
Codex 精确轮次差异TurnDiffTracker 只在当前 turn 内消费 exact AppliedPatchDelta,不重读 workspace;不精确时使 turn diff 失效。它是内存聚合器,不是持久恢复日志。调整 采用 exact delta 作为归因输入;OpenProgram 自行增加持久 receipt、digest、before/after blob 和 transaction 状态。不声称 Codex 提供 durable Undo journal。
Codex 历史thread/fork 创建新 thread ID、只复制 history;TUI 编辑旧 prompt 使用 source-preserving fork。旧 thread/rollback 已废弃,实验性 thread/revert 只处理 conversation;两者都不恢复文件。采用 source-preserving fork 和不可变历史。未知 Codex App 是否另有未开源的 per-turn checkpoint/turn-card file Undo。
Codex Git 审查Repository Review 区分 Last turn 与 Git 状态,并提供 Unstaged、Staged、Commit、Branch、多 repo、行评论和 Git whole/file/hunk stage/revert;TUI /diff 对 untracked 使用 --exclude-standard。采用 Workspace Git 子范围和 ignored 排除。分开命名 Git Discard 不是 checkpoint Restore;具体 desktop Git revert 实现不当成 turn Undo。
参考系统没有公开保证的部分:Claude 对外部并发修改的覆盖/拒绝/合并规则、多文件原子性、digest preflight 和崩溃一致性均未说明;Codex exact turn delta 的长期持久化与 Desktop per-turn file Undo 未确认。本页的全量预检、workspace lock、durable intent、rollback staging 和 crash recovery 是 OpenProgram 新增合同。
目标架构与信任边界

对话 DAG、精确 mutation journal 和 Git workspace view 是三个独立事实源。历史操作 planner 可以读取三者,但只有 journal 中的可恢复 receipt 能授权文件恢复。

文件修改与历史恢复架构直接编辑工具产生精确 mutation receipt,普通 Bash 不进入本轮归因;journal 派生 turn 和 session review,Git 派生 workspace review;历史操作 planner 经过预检和持久化 intent 后才更新文件和对话 HEAD。 可信文件修改器write · edit · apply_patch已验证且可修改文件的适配器 通用 Bash / 外部进程无轮次回执 · 无轮次撤销 修改回执修改前后摘要 · 操作 · 执行者恢复 blob 引用 · 统计 修改日志只追加事务轮次 · 当前分支 · 还原 对话 DAGuser · llm · code 节点HEAD 与同级分支 派生审查范围本轮 · 当前分支工作区仅来自 Git 历史操作规划器影响 · 目标投影冲突与可恢复性 持久操作意图prepared · applyingcommitted · rolled_back 工作区事务加锁 · 暂存 · 应用 · 验证 HEAD 事务仅对话模式
普通 Bash 与 Workspace Review 的边界:Bash 可以在沙箱或 worktree 中运行,但本地共享工作区里的通用 shell 结果不自动归因给某个 turn。Git 能显示当前 workspace 变化,却不能证明它属于哪一轮,也不能赋予 turn Undo 权限。
文件浏览、搜索与 Review 查询合同

Project file explorer 与 Review 都使用 project/session 绑定的服务端快照。目录、搜索和 Review 过滤先确定完整的有序候选集,再返回一页;客户端不得以当前页数据推断项目或 scope 的完整结果。

查询事实源与范围排序、筛选与分页无效化
目录列表由 project_id 解析的项目根目录;path 必须是规范化的根内相对目录。排除路径穿越、符号链接逃逸和服务端禁止浏览的目录。先按类型(目录、文件)和根内规范化路径稳定排序,再建立 snapshot。每页最多 100 项;cursor 是不透明 token,不是数组下标。目录版本、ignore 规则或请求中的 project/path/sort 不匹配时返回 STALE_SNAPSHOT,客户端从第一页重取。
项目搜索服务端遍历同一项目根,并应用与目录浏览相同的访问与忽略规则;不依赖树已展开的节点。结果只包含名称或根内相对路径匹配的项目文件与目录。先以 query、匹配模式和类型过滤,再按稳定 rank、根内路径排序并建立 snapshot;分页只作用于已过滤结果。搜索 query 或模式变化必须丢弃 cursor。项目切换、搜索 snapshot 到期或根目录版本变化后显示可刷新状态;不得把其他项目的旧结果保留在新项目中。
审查范围This turn / Current branch 读取 mutation journal;Workspace 读取 Git 的 HEAD、index 和 worktree。每一项继续携带 source、actor 和 change-set 归因。服务端先按 category、path query、operation、diff state 与排序过滤,随后对该过滤结果建立 snapshot 并分页。计数和 totals 针对完整过滤结果,不是当前页。scope、assistant message、filter、sort 或 snapshot 任一不匹配时拒绝 cursor;Workspace 还比较固定 candidate list 与每个候选的 index/worktree identity。选择的文件若不在新 snapshot 中,清空 selection 和 diff。
审查文件差异只接受已由同一 Review snapshot 返回的 path;turn/branch 读取 journal blob,workspace 读取 snapshot 中记录的 HEAD/index/worktree blob pair。diff cursor 同样是不透明且绑定 file identity、blob pair、scope snapshot 与行预算的 token。每次最多 200 行或 256 KiB。snapshot、候选列表、index/worktree identity 或 blob pair 改变时返回 stale,不返回来自另一版本的后续 diff 页。

稳定 cursor

{
  "snapshot_id": "snap_...",
  "query_kind": "directory | project_search | review_scope | review_diff",
  "owner": {"project_id": "...", "session_id": "..."},
  "basis": "directory/version or journal/Git revision",
  "filter": {"query": "...", "category": "...", "sort": "..."},
  "cursor": "opaque token",
  "next_cursor": "opaque token | null",
  "page_size": 100
}

cursor 不变量

  • cursor 只在创建它的 snapshot、owner、query kind、过滤条件和排序完全一致时有效;服务端不接受客户端提供的 offset、路径锚点或跨项目 token。
  • snapshot 保存候选集的稳定顺序或足以重建该顺序的不可变 revision;后续页绝不重新扫描后混入新增、删除或重排的项。
  • snapshot 可受容量和 TTL 限制。逐出或内容版本改变时明确返回 stale,由客户端刷新首屏;不得悄悄改用最新列表继续旧 cursor。
  • 目录和搜索各自使用 cursor;Review 文件列表与单文件 diff 使用不同 cursor namespace,不能互换。

工作区审查快照

{
  "snapshot_id": "workspace_...",
  "project_id": "...",
  "head_identity": "commit/tree identity",
  "index_identity": "index tree identity",
  "candidates": [{
    "path": "canonical relative path",
    "status": "XY or ??",
    "base": {"kind": "blob | absent", "digest": "...", "mode": "..."},
    "index": {"kind": "blob | absent", "digest": "...", "mode": "..."},
    "worktree": {"kind": "regular | absent", "digest": "...", "mode": "...", "identity": "lstat fingerprint"}
  }]
}

Workspace 不变量

  • 创建 snapshot 时一次性确定未提交 candidate list,按规范化相对 path 排序;它包含 staged、unstaged、untracked、rename/delete 的所有相关 path,且保留旧路径和新路径的对应关系。
  • 每个 candidate 固定 HEAD base、index blob 和 worktree content identity/blob pair。文本 diff 只能从该 pair 渲染,不能在后续请求中重新执行最新 git diff 代替。
  • 请求下一页或单文件 diff 前,服务端重新读取 status candidate vector、index tree identity 和目标 path 的 no-follow worktree identity;任一新增、删除、状态、mode、index blob、worktree digest 或路径映射变化均返回 STALE_SNAPSHOT。
  • snapshot 保存的 content blob 受同一 review storage quota 管理;blob 缺失、超限或过期也返回 stale/unavailable,绝不从当前 worktree 近似补齐旧 diff。

所有文件 WebSocket 请求

规则合同禁止
必填关联键所有文件浏览、读取、写入、创建、重命名、复制、删除、reveal、turn summary、turn diff、Review scope 与 Review diff 请求都带客户端生成的 UUID request_id;成功、stale、validation error 和 transport error 都原样回显。不接受缺失或非 UUID 的文件请求;不再以 response type、path 或到达顺序认领响应。
响应验证客户端以 request_id 作为唯一 pending key,并额外验证 action、project/session、snapshot 与目标 path;组件卸载、项目切换或新查询会取消并遗忘旧 pending key。不得用全局请求队列消除竞态;一个慢目录请求不能阻塞另一个文件 read 或 Review diff。
写入幂等与冲突有副作用的文件 action 还携带独立 idempotency_key 与现有的 optimistic-lock 条件。服务端以 action、owner、canonical payload 和 precondition fingerprint 建立 durable record。request_id 仅关联本次传输,不替代写入幂等键。不把重连后的新 request id 当作新写入;不以缓存 mtime 覆盖服务端冲突结果。
错误形状每个结果提供 request_id、action、owner、status 和稳定 error code;STALE_SNAPSHOT、NOT_FOUND、CONFLICT 与 INVALID_REQUEST 可被 UI 明确处理。不吞掉缺少 request id、错误 owner 或未知 response 的帧,也不将其更新到当前文件状态。

写操作 idempotency_key

{
  "record_key": {"owner": "profile + project", "action": "project_file_write", "idempotency_key": "uuid"},
  "fingerprint": "sha256(action + owner + canonical payload + precondition)",
  "state": "prepared | in_flight | completed",
  "operation_id": "fileop_...",
  "result": "canonical terminal result or null"
}

幂等不变量

  • owner 是经授权的 profile 与 project;canonical payload 使用规范化根内 path、标准化 operation 参数和内容 digest,排除 request_id 与 idempotency_key。precondition fingerprint 包含 expected mtime/digest、源与目标路径、overwrite 条件及影响目录的版本条件。
  • 服务端在与文件 mutation 同一 durable scope 中原子领取 (owner, action, idempotency_key)。同一 record key 的 fingerprint 不同,返回 IDEMPOTENCY_KEY_CONFLICT,零文件写入。
  • 同 fingerprint 的 in-flight 重试绑定既有 operation_id,等待既有操作到本次请求的响应期限;未完成时返回 IN_PROGRESS 和该 operation id,客户端只能重试同一个 key,不能另发写入。
  • 完成后 durable record 保存 canonical terminal result。相同 fingerprint 的任何重试只重放该结果,即使 request_id 不同,也不再次执行文件 mutation。进程重启先恢复或判定 in-flight record,再允许其结果被重放。
  • record retention 至少覆盖客户端重试窗口与 worker restart recovery;过期清理不得删除仍为 in-flight 的 record,且不会将已过期 key 解释为一个不同 fingerprint 的成功重放。

缓存与未保存草稿

存储键与容量淘汰与一致性数据保护
读取缓存键为 project_id + canonical relative path + content revision;最多 64 项且最多 16 MiB,使用访问顺序 LRU。只缓存成功且完整的只读结果。写入、rename、delete、tree revision 变化和容量超限会失效或淘汰最旧的干净 read;缓存未命中只触发新的 request_id 请求。缓存不是编辑状态,也不保存 dirty text。
未保存草稿存储浏览器原生 IndexedDB 的 openprogram-file-drafts 数据库,键为 project_id + canonical relative path;持久化 UTF-8 draft、baseline content revision、baseline mtime、保存状态与更新时间。容量上限为 32 个 draft 或 8 MiB。干净 draft 可删除;dirty draft 不参与 LRU 淘汰。所有 entry 与 aggregate byte/count index 在一个 readwrite transaction 中更新。页面刷新、tab unmount、切换项目和 read-cache 淘汰都不能删除 dirty draft。服务端文件变化后保留草稿并标记冲突,保存必须继续提交其原始 baseline 条件。
路径变更与清理成功 rename 在 IndexedDB transaction 中移动同项目 draft key;copy 不共享 source draft。删除文件先列出 dirty draft,要求明确的保存、保留/导出或丢弃选择。项目 draft 清理只由未来显式 project unlink/delete command 触发;当前产品没有该 action。任何文件操作失败时不变更 draft key。确认 discard 后,文件 draft 与 project aggregate index 在单个 IndexedDB transaction 中清理;清理失败保留原记录并报告失败。不得把 list_projects 中项目消失解释为用户授权。跨项目的同名 path 永不共享 cache、draft、selection 或 search snapshot;不因 tree 刷新、Review 切换、临时 registry unavailable 或后台响应重置编辑器 buffer。

IndexedDB dirty draft 合同

{
  "database": "openprogram-file-drafts",
  "stores": ["drafts", "project_index"],
  "draft": {
    "key": "project_id + canonical relative path",
    "draft_utf8_bytes": 0,
    "baseline_utf8_bytes": 0,
    "baseline_revision": "...",
    "baseline_mtime": 0,
    "updated_at": "local monotonic ordering"
  }
    }

持久化与恢复不变量

  • 使用浏览器原生 IndexedDB,不增加依赖。配额计算使用 TextEncoder 的 UTF-8 byte length,计入 draft、baseline 与所存元数据;project_index 保存每项目的键集合、count 和总 bytes。启动时以 project_index 恢复该项目的 dirty drafts;索引缺失或不一致时扫描 drafts 重建索引,不删除记录。
  • 新建、更新、rename、discard 与未来显式 project cleanup 都在一个 IndexedDB readwrite transaction 内先计算新旧 bytes,再同时写 draft 与 aggregate index。超出 32 项或 8 MiB 时 transaction 不写入,现有 draft 保持不变。
  • 编辑器在接受会把持久化 draft 超出配额的输入前先检查预算;满额时阻止创建新 dirty draft,并显示可见的保存、还原、导出或显式丢弃提示。已有 dirty draft 不自动淘汰;更新已有 draft 遇到浏览器 QuotaExceededError 时保留最近成功持久化版本、显示持久化失败状态并暂停进一步会扩大该记录的编辑,直到用户处理空间或显式导出/丢弃。
  • 删除项目文件时,若对应 dirty draft 存在,服务端删除完成前 UI 必须要求保存、导出保留或明确 discard;成功 discard 才清理该 key。当前没有 project unlink/delete action,因此项目 draft 不因 registry snapshot 缺少该项目而清理;未来显式 command 必须先展示该项目 draft 数量和 bytes,确认后清理所有该项目 keys 与 index;取消或失败不清理。
  • draft 内容仅保存在当前浏览器 origin 的 IndexedDB;不进入日志、遥测、模型上下文、WebSocket payload 或跨设备同步。显式 discard、未来确认的 project cleanup、浏览器站点数据清除和应用卸载会删除本地内容;恢复时不得自动上传或重新写回项目文件。
Review 的顺序固定:解析 scope 和 owner → 取得或创建事实源 snapshot → 服务端过滤与排序 → 对过滤结果分页 → 客户端渲染单页。分类按钮和搜索框不是前端对已加载一页的二次筛选。
Mutation journal 数据合同
{
  "transaction_id": "mtx_...",
  "session_id": "...",
  "workspace_id": "workspace_...",
  "workspace_sequence": 184,
  "branch_ref": "branch_...",
  "lineage_head_id": "...",
  "producer_turn_id": "actual assistant message id",
  "origin_turn_id": "user-visible parent turn id",
  "actor_id": "main | child_...",
  "job_id": null,
  "worktree_id": null,
  "kind": "edit | revert | rewind",
  "status": "prepared | applied | committed | aborted | rolled_back | recovery_required",
  "files": [{
    "file_lineage_id": "file_...",
    "path": "canonical absolute path",
    "operation": "create | modify | delete | rename",
    "old_path": null,
    "before": {"kind":"regular","digest":"sha256:...","blob_ref":"blob_...","mode":"0644"},
    "after":  {"kind":"absent"},
    "stats": {"added":16,"removed":4,"binary":false},
    "diff_state": "available | large | binary | timeout",
    "recoverability": "exact | unavailable",
    "unavailable_reason": null
  }]
}

不变量

  • 原始写入先持久化 prepared receipt,再写文件,确认 after state 后转 committed;prepared 持久化失败时 trusted mutator 必须在写盘前失败。
  • {kind:"absent"} 只表示已精确确认路径不存在;baseline 获取失败只能由 recoverability=unavailable 和 reason 表达,永远不能编码成 absent。
  • recoverability=unavailable 只用于 journal 已成功持久化、但因明确大小或文件类型策略不保存 recovery blob 的 mutation,不用于吞掉 journal 故障。
  • 每个 user prompt 定义 before_turn;assistant 完成后定义 after_turn。UI 必须写清恢复哪一个边界。
  • 同一 turn 多次修改同一 file lineage,摘要折叠为 first-before 到 last-after 的净变化;rename 后仍保持 lineage。
  • 所有共享 checkout 的 transaction 在 workspace lock 下领取全局单调 workspace_sequence;多轮投影按 sequence 和 lineage,不按 DAG seq/DFS。
  • before/after regular state 都保存 blob ref,才能稳定显示历史 diff、恢复和条件式 Reapply。
  • 路径在 capture/plan/apply 时都重新规范化;保存并复检父目录链 identity、leaf lstat、device/inode 和 hardlink count,使用已验证 directory handle 或等价 no-follow 原语。
  • Current branch 只折叠 active lineage 的 transaction,不混入 sibling branch。
  • Revert/Restore/Reapply 本身也写 mutation transaction,原记录保持不可变。

Checkpoint 与 WorkspaceRevision

对象必需字段用途
分支稳定 branch_id、parent branch、fork checkpoint、HEAD、head_version、writer epoch;session 另存 active_branch_id。source branch HEAD 永不后移。Restore/Branch 确认时立即创建新 branch ref;纯历史浏览只改变 navigation cursor。
Checkpointcheckpoint_id、boundary=before_turn|after_turn、user/assistant node、branch id、journal sequence、workspace revision。定义恢复到哪里;不重复保存一套文件列表。
ChangeSetproducer turn、origin turn、branch、actor/job/worktree、transaction sequence、净 file lineage 变化。Turn card 通过 origin 分组,但按 change set id 去重并保留真实生产者。
WorkspaceRevisionrevision id、受管路径投影 digest、对应 branch/checkpoint、alignment 状态。检查 branch checkout、conversation-only restore 和实际 workspace 是否一致。
RestorePlanplan hash、idempotency key、expected HEAD/revision、目标 checkpoint、文件 actions、冲突。预览与确认之间防止 TOCTOU;重复请求不得执行两次。

RestoreIntent / RestoreAction

{
  "restore_intent_id": "restore_...",
  "idempotency_key": "...",
  "plan_hash": "sha256:...",
  "source_branch_id": "branch_source",
  "target_branch_id": "branch_target",
  "expected_head_version": 42,
  "expected_workspace_revision": 184,
  "target_checkpoint_id": "cp_...",
  "mode": "code_and_conversation",
  "status": "prepared | applying | committed | aborted | rolled_back | recovery_required",
  "actions": [{
    "action_id": "ra_...",
    "file_lineage_id": "file_...",
    "path": "/canonical/path",
    "expected_current_digest": "sha256:...",
    "target_digest": "sha256:...",
    "target_blob_ref": "blob_...",
    "rollback_digest": "sha256:...",
    "rollback_blob_ref": "blob_...",
    "applied_digest": null,
    "state": "pending | applied | verified | rolled_back",
    "error": null
  }]
}

恢复记录不变量

  • Plan 是只读预览;Intent 是确认后的持久执行记录,两者由 plan hash 绑定。
  • 每个 action 在文件替换前后分别持久化状态;重启不通过目录内容猜测执行位置。
  • Rollback 只在 current digest 仍等于该 action 的 applied digest 时写回 rollback blob。
  • 任何 action 无法安全 rollback 时,intent 保留每个路径的真实状态并进入 recovery_required。
  • target branch 只在所有代码 action verified 后激活;source branch ref/head 始终不变。

三个 Review scope

范围事实源包含恢复能力
本轮指定 origin turn 的 committed change sets父 turn 直接 change set + owned child change sets;child 始终保留独立 producer_turn_id,按 transaction id 去重并显示 actor。所选 causal closure 全部 receipt exact、所有 actor terminal 且 current digest 匹配时可 Undo/Revert。
当前分支当前 active lineage 的增量 mutation projection所有 turn、显式 revert/rewind/reapply;不包含 sibling branch 和外部写入。从具体 turn/checkpoint 发起,不提供无范围的一键 branch Undo。
工作区Git 跟踪差异 + git ls-files --others --exclude-standard当前未提交变化;遵循 .gitignore。内部再切换 Unstaged、Staged、Branch 或 Commit。无 turn Undo。Git Discard 与 checkpoint Restore 使用不同入口和确认文案;非 Git明确 unavailable。
多轮 Rewind:一次规划,一次事务

每轮同时有 before_turn 与 after_turn checkpoint。User message 的 Restore 入口默认选择“恢复到本次请求之前”;assistant turn card 可选择“恢复到本次回复之后”。目标 suffix 只沿 source branch predecessor chain 计算,不碰 sibling branch。Source branch ref 和 HEAD 始终保留;conversation 模式立即创建新的 target branch ref,并在协调事务提交后切换 active branch。

IDLE

选择 checkpoint 和恢复模式。

PLANNING

冻结 expected HEAD、workspace version 与 suffix。

READY

展示 turn/file 影响、不可恢复项和 branch 结果。

BLOCKED

冲突、缺 blob、运行中任务或不安全路径;零写入。

APPLYING

写 durable intent,锁 workspace,stage、apply、verify。

COMMITTED

追加 transaction;需要时移动 HEAD;刷新 UI。

多文件恢复不是单个文件系统原子操作。目标保证来自 durable intent、rollback staging、逐文件原子替换和重启恢复;若 apply 与 rollback 都失败,状态必须是 Recovery required,不能显示 Reverted 或移动 conversation HEAD。

规划算法

阶段规则失败结果
解析分支沿袭关系从当前 HEAD 沿 conversation predecessor 回到目标 user checkpoint;caller subtree 只按明确 ownership 纳入。目标不在 active lineage:拒绝,提示先切换分支。
合并目标状态按 journal 投影 checkpoint 时每个路径的目标状态;同文件跨多轮只生成一个最终 restore action,不逐轮覆盖。journal 不连续或历史 receipt 不精确:代码模式 unavailable,对话模式仍可选。
预检从全局 current_workspace_revision 规划到 target checkpoint,只比较实际 plan actions 涉及的 file lineage;检查 blob、父目录/leaf identity、file type、root、空间和权限。任一失败进入 BLOCKED,列出每个路径,零文件改变。conversation/workspace mismatch 本身不是 source digest。
准备意图保存 plan id、expected branch/head version、workspace revision、before images、目标 images、writer epoch 和恢复模式;请求幂等。确认前状态变化返回 stale-plan,重新预览。
应用文件获取 workspace mutation lock;每个 action 持久化 pending/applied/verified/rolled_back 和本 transaction applied digest;逐文件原子替换,删除仅在 current digest 匹配时执行。回滚前再次确认 current digest 仍等于本 transaction applied digest;外部 actor 已改写时不覆盖,进入 RECOVERY_REQUIRED。
创建对话分支conversation-only 或 code+conversation 先准备新的稳定 target branch id/ref,source branch HEAD 不变;首轮前目标统一为持久 synthetic ROOT,禁止 head_id=None fallback。创建/激活使用 expected source head_version CAS;失败则按 intent 恢复文件并保留 source/active branch。
完成追加 rewind transaction 和 navigation event;不把旧节点全局写成 rewound。提升 branch writer epoch,使旧异步任务无法回写当前 branch。重启时扫描未终态 intent,完成或回滚,不猜测成功。

恢复模式

模式文件对话 HEAD后续行为
代码 + 对话 默认恢复到 checkpoint立即创建 target branch,HEAD 指向目标 user prompt 之前;提交后激活原 prompt 回填;source branch ref/head 保留。
仅对话保持当前立即创建并激活 target branch显示 workspace mismatch。用户确认 Keep current files 后追加 adopt_workspace_revision event 和新的 branch checkpoint;之后从该明确基线继续。
仅代码恢复到 checkpoint保持当前追加 rewind transaction;显示“代码已回退、对话仍在最新位置”。
分支、Checkout 与 sub-agent
场景目标语义文件规则
从助手结果创建分支立即创建稳定 target branch id/ref,HEAD 指向该 assistant,并切换 active_branch_id;source branch HEAD 保持原位置。默认不修改文件,按钮副标题明确“Files stay as they are”。纯浏览历史只移动 navigation cursor,不创建/移动 branch。
分支为新任务创建 source-preserving 新 task/thread,原 task 和 HEAD 不变;可选择复制 conversation only 或携带 checkpoint 文件状态。Git 项目中“with files”优先创建隔离 worktree 后物化 checkpoint;非 Git 不提供无提示目录复制,改用同 task 的显式 Code + conversation Restore。
切换同级分支切换当前可见与模型使用的 conversation lineage。计算 branch/workspace alignment。浏览允许;开始文件修改前必须选择保持当前 workspace 或恢复该 branch 的代码投影。
Owned child(前台或后台)判据是 relation + creates_agent + origin_turn_id,不是前台/后台。child 始终有独立 producer turn/change set,父 turn 只按 origin 分组。运行中时阻止父 restore;完成后进入父级 owned causal closure,plan 逐个列出并按 transaction id 去重,不能靠 caller DFS 猜测。
独立执行者无 owned relation 的 background terminal、job runner、channel 和 scheduler 注册独立 workspace writer identity。运行中时阻止同 workspace restore;完成回写必须校验 branch writer epoch,旧任务不能在 restore 后重新写入当前 branch。
已有对端 / 跨会话调度agent(to=existing)、send message 和既有 peer 是 linked collaboration,不是父 turn 独占后代。父 restore 默认不修改 peer 的对话或 change set;impact sheet 单独列出 linked actor,重叠 workspace/path 时阻止 code restore。
Worktree 子任务文件状态属于独立 worktree。父 workspace 的 Undo/Rewind 不触碰;merge/discard 使用 worktree 自己的事务和冲突语义。
Worktree 合并merge 产生独立 mutation transaction,归属于执行 merge 的 producer turn。父 workspace 只从 merge transaction 恢复;不依赖可能已删除的 child worktree checkpoint。
同级分支Rewind 只作用于 active lineage suffix。不改变 sibling journal;切回 sibling 时重新计算 alignment。
Branch、Fork 与 Restore 不共用含糊按钮。同 task 的 Branch 是对话导航,默认不碰文件;Fork 创建 source-preserving 新 task;Restore 是显式历史恢复。需要在当前 task 从历史代码继续时使用 Code + conversation Restore;需要两套同时可运行的代码状态时使用 Git worktree-backed Fork。

Resume、Archive 与 Purge 不变量

操作合同禁止
继续会话未知 session 返回 not-found;先恢复所有 prepared/applied/recovery-required transaction,再加载真实 node ids、active_branch_id、branch HEAD/version 和 workspace revision。不能把未知 ID 当新 session;不能生成 loaded-<index> 伪 ID。
继续空分支首轮前 HEAD 指向持久 synthetic ROOT;Web/TUI/Rich CLI 使用同一 branch result schema。不能用 persisted_head or tip 或 head_id=None 自动选择其他 tip。
归档分支默认删除操作只 archive branch ref,保留 nodes、journal、checkpoint refs 和重新激活能力。不能删除共享祖先或把 predecessor 留成意外新 tip。
清除分支显式高级操作;仅释放没有其他 branch、checkpoint、operation、audit 或 active intent 引用的独有对象,使用引用计数 GC。不能按 leaf 向后删一个节点,也不能让 blob GC 绕过引用。
冲突、不可恢复与并发状态
后来修改了同一文件

Revert historical turn 不尝试自动反向合并;Rewind 预检 current digest。任何不匹配都阻止整次文件操作。

BLOCKED_CONFLICT · 0 次写入
Checkpoint blob 已 GC

summary 和 diff metadata 仍可 Review;Code restore 选项 disabled,Conversation only 保持可用。

UNAVAILABLE_BLOB_EXPIRED
大文件无 recovery blob

operation、path、size 和 recoverability 必须精确;只有工具 delta 或预算内 before/after 可得时行数才精确,否则 added/removed 显示 unknown。不可 Undo,也不能把整文件算成新增。

UNAVAILABLE_SIZE_POLICY
symlink / hardlink / 特殊文件

不跟随、不覆盖;显示路径和原因,要求用户通过原工具或版本控制处理。

UNSAFE_FILE_TYPE
运行中的 turn / background task

同 workspace mutation lock 未释放时不生成可确认 plan;用户先停止或等待任务。

WORKSPACE_BUSY
确认后状态又变化

apply 校验 expected HEAD、workspace version 和 plan token;返回 stale-plan 并刷新影响,不执行旧 plan。

STALE_PLAN · 0 次写入
应用中进程崩溃

启动时读取 durable intent 和每个路径状态;能安全回滚则 ROLLED_BACK,外部改写导致回滚会覆盖新内容时保留现场并进入人工恢复。

COMMITTED | ROLLED_BACK | RECOVERY_REQUIRED
非 Git workspace

This turn 与 Current branch 精确 journal 可用;Workspace scope 显示 unavailable,不进行目录扫描。

WORKSPACE_REVIEW_UNAVAILABLE
ignored 后台日志增长

既没有 mutation receipt,也被 Git exclude-standard 排除,不出现在 turn card 或默认 Workspace Review。

EXCLUDED_BY_DESIGN
精确编辑 gitignored / repo 外允许路径

Trusted mutator 的 receipt 仍进入 journal,可 Undo/Restore;它只是不出现在 Git Workspace scope。普通 Bash 或无 receipt 的 ignored 变化仍排除。

JOURNALED_NOT_GIT_VISIBLE
Reapply 已撤回 change set

仅当 current digest 等于 revert 后状态、没有后续同 file lineage mutation、after blobs 仍存在时可用;执行后追加新的 transaction。

READY | BLOCKED_DEPENDENCY
外部副作用

数据库、API、部署、包安装、Git index/commit、运行进程、网络请求和未记录 Bash 不在文件 Restore 范围内;确认页逐项提示可能重复。

UNSUPPORTED_SIDE_EFFECTS_VISIBLE

UI 信息架构与操作入口

位置显示操作禁止
助手轮次卡片精确文件数、净增删、前三个文件;完整外框和约 40px header。左侧使用用户指定的 19px FeatherIcon 表示本轮包含直接文件编辑,不使用网站 logo。总增删数字始终显示 additions 与 deletions 两项,包括零值;其下以 2.5px 双色比例条编码两者的真实占比。操作组、按钮和 Undo 图标不参与 flex 收缩,方向图标使用 1em 与按钮文字等高,标题区域承担截断;≤420px 时标题缩写为 “N files”,FeatherIcon、统计和操作保持可见,header 固定 40px。header 与文件列表之间保留一条分界线;目录弱、basename 强,统计固定列宽,分类只在 Review 中出现。最新可恢复 turn:Undo;成功 Undo 后且重新预检可用:Redo;历史 turn:Revert;历史 Revert 后且重新预检可用:Reapply;所有 turn:Review。Undo / Revert / Redo / Reapply 使用文字加方向图标,Review 使用中性色描边按钮。header 只显示当前可执行动作,unavailable、blocked 与 Reverted 状态只在 footer 说明。Redo 与 Reapply 都写新的 reapply transaction,不维护独立线性栈;不显示 header chips、禁用状态标签或参考产品品牌元素。
用户消息页脚现有消息动作中的 Restore checkpoint 入口。打开 checkpoint impact sheet,明确 before_turn/after_turn,默认 Code + conversation。不在点击后立即恢复;必须先显示影响、可恢复性和外部副作用。
助手消息页脚Branch 动作。Branch from here,副标题 Files stay as they are。不暗中恢复 checkpoint。
中心变更标签页This turn / Current branch / Workspace;Workspace 内含 Unstaged / Staged / Branch / Commit;左文件 rail、右单文件 diff;来源标签始终可见。搜索与分类显示完整过滤结果的总数,页码只表示该结果集。Unified / Side-by-side、行级评论、Open file、Reveal。改变 scope、搜索、分类或排序时清空 cursor、selection 和 diff;File 使用现有虚拟化 editor tab,不在 Review 内复制整文件。Workspace scope 不显示 turn Undo;一次只挂载一个有界 diff;不能在客户端只过滤已加载的一页。
历史影响面板目标 prompt、撤回 turn 数、文件数、branch 结果、恢复模式、冲突和 unavailable 原因。确认 Rewind、Conversation only、Code only;取消无副作用。blocked 时无 Force 按钮;高级手动恢复从 Review 处理。
对齐提示条Conversation branch 与 workspace projection 不一致的原因。Keep current files 或 Restore branch code。不能只显示警告后让 mutating turn 静默开始。
性能、保留、安全与兼容
轮次收尾

复杂度只与 committed changed paths 有关;不遍历 workspace。摘要在 finalize 持久化并随 transcript 返回。

审查加载

服务端先筛选和稳定排序,文件列表每页 100;客户端只保留当前页和相邻页。选中文件后每批最多 200 行或 256 KiB,并支持继续加载。

差异预算

计算超预算返回 timeout metadata;不阻塞 Agent 完成,也不回退到 before 与当前磁盘的跨轮近似 diff。

快照分页

目录、项目搜索和 Review 的分类、搜索、排序与 opaque cursor 都绑定同一 snapshot;workspace 或项目变化后旧页返回 stale 并整体刷新,不能混页。

请求身份

每个文件 WS 请求有 UUID request_id;切文件或切项目取消旧请求。迟到响应还必须匹配 owner、scope、snapshot revision、change set 与 blob pair。

大型恢复计划

上千文件预检作为可观察后台任务,冲突结果分页;进入 APPLYING 后不可取消,只能完成或事务回滚。

恢复 blob

使用独立内容寻址存储,按 digest 去重,权限限于本地用户;不进入 session Git。默认保留最近 100 个 checkpoint 和每个 file lineage 的首个 baseline。

回收状态可见性

Pinned、活动 task、未解决冲突、prepared/applying intent 和仍被 branch ref 引用的 checkpoint 不回收。其余 blob 到期后显示 Review available / Code restore unavailable。

秘密信息

blob 不进入日志、遥测或模型上下文;session 删除一并清理无引用 blob。外部路径必须有当时和恢复时的明确授权。

读取缓存与草稿

Read cache 受 64 项 / 16 MiB LRU 限制;dirty draft 独立持久化,受 32 项 / 8 MiB 配额保护且绝不自动淘汰。

旧版会话

旧 checkpoint 只用于只读 Review 或明确标记 unavailable;没有 digest/recovery contract 时不提供新 Undo/Rewind code 模式,也不保留无 request_id 的兼容入口。

TUI 一致性

/rewind 先展示同一 server plan,再选择模式并确认;不能继续直接调用旧 rewind_to。

App/Web 一致性

同一 plan/apply 协议和幂等 request id;UI 只渲染 server 返回的 canonical impact,不在客户端重算。

行内评论

绑定 change_set id、before/after blob pair、side 与 hunk/line;scope、branch 或 restore 变化后标 stale,不能发送到另一版本。

稳定模块职责与兼容移除

模块最终职责不承担的职责
apps/server/.../ws_actions/files.py项目根授权、目录 listing、project search、read 与写入类文件操作;统一校验 project/path、request_id、idempotency key 和目录/search snapshot。不计算 turn/branch Review,不保存浏览器缓存或草稿。
apps/server/.../ws_actions/turn_files.py从 mutation journal 与 Git 生成 Review scope、过滤后的分页结果和绑定 snapshot 的单文件 diff;统一回显 request_id。不提供项目文件树搜索,不让 turn diff 绕过 Review snapshot。
apps/web/lib/net/ws-request.ts创建 request_id、维护按 id 的 pending registry、超时/取消和严格响应验证。不以 response type 匹配第一个响应,不维护文件请求的全局串行队列。
apps/web/lib/files/files-shared.ts以 project-scoped key 管理有界 read cache、持久 dirty draft store 与显式失效事件。不作为组件间的无界内容仓库,不保存 Review page 或 socket listener。
FileTree / FilesPage渲染目录、搜索和文件操作意图;仅消费服务端分页与 project search 结果。不扫描本地已加载节点来代表项目搜索,不自行重排跨页结果。
ReviewTabPane保存当前 scope/filter/snapshot/cursor/selection,渲染服务器确认的单页与单文件 diff。不对当前页二次过滤来实现 category/search,不复用另一 scope 的 diff。
FileTabPane编辑器 buffer、保存冲突提示和 dirty-draft 生命周期;从项目文件读取 canonical 内容。不直接调用旧 turn diff 入口;历史文件比较统一由 Review tab 打开。
最终移除临时兼容入口:删除按 response type 配对的 filesWsRequest 全局队列、缺少 request_id 的文件 action、FileTabPane 直接调用的 turn_file_diff 入口,以及把 list_turn_files 当作新消息摘要回填的路径。旧 session 没有可用的 journal/review snapshot 时返回只读 unavailable;不为旧入口保留会绕过新合同的 fallback。
实施 brief 与验收矩阵

A–J 已完成并通过独立 specification review 与 quality review。每个新增任务实现后也必须通过相同审查,才能更新本页状态。

任务生产边界必须先失败的 public-entry 场景排除状态与证据
A · 精确修改日志programs/tools/files/、turn context/finalize、checkpoint manifest/store。已有 >5 MiB 文件首轮修改不算全新增;Bash ignored log 不进入 turn;失败 edit 无 receipt。不实现 Review UI,不改用户 Git。审查通过 public-entry、受影响测试与静态检查均已验证。
B · 安全单轮撤销/还原agent/internals/_revert.py、workspace lock、durable intent。后续同文件修改时零写入;创建文件 digest 不符时不删除;中途 I/O 失败不部分标记。不实现 multi-turn HEAD move。审查通过 public-entry、受影响测试与静态检查均已验证。
C · 多轮规划/应用agent/_rewind.py、session head API、intent recovery、WS/CLI protocol。同文件跨三轮恢复到目标;file failure 不移动 HEAD;sibling branch 不受影响;stale plan 零写入。不重写 compaction 或 DAG schema。审查通过 public-entry、受影响测试与静态检查均已验证。
D · 审查范围与界面ws_actions/turn_files.py、message metadata、center tab/store、chat card。历史 transcript 不逐条请求;Workspace ignored 排除;一次只挂载一个有界 diff;三 scope 来源一致。不加第三 pane、新窗口或参考产品品牌。审查通过 public-entry、受影响测试、TypeScript 与 UI gate 均已验证。
E · 分支对齐与多 agent 归属checkout/branch UI、active-lineage fold、owned/linked/worktree ownership。conversation-only checkout 后 mutating turn 不静默开始;owned background child 运行时阻止父 restore、完成后按 origin 进入 causal closure;linked peer/cross-session 不被父 restore;worktree child 不改父 workspace。不实现通用 workspace cloning。审查通过 public-entry、受影响测试、TypeScript、ruff 与 WS action gate 均已验证。
F · 项目查询快照ws_actions/files.py 的目录分页、project search、路径授权与 snapshot registry;FileTree 的结果状态。未展开目录中的命名文件能被搜索;第一页后修改目录不会让同一 cursor 混入新项;cross-project cursor 被拒绝。不更改视觉布局、不引入全文内容索引或第三方搜索服务。审查通过 目录与搜索使用 stable cursor、同一 snapshot 的增量分页和有界结果。
G · 文件请求身份文件类 WS dispatch、ws-request.ts、durable idempotency record 与所有文件/Review 调用者。两个同 action 请求可乱序返回且分别更新正确调用者;缺失 request_id 被拒绝;相同 idempotency_key 的 in-flight retry 绑定原 operation,完成后重放结果;相同 key 而 fingerprint 不同则冲突且零写入。不改变非文件 WS action 的协议,不把 request_id 当作写入幂等键。审查通过 request identity、durable mutation、断线重试、worker lease 与有界 pending registry 已验证。
H · 有界缓存与持久草稿files-shared.ts、原生 IndexedDB draft store、FileViewer、FileTabPane、tab close/rename/delete 生命周期;project unlink/delete cleanup hook 保留到产品提供该显式操作时接入。超过 read-cache 限额后只淘汰干净 LRU read;刷新、tab 切换和项目切换后 IndexedDB dirty draft 仍存在;quota/浏览器 QuotaExceededError 时旧 draft 与 aggregate index 原子保留,满额阻止新 dirty 并显示提示。当前没有 project unlink/delete action,不从 list_projects 消失推断用户授权。不引入协作编辑、远端草稿同步或无限离线文件副本;不新增 project remove UI/action。审查通过 64 项 / 16 MiB read cache、32 项 / 8 MiB durable draft store、生命周期补偿与恢复合同已验证。
I · 筛选后审查分页turn_files.py 的 filter/sort/snapshot/page,以及 ReviewTabPane 的 query state。分类结果跨页完整;改变 category/query/sort 后旧 cursor 与 selected diff 失效;Workspace snapshot 固定 staged/unstaged/untracked candidate list 及每文件 blob pair,随后 index/worktree 任一变化返回 stale。不增加第三 Review pane,不改变 mutation journal 或 Git 的事实源。审查通过 服务端先筛选后分页,Review cursor 绑定冻结 snapshot 并检测 stale。
J · 规范入口切换文件模块调用图、旧 adapter 删除、legacy-session unavailable 呈现。没有 filesWsRequest 全局队列、无 request_id 文件 action 或直接 turn_file_diff 的 UI 调用;旧 session 不会走 bypass fallback。不为旧入口保持隐藏兼容开关,不删除可验证的只读历史元数据。审查通过 canonical request path、旧 action/fallback、临时 registry 已移除;服务端与前端按稳定职责完成无环拆分。
K · 轮次卡片空状态与失败状态assistant-bubble.tsx、message-rail.tsx、turn-files-chips.tsx 与卡片 CSS。普通文字回复不挂载卡片或 Review;旧文件写入轮次按需查询,空结果隐藏;查询失败只显示可重试的紧凑状态。不改变 mutation journal、Review scope、diff 或恢复协议。审查通过 empty/error/retry、stale response、rail round-trip、TypeScript、Web 单测、静态检查、生产构建与文档 gate 均已验证。

完整可见验收

目录与搜索分页

搜索命中一个未展开深层目录中的文件;并发 create/rename 后继续旧 cursor 必须返回 stale,刷新后结果按项目内稳定顺序重新开始。

要求:完整项目范围
全部文件请求 ID

目录 read、file read、write、rename、turn summary、Review list 和 Review diff 同时发出并乱序返回。每个 response 只能被匹配的 pending request 接受;同 idempotency key 的 write retry 只关联同一 operation 并重放完成结果。

要求:无按类型匹配或重复写入
资源压力下的未保存草稿

填满 read cache 与 IndexedDB draft quota 后刷新页面、切换 tab 和项目。已有 dirty draft 可恢复并保留原 baseline;新 draft 或扩大 draft 在无空间时不提交 transaction,并显示可见处理提示。

要求:不得静默丢失草稿
仅对话

立即创建并激活稳定 target branch,source branch ref/head 不变;文件保持当前,alignment banner 出现,下一次文件修改前要求决策。

通过:不匹配可见
仅代码

HEAD 不动,追加 rewind transaction,Current branch Review 反映新状态。

通过:历史保留
从此处分支

确认时 target branch ref 立即存在并激活,source branch HEAD 不变;文件保持当前。下一条消息只是延长已创建的 target branch。

通过:来源保留
重试/编辑同级分支

新分支绑定明确 before/after checkpoint;保持当前文件或恢复目标文件由用户选择,不从旧运行结果静默继续。

通过:检查点明确
还原与重新应用

历史 Revert 仅在无后续同 lineage 依赖时成功;Reapply 再次预检并写新 transaction。

通过:无重做捷径
筛选后的审查分页

超过一页的 Code、Tests、Docs 和 Large 结果分别先在服务端过滤;切换分类、query 或排序后旧页和已选 diff 均不再显示。Workspace 创建 snapshot 后修改 index、worktree 内容或候选列表,后续页和 diff 均返回 stale。

要求:先筛选后分页,精确匹配工作区版本对
并发写入者

OpenProgram background task、其他 session 或外部进程改变文件时计划失效或 apply 后校验回滚。

通过:零覆盖
崩溃恢复

在每个 intent phase 强制终止并重启,最终必须是 COMMITTED、ROLLED_BACK 或持久化到具体路径的 RECOVERY_REQUIRED;永不假报 committed,也不覆盖外部新写入。

通过:每条路径可解释
规范入口切换

从用户可见文件入口检查调用图:没有临时 queue、缺 request_id action 或 direct turn diff fallback;无法按新合同解释的旧 session 显示只读 unavailable。

要求:无兼容路径绕过

可选 Office 安装已实现并通过独立规格与质量审查。最终受影响配置、适配器、安全与仓库契约范围内1812项测试通过(82项可选依赖跳过,1项预期失败)。全部22项原生 Office/浏览器测试与710项 Web 测试通过;Web 构建、TypeScript、静态检查、桌面检查和文档链接通过。显式同意浏览器用例验证取消不安装、失败重试与自动打开文档;组件测试验证不可变发布、origin 拒绝和并发请求去重。托管 HTTP 客户端真实访问固定来源成功,未下载归档正文。

实现状态

连续 PDF 阅读器、文本选择、剪贴板规范化、大纲与缩略图导航、高亮和自由文本批注已实现。公开浏览器测试在原生与桌面兼容环境中验证渲染、复制、批注序列化、撤销/重做与保存失败后的草稿保留。独立规格与质量审查通过。公开回归还验证恢复输入限制、极端纵横比缩略图有界性与清除搜索高亮。完整源码验证清单通过,包括真实浏览器测试、Web 测试、契约、文件组件测试、构建、类型、静态资源与文档检查。已安装 App 验收与源码验证分别记录。

PDF 运行时兼容性使用匹配的上游 legacy 模块,并在真实应用策略下允许本地 blob 字节读取。公开 FileViewer 测试在原生和缺少 API 的环境中验证渲染、导航、缩放、搜索、关闭/重开、无效输入和外部请求拒绝。独立规格与质量审查、完整 Web 与浏览器测试集、仓库契约、受影响认证/前端组件、类型检查、生产构建、资源预算和文档链接通过。报告中的研究 PDF 在缺少桌面 API 的生产策略下可渲染和搜索,完整文档也能在已安装 Electron 运行时解码。

项目人工编辑的二进制发布与历史接口已完成独立规范审查、质量审查和完整后台测试。现有文本写入也使用共享恢复事务;每次写入立即发布,历史按编辑时段分组,恢复新增版本。项目移位后按当前位置恢复,离线时仍能读取已保存版本;失败与损坏记录明确显示未确认状态。

统一预览窗口、文本编辑和后台自动保存控制器已完成源码实现、独立规范与质量审查,以及完整后台、Web、浏览器与文档检查。草稿覆盖未打开的文件,失败不会关闭文件标签;重命名期间禁用相关编辑,成功后按新路径重新打开。人工和模型历史已汇总到同一文件 History,可以预览与恢复。Office 的 DOCX/PPTX/XLSX 已完成真实内容修改、导出与重新打开验证;旧 DOC/PPT/XLS 需要另存 OOXML,ODF 格式已验证原格式导出。保存失败后立即重试,以及关闭前等待保存期间新增内容完成导出,也已在本地引擎中验证。安装后通过默认 App 验证资源与界面,运行状态保存在本地发布记录。

PDF 分页、缩放与搜索,PSD 合成图与图层列表、TIFF 和普通图片预览,以及本地音视频播放已完成源码实现、独立审查和完整验证。预览使用本地固定版本资源,损坏或超限文件显示错误和下载入口;PDF、PSD、TIFF、音频和视频保持只读。

本地 Office 资源的清单校验、独立静态来源和受认证的可用性接口已完成独立审查与完整验证。仅接受固定来源与版本的本地资源,远端来源不可用;编辑器资源不能访问主应用 API。实际 Word、PPT、表格的编辑、导出、预览切换、原生撤销与重开已在研究引擎中验证,保存失败重试及最终导出也已验证。Office 资源独立安装到共享本地缓存;默认 App 不携带资源,安装完成后当前 worker 直接使用已验证版本。字体仅采用附有许可证的输入,资源包保留源码、补丁和来源记录。统一窗口的 Office 预览与编辑接入已完成独立规范、质量审查和完整检查(实现 ef64e6ab):后台 8746 项、Web 单元 672 项、真实 Office 浏览器 16 项和其他预览浏览器 20 项通过,文档 542 页构建通过且无死链。编辑模式等待原生状态确认,原生撤销随标签和历史切换保留,关闭提交尚未完成的输入;旧格式明确转换到新文件。人工/模型历史已完成汇总,

静态 PNG/JPEG/WebP 编辑已完成独立规范、质量审查和完整验证(实现 8dc8bf81)。裁剪、旋转、绘图、形状、文字与原生撤销/重做通过实际导出像素验证;编辑器跨预览、历史、标签和页面切换保留,错误后可重试,转换 PNG 创建独立文件且拒绝覆盖。后台 8746 项、Web 单元 678 项、文件浏览器 30 项和真实 Office 浏览器 16 项通过,文档 542 页构建通过且无死链。首次后台全量运行出现一项并发额度测试超时,未改代码的完整重跑通过。动画与 16 位 PNG 保持只读;限制 64 MiB、1600 万像素和单边 16384 像素。导出不承诺保留嵌入元数据,PSD 仍为合成图和图层预览。

人工和模型文件历史汇总已完成独立规范、质量审查及完整验证(实现 fcf799bd):后台 8767 项、Web 单元 678 项、文件浏览器 32 项、真实 Office 浏览器 16 项通过,文档 542 页构建通过且无死链。首次后台运行的一项取消重试测试超时,候选与任务基线单独复现均通过,未改代码的完整重跑通过。模型版本复用所属会话保留的不可变字节;归档保持可读,彻底删除后不再可读。旧历史有界分批补录,无法核实的归属明确显示不可用。恢复仅修改所选文件并创建新记录;项目移动保持稳定归属,离线只读。主分支整合已通过独立审查和完整组合验证。

最终整合实现 f0e67531 包含当前主分支修复,独立规格与质量复核通过。完整组合验证通过后台 8862 项、Web 单元 678 项、文件窗口浏览器 32 项、真实 Office 浏览器 16 项及 CLI 190 项;Desktop、类型、构建、静态资源体积与 546 页文档检查通过,无死链。前一轮发生自更新测试执行进程退出及替补进程状态复用,聚焦与基线检查通过;保留失败记录,最终完整运行未复现。默认 App 安装与重启验收使用同一整合源码和已验证 Office 资源包,记录与源码检查分开保存。

文件历史持久性已验证:不可变版本、失败重试、损坏记录拒绝、未完成写入投影与旧版本兼容。新增本地生成器继续复用 source_path 发布入口;Office 语义差异和远端条件存储不属于当前实现。

文档 source_path 发布与二进制读取已实现并通过独立审查和测试:完整文件版本随会话持久保存,支持撤回、重新应用及冲突检测;不提供 Office 内容差异视图。

当前实现状态:目录/搜索 snapshot、文件 request identity、durable mutation、有界 read cache、持久 dirty draft、Review 服务端分页、canonical entry-point cutover 与稳定模块边界均已完成独立审查。

实现证据写入对应测试;本设计页只维护当前合同与总体状态。

跨平台快照一致性

普通文件快照比较读取前后的描述符元数据,以及打开前与读取后的路径元数据。描述符和路径身份的设备与 inode 必须一致。不同操作系统 API 的元数据不能假定具有相同时间戳或权限表示后直接比较。任一观察变化都中止发布;存储权限取自路径观察。在 Windows 上,旧格式迁移先以可写句柄打开暂存文件再刷盘,直到发布成功前始终保留源文件。