Skip to content

feat(workspace): add transactional checkpoints, rewind, and fork - #111

Merged
Qiyuanqiii merged 1 commit into
mainfrom
codex/issue-101-workspace-checkpoints
Aug 19, 2026
Merged

Qiyuanqiii merged 1 commit into
mainfrom
codex/issue-101-workspace-checkpoints

Conversation

@Qiyuanqiii

@Qiyuanqiii Qiyuanqiii commented Aug 19, 2026 •

Copy link
Copy Markdown
Member

摘要

  • 新增严格版本化的 workspace-checkpoint.v1,将精确 Workspace/root identity、base commit、branch、原始 Git index、稳定 manifest、内容 SHA-256、触发 receipt、attempt、capability generation 与恢复等级绑定为不可变检查点。
  • 为 FileEdit、模型工作区 apply/delete、Run-owned 前台命令批次、后台 Job、typed Git mutation 与未来 agent merge writer 建立统一 before/after 事务边界;失败、拒绝、重放与崩溃后的 partial state 均有可审计终态。
  • 新增三方 Preview、Undo、Redo、Rewind 与独立 Fork。恢复使用精确 cursor CAS、逐路径/原始 index 冲突检测、root-confined 原子写入和 Git index.lock,遇到外部修改、root/commit/branch/case/link/index 漂移时 fail closed。
  • 新增 schema v117 的内容寻址 blob、sealed manifest、引用计数、硬配额、GC、mutation transaction 与 Run cursor;启动 reconciliation 覆盖 boundary、restore、terminal cursor commit 和 Fork 注册前后崩溃窗口。
  • CLI、认证 HTTP/OpenAPI 与 Desktop 增加等价的时间线、手工捕获、预览、确认恢复和 Fork 入口;同步 ADR 0118、架构、使用指南、API、测试矩阵、README 与项目恢复上下文。

Closes #101.

协议、恢复等级与内容存储

workspace-checkpoint.v1 以 Run/Workspace/root fingerprint 为身份边界,并保存捕获时的 Git base/branch、原始 index presence + digest + bytes、排序 manifest、内容 hash、文件模式、大小、换行类型、触发来源和 recovery reasons。

  • complete:边界内所有已知变化都有可恢复字节与完整归因。
  • partial:Workspace 内已知状态已记录,但存在明确排除或归因不完整;没有可移植 filesystem watcher 时,命令批次固定为 partial,不夸大恢复能力。
  • unavailable:root/Git identity、大小写、index、link 或必要内容不能安全物化,Restore/Fork 直接拒绝。

manifest 明确区分 stored、missing、excluded_ignored、excluded_generated、excluded_large、excluded_sensitive、excluded_link、excluded_special 与 unreadable。限额内文本和二进制均按原始字节保存;LF、CRLF、mixed 与 no-newline 可逐字节恢复。ignored、生成物、超限、疑似敏感文件、symlink/junction/reparse、特殊或根目录外内容绝不被静默描述为可恢复。

内容存储按 SHA-256 去重,schema v117 在同一 SQLite 事务内提交 blob、entry、seal 与事件;未 sealed manifest 不可读取。硬上限为:

  • 单 checkpoint 最多 20,000 entries、64 MiB 引用 blob;普通文件 4 MiB、原始 index 32 MiB;
  • 全局 blob store 2 GiB、10,000 checkpoints、2,000,000 manifest entries、20,000 mutation transactions;
  • preview 最多 2,000 changes、256 conflicts。

SQLite trigger 在并发写者下执行内容与元数据配额,重复 SHA blob 不重复计费;配额失败规范化为 RESOURCE_EXHAUSTED 并回滚候选 blob。sealed checkpoint、entry、transaction 的身份/状态不可变,refcount 与 GC 只回收无引用内容,不静默修剪不可变历史。

统一 mutation 边界与归因

每个高层 mutation 使用一个稳定 operation key 和一组 pre/post checkpoint,而不是按底层 syscall 产生碎片快照:

来源 边界 持久归因
FileEdit 与 agent-code-tools.v1 apply/delete durable apply 前;成功、拒绝、失败或 replay 后 edit/tool receipt、invocation、attempt、capability generation、execution lease
command-runtime.v2 前台批次 整个有序批次一次 command operation、Supervisor binding、前后 manifest/Git/index
后台 command Job Start 时打开;terminal read/wait/stdin/cancel/kill/reconciliation 时关闭 Job operation、owner/lease binding、终态结果
typed Git mutation stage/unstage/commit/branch mutation 前后 Git mutation receipt
agent merge 公共 BeginBoundary / CompleteBoundary 合同 merge receipt;当前不伪造尚未存在的 merge writer

自动边界要求 Run 正在运行、Session active、execution lease 精确且未过期;同一 Run 同时只能有一个 open mutation transaction。手工 Capture 在 writer 未结束时返回 CONFLICT,不会从正在写入的边界下方移动 cursor。open transaction 查询有 2,000 条 fail-closed 上限;启动 reconciliation 分批收敛,避免积压被静默遗漏。

三方 Preview 与安全恢复

Preview 每次重新捕获一个不持久化的 live observed manifest,并比较:

  1. 操作者审阅时的 current cursor checkpoint;
  2. 目标 historical checkpoint;
  3. 当前 live Workspace 与原始 Git index。

文本、二进制、create/modify/rename/delete、未跟踪文件、mode、换行和 index 均按精确 hash 比较。目标涉及的任一路径若不再等于审阅时 current side,就返回有界三方冲突而不是覆盖;root identity/path case、base commit、branch、link/reparse、unsupported content 与 index drift 同样停止操作。

确认后的 Undo/Redo/Rewind 是新的追加写,不改写旧历史。执行前重新校验 paused Code/Deliver Run、active Session、无 live execution lease、当前非 conservative permission、进程启动 capability、显式 operator、operation key 与 expected-current cursor。历史 checkpoint 中的权限、审批、凭据、lease 或进程状态不能提供当前 authority。

文件应用通过 os.Root 限制在注册根目录内,采用临时文件 + 原子 replace/remove,并在提交前后复核 root identity。Git index 通过标准 index.lock 做 presence + digest CAS,再原子 rename;能精确恢复“捕获时 index 不存在”的状态,并保留 index mode。若最终 cursor CAS 竞争失败,prepared Restore 会以 workspace_cursor_race 进入明确 failed 终态,不留下无法解释的 open transaction。

Undo、Redo、Rewind 与独立 Fork

  • Undo 只允许从当前 cursor 的 terminal mutation after 回到该边界 before。
  • Redo 只允许从 Undo 的 terminal result 回到原 mutation 的 after。
  • Rewind 可选择同一 Run 内任意可物化 checkpoint;三者都会追加新的 before/after transaction。
  • Fork 要求 checkpoint 有真实、已提交 Git base;unborn/non-Git target 返回 failed precondition。

Fork 使用 typed literal Git argv 在历史 commit 建立新 branch/worktree,校验完整 commit、精确 branch 与目标内容,再原子注册独立 Workspace、Mission、Run、Session、初始 events 与 continuity node。新 Run 从 created 开始;只继承明确的上下文/配置快照,不继承审批、凭据、permission capability、execution lease、终端、进程或网络授权,源 Run cursor 永不移动。

CLI 的 --workspace-root 是显式 operator-only 输入。HTTP/Desktop 不接受 renderer 提供的绝对主机路径;Go 从受信源 Workspace 确定性派生一个不存在的 sibling worktree,响应只投影新 Workspace/Run ID。Fork 本身还要求 Application 层 Confirm=true,不能绕过 controller 直接调用。

WAL、崩溃恢复与 reconciliation

operation digest + request fingerprint 让同意图 retry 收敛、不同意图复用 operation key 冲突;transaction prepare 先于文件写入,terminal transaction/event 在同一 DB transaction 中提交,Run cursor 使用 CAS。

启动 reconciliation 覆盖以下窗口:

  • 普通 boundary 已 prepare 但 cursor 尚未到 before:仅从 exact expected cursor CAS 前移,再捕获 observed partial result 并关闭为 interrupted;
  • boundary 已 open 且 writer 崩溃:捕获当前部分状态,记录明确 restart reason;若 execution lease 仍有效则拒绝由第二进程关闭 live writer;
  • 非 Fork transaction 已 terminal 但最终 cursor commit 丢失:仅从 exact before CAS 到 terminal after;Fork 明确排除,源 cursor 不动;
  • 显式 Restore 中断:只有相同 request 且 cursor、Workspace identity、当前 authority 与 manifest 仍一致时才可恢复;
  • Fork 已注册新 Run 但 final checkpoint 未持久化:重新捕获并校验现有独立 worktree,完成同一个 Fork;
  • Fork 已创建 worktree 但新 Run 尚未注册:prepared row 私下保留 normalized destination/branch(json:"-",不进入 timeline/event/HTTP/OpenAPI),reconciliation 校验 source/destination、完整 commit、branch、完整 manifest 与原始 index 后才让 Git 移除已注册的 orphan worktree/branch。

注册前 Fork 清理会先重捕获全部 manifest/index;崩溃后的任何用户编辑都会导致 fail closed、保留文件并让 transaction 可重试。清理失败不伪装成功,也不进行递归目录删除或按不可信路径操作。

安全边界与非目标

  • Recovery 是当前权限下的新写操作,不是历史 authority 恢复;每次都重新校验 Run/Mission/Session/Workspace/root、mode、permission、capability、lease 与操作者确认。
  • 不自动 Git commit、不改写 Git 历史、不执行 git reset --hard,也不 blanket-delete 未跟踪文件。
  • 不声称恢复 Workspace 外文件、注册表、数据库、网络服务、外部进程或故意逃逸的子进程副作用。
  • 没有 at-rest encryption 声明;疑似敏感文件直接排除,不写入 blob 数据库。
  • HTTP/Desktop Fork DTO 不包含 Workspace root、内部 Run config、continuity body 或私有 crash-cleanup 字段。
  • 所有 ID、branch、commit、operation key、路径、请求体、分页、变化/冲突数量与存储量均有界;base commit 仅接受 unborn、non-git 或小写 40/64 位 hex。

API、Desktop 与 CLI

认证 HTTP/OpenAPI 新增:

GET  /api/v1/runs/{run_id}/workspace-checkpoints
POST /api/v1/runs/{run_id}/workspace-checkpoints
POST /api/v1/runs/{run_id}/workspace-checkpoints/preview
POST /api/v1/runs/{run_id}/workspace-checkpoints/rewind
POST /api/v1/runs/{run_id}/workspace-checkpoints/undo
POST /api/v1/runs/{run_id}/workspace-checkpoints/redo
POST /api/v1/runs/{run_id}/workspace-checkpoints/fork

GET 使用 read bearer;POST 使用独立 control bearer、严格 JSON、duplicate/unknown-field 拒绝和有界 body。Rewind/Undo/Redo/Fork 要求 confirm: true,operation key 可与标准 Idempotency-Key header 绑定。生成后的 OpenAPI 为 117 paths / 130 operations / 293 schemas,TypeScript schema 已同步重建。

CLI 新增 workspace checkpoint timeline|capture|preview|rewind|undo|redo|fork,结果使用 machine-readable JSON。恢复命令要求匹配当前 permission 的 process startup flags 与 --confirm。

Desktop Run 页面新增双语“工作区检查点 / Checkpoints”面板,展示不可变时间线、来源 receipt、attempt/capability、Git identity、恢复等级/incomplete reasons、影响路径、index drift 与冲突;只有 preview 无冲突时才开放确认。Fork 在 Go 完成 worktree、新 Run 和 final checkpoint 校验后才切换 UI。

主线兼容性

本分支直接基于当前 main 1c8761a,包含 #99 的 schema v115 模型工作区工具与 #100 的 schema v116 Run-owned command runtime;本 PR 顺延为 schema v117 与 ADR 0118,不改写既有迁移历史。

  • v117 保留 v115 authority_json、v116 command-runtime records 与全部 legacy migration fixture;新增 checkpoint/blob/entry/transaction/cursor 表及 trigger。
  • FileEdit 默认构造路径内嵌 checkpoint service,CLI edit apply、模型工具、command runtime 与 typed Git 共用相同边界。
  • Workspace root fingerprint 提取到 internal/workspaceidentity,避免 checkpoint 与既有 agent-code 路径出现两套身份算法。
  • OpenAPI、Desktop bootstrap/runtime capability、事件类型、README/usage/architecture/API/迁移账本均同步更新。

验收条件对应

  • 文件工具、命令批次、Git 与 merge contract 均产生稳定 before/after checkpoint/receipt,并绑定 Run、attempt 与 capability generation。
  • 文本、二进制、create/modify/rename/delete、未跟踪、dirty/missing index、换行、mode 与 Windows exact casing 有回归测试。
  • Shell 多文件修改通过前后 manifest/Git/index 归因;缺少 watcher 与根目录外副作用明确降级为 partial。
  • Undo/Redo/Rewind 对外部文件/index/root/branch/commit 漂移做三方 fail-closed 冲突。
  • Fork 创建独立 Run/branch/worktree,只继承明确上下文,不继承过期 authority 或 live process state。
  • blob/manifest/file apply/event/Fork 注册前后故障注入与 restart reconciliation 覆盖主要 commit windows。
  • blob/metadata 配额、dedup、seal、引用计数、GC、敏感文件与 transaction quota 有测试。
  • Desktop 时间线/preview/confirm/failure explanation,CLI 与 OpenAPI 等价入口已实现并可审计。
  • 单元、集成、race、故障注入、Windows casing/POSIX link 与 Linux amd64 CGO-off 交叉编译完成;远端平台矩阵已通过。

本地验证

  • go test -count=1 -timeout 20m ./...:全仓通过;internal/store 完整 v1–v117 迁移/恢复矩阵 854.588s、internal/application 414.658s、internal/httpapi 180.525s。
  • go test -race 定向覆盖 internal/workspacecheckpoint、internal/repository、schema v117/store 与 Application checkpoint/reconciliation 路径。
  • checkpoint/repository、CLI、HTTP/OpenAPI、Store/Application 的独立回归与故障注入测试。
  • Linux amd64 / CGO-off 的 workspacecheckpoint、repository、application 测试二进制交叉编译。
  • go vet ./...、go mod verify、go mod tidy -diff。
  • correctness-focused staticcheck -checks='SA*,S1*,QF*' 覆盖全部受影响 Go 包。
  • npm run check:api,并验证 OpenAPI/TypeScript 连续生成 SHA-256 不变。
  • npm run typecheck、完整 npm test(61 files / 249 tests)、npm run build。
  • npm audit --audit-level=high:0 vulnerabilities;首次请求遇到 npm registry TLS 建连中断,立即重试成功。
  • git diff --check、私有 Fork 字段投影扫描、本机绝对路径/临时文件/凭据扫描、隔离 worktree 清洁检查。

额外 govulncheck ./... 如实报告本机 Go 1.26.5 标准库的 5 项可达已知问题(GO-2026-6218、GO-2026-6090、GO-2026-6089、GO-2026-5972、GO-2026-5026,上游修复版本为 Go 1.26.6);它们不是仓库依赖或本次代码引入,不能把该本机扫描描述为 zero finding。远端固定补丁版的扫描结果见下节。

远端 CI

  • GitHub Actions CI #364 全绿:Ubuntu Go 1.25.13 下完整测试、module verify/tidy、analyzer vectors、go vet 与 govulncheck(No vulnerabilities found);TypeScript、Rust、Windows Desktop 与 macOS Desktop 同时通过。Go control plane 18m39s,Windows 5m19s,macOS 2m11s。
  • Desktop release #25 全绿:release dependency/license boundary 与两次可复现 Portable ZIP 构建/验证通过;PR 场景 publish 按预期跳过。

审计

  • 未提交凭据、本地数据库、构建产物、临时测试文件、测试 junction 或原工作区无关修改。
  • 已审查 operation replay、cursor race、active lease fencing、open transaction 饱和、terminal cursor commit、index lock ownership、missing-index 恢复、配额并发与 dedup rollback。
  • 已审查 Fork 的 explicit confirm、committed-base 前置条件、renderer 路径隔离、私有 cleanup metadata、注册前/后 crash、外部编辑保留与 source cursor 不变。
  • README、usage、architecture、HTTP API、Desktop 测试矩阵、项目状态、独立运行手册及双语 ADR 0118 同时描述保证、失败语义与残余边界。

仍需人工证据

PR 暂保持 Draft。合并前仍建议人工确认 Desktop 时间线、三方冲突、确认按钮与 Fork 切换的 reviewer-facing 交互;实现不会把这项尚未取得的人工证据写成已完成。

@Qiyuanqiii
Qiyuanqiii marked this pull request as ready for review August 19, 2026 08:57
@Qiyuanqiii
Qiyuanqiii merged commit 495c27a into main Aug 19, 2026
8 checks passed
@Qiyuanqiii
Qiyuanqiii deleted the codex/issue-101-workspace-checkpoints branch August 19, 2026 08:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(workspace): 可逆编辑、Checkpoint/Rewind 与会话 Fork

1 participant