12 KiB
沙盒长期工作区接入(2026-10-18)
当前状态:本文记录 0.6.0 长期草稿历史范围;0.7.0 已扩展宿主 Git 导入/写回/远程。本文后部关于“宿主 Git 尚未接通/下一步”的内容是当时状态,不代表当前;请以完整 Git 接入和验收矩阵为准。长期草稿的其他限制仍有效。
交付范围
组件升级为 0.6.0 / protocol 1,新增 workspaceState: 1。同一项目、同一会话可显式选择长期草稿:连续命令保留文件与沙盒私有 Git,检查变更后再审批提交到宿主项目。默认命令仍使用每命令快照;本批没有切换用户生产配置。
这是 P2 长期工作区的已验证子集。没有新增 WorkBuddy 取证,不代表完整 P2/P3、安全中心或原版等价验收。
| 入口 | 当前行为 |
|---|---|
execute_command 不传 workspace |
沿用当前权限路由;默认权限使用快照,成功变更经审批写回 |
execute_command 显式 workspace: "snapshot" |
强制使用隔离快照,包括原本为完全访问的调用上下文 |
execute_command 显式 workspace: "persistent" |
强制使用当前会话隔离草稿;成功命令保存草稿,不自动写宿主 |
sandbox_workspace |
status、changes、commit、discard、recover;宿主根据工具上下文确定项目/会话,不接受模型指定任意归属或路径 |
window.ycode.app.sandboxWorkspace(sessionId) |
只读状态;主进程根据保存的会话推导项目根,检查受信顶层页面,拒绝未知会话 |
| 维护 CLI | 指定绝对项目根、状态根和会话;提交需要显式 --approve |
普通 read_file、write_file、edit_file、list_dir 仍作用于宿主项目。读取或修改未提交草稿必须使用 workspace: "persistent" 的命令。只读宿主文件桥仍读取绑定的宿主项目,也没有自动重定向到草稿。
使用方式
模型工具调用示例:
{"command":"echo draft-value>draft.txt","workspace":"persistent"}
{"command":"type draft.txt","workspace":"persistent"}
{"action":"changes"}
{"action":"commit","expectedRevision":"已观察到的版本 UUID"}
后两项调用 sandbox_workspace。expectedRevision 可省略;提供时版本变化会拒绝操作。status 只查看已保存状态,changes 才同步未冲突的宿主外部修改并计算待提交变更。commit 复用现有对话审批和原生 v3 宿主事务;拒绝审批会保留草稿。规划模式不能调用草稿管理工具。
私有 Git 示例:
{"command":"git add . && git commit -m draft","workspace":"persistent","runtimes":["git"]}
Git 默认由应用携带,无需用户注册。此处提交只保存当前会话的沙盒私有历史,不触发宿主写回审批,不写宿主 .git,也不代表已经提交到用户原仓库。Node/Python 仍需维护者先导入;只读依赖通过已有 dependencies 参数显式选择。
npm run sandbox:maintain -- workspace-status --workspace 'C:\absolute\project' --session SESSION_ID --state-root 'C:\absolute\userData\sandbox'
npm run sandbox:maintain -- workspace-changes --workspace 'C:\absolute\project' --session SESSION_ID --state-root 'C:\absolute\userData\sandbox'
npm run sandbox:maintain -- workspace-commit --workspace 'C:\absolute\project' --session SESSION_ID --state-root 'C:\absolute\userData\sandbox' --draft-revision REVISION_UUID --approve
npm run sandbox:maintain -- workspace-discard --workspace 'C:\absolute\project' --session SESSION_ID --state-root 'C:\absolute\userData\sandbox'
npm run sandbox:maintain -- workspace-recover --workspace 'C:\absolute\project' --session SESSION_ID --state-root 'C:\absolute\userData\sandbox'
discard 归档旧草稿和私有 Git 引用,然后从当前宿主/策略建立新基线;它不是永久删除历史的保留清理。若宿主提交结果尚未确定,必须先 recover,避免把已发生的宿主写入当作未执行。
保存、隔离与冲突
状态位于 stateRoot/workspaces/<项目与会话摘要>/。活动引用指向摘要校验的不可变版本清单,文件内容保存在 SHA-256 blob 中。blob 先写临时文件并刷新,再发布到摘要名称;版本清单发布前限制为 8 MiB。默认文件/总容量/条目上限继续有效;保留历史没有自动回收,也不是操作系统磁盘硬配额。
正常成功命令之间保留同一个实际 NTFS 工作目录身份:执行前将 worktree 移入本次私有 stage,执行结束并清理 Job/profile/映射后移回。没有每次重新复制整个项目。恢复、丢弃可以重建物理目录并产生新身份。
新增宿主专用 --seal-workspace:使用原生相对目录句柄递归检查并设置受保护 DACL,只允许宿主用户和 SYSTEM。它拒绝 AppContainer 调用、链接、多重硬链接和过深/过量目录。保留文件移回前去除旧 AppContainer 权限;blob/版本存储由宿主独占,后续同会话 Job 也不能直接读取。运行时只向本次 stage 开放当前 Job 所需访问,宿主项目 ACL 不改变。
版本绑定规范项目根、宿主根卷/文件身份、会话、策略内容指纹和草稿 revision。换根、策略变更、物理草稿被替换、摘要损坏均拒绝自动复用;失效状态不返回旧文件名。明确 discard 后才按当前策略建立新草稿。
执行与管理操作复用项目队列,持有独占草稿锁。status 走队列外的只读检查,命令运行或等待提交审批时及时返回 busy。宿主外部修改在下一次同步时做三方合并:不相关修改进入草稿;同文件、目录祖先冲突停止执行/提交,保留双方内容。当前不进行行级文本合并;文件/目录互换在发布新版本前拒绝。
中断与提交结果
- 非零退出、取消、超时不发布新文件版本,恢复最近的已保存草稿;未成功内容归档在宿主私有存储。
checkout.json记录执行归属,mutation.json记录同步意图;未完成记录阻止普通复用。显式恢复检查保存的 run 请求、会话、主进程锁和原生租约,活动进程或未清理租约继续拒绝接管。- 草稿提交先保存
commit-intent.json,授权绑定 revision、宿主根身份和完整变更摘要。原生宿主事务仍使用 v3 根身份/逐操作日志与独立备份。 - 宿主已经提交、但随后草稿元数据失败时,结果仍报告
writeback: committed,并保留需恢复状态。recover根据授权和会话匹配原生事务,再推进草稿基线;结果未知时不自动重试宿主写入。 - 私有 Git 使用独立的项目/会话命名空间,与原有项目级快照 Git 分开。文件检查点和 Git 发布是两个步骤;Git 失败单独报告,不能声称两者为单个崩溃原子事务。失败命令和真实宿主进程死亡的用例已验证旧 Git 版本不被替换。
恢复支持进程中断,不承诺逐原生指令断电耐久性。原有宿主文件替换仍为禁止覆盖的两次重命名,有短暂缺名窗口,见原生写回事务。
若未确定的宿主提交同时遇到策略或宿主根身份变化,当前自动恢复会拒绝继续,丢弃也不会绕过该记录。此组合需要维护者核对原事务;尚无跨策略/换根自动迁移恢复入口。
源码与验证
| 文件 | 职责 |
|---|---|
native/sandbox/workspace-state.h、runner.cpp |
原生宿主封存入口、目录句柄与 DACL |
src/main/sandbox/workspace.ts |
物理草稿、blob/版本、三方同步、锁、检查点与恢复 |
src/main/sandbox/workspace-service.ts |
管理动作、审批、宿主提交意图与结果恢复 |
src/main/sandbox/workspace-files.ts |
快照/变更扫描共用实现,由原 service 提取 |
src/main/sandbox/service.ts、git-repository.ts |
命令模式路由、草稿生命周期、私有 Git 命名空间 |
src/main/agent/tools/sandbox-workspace.ts、tools/index.ts |
模型工具与显式工作区参数 |
main/preload/shared IPC、scripts/sandbox-maintain.ts |
所属会话只读状态与维护入口 |
npm run build 已通过,包含原生 /W4 /WX、TypeScript 和 main/preload/renderer 生产构建,日志 .tmp/sandbox-persistent-final-build.log。专项命令为 npm run test:sandbox:workspace;生产整应用为 npm run test:sandbox:app。测试期间不能重建正在使用的原生 exe;批量回归直接运行同一次构建对应的独立测试 bundle。
最终报告与摘要汇总见 .tmp/sandbox-persistent-validation.json。所有测试使用独立 .tmp 项目/状态和隔离 Electron userData;生产 OMP 使用实际已安装内核及本机回环模型,没有调用用户付费 API。
最终 11 组共 356 项通过:
| 专项 | 结果 | 最终报告 |
|---|---|---|
| 长期会话草稿 | 51/51 | .tmp/sandbox-workspace-b84whI/report.json |
| 真实生产 Electron/OMP | 42/42 | .tmp/sandbox-app-ZWTjR8/report.json |
| 基础隔离/宿主工具 | 52/52 | .tmp/sandbox-regression-XPTm0T/report.json |
| Git 本地工作流 | 43/43 | .tmp/sandbox-git-mDlqPV/report.json |
| 策略/授权 | 38/38 | .tmp/sandbox-policy-zkcBxS/report.json |
| 目录事务 | 13/13 | .tmp/sandbox-directories-mKwa11/report.json |
| 原生宿主写回 | 32/32 | .tmp/sandbox-write-eZDjBV/report.json |
| 内置 Git 分发 | 20/20 | .tmp/sandbox-bundled-git-EmYmSY/report.json;本次未提供离线归档重建参数 |
| 只读文件桥 | 21/21 | .tmp/sandbox-read-bridge-22EY7p/report.json |
| Node/Python 进程兼容 | 20/20 | .tmp/sandbox-process-QOd5lW/report.json |
| 工具链/依赖 | 24/24 | .tmp/sandbox-toolchain-FUo7VU/report.json |
组件 manifest 中全部原生源码摘要、适配器摘要和二进制摘要已与实物逐项核对;原生 --version 与 manifest 均为 0.6.0。汇总另保存 main/preload 产物和测试报告摘要。本批没有重新构建安装包,不能用之前的 0.4.0 目录包验收替代当前 0.6.0 发布验收。
专项包含真实独立 Node 宿主进程死亡及原生租约恢复、真实 AppContainer 跨会话/同会话私有内容拒绝、只读依赖注入/卸载、原生宿主提交、提交后元数据故障、策略撤销、中文/空格/^ 路径和 CLI 新进程重载。同步/检查点已发布但确认记录未移除的用例是可复现磁盘状态夹具;不把夹具当作每个写入指令位置强杀或断电测试。
尚未完成
长期草稿目前保留受过滤的项目文件和私有 Git。进程、home、TEMP、工具和盘符映射仍为每命令生命周期;实际执行绝对路径不稳定,原项目绝对路径不重定向,后台服务不会跨命令继续运行。
node_modules、.venv、venv、.tmp、__pycache__ 等不作为可写持久层保存。受控只读依赖可临时注入,Node 依赖在封存前移除;联网安装、可写依赖缓存和链接布局仍未完成。宿主 Git 历史/索引导入、元数据事务和远程 Git 尚未接通。
完整文件 shim、元数据/回收站、受控出站、逐程序/逐后代规则、MCP/交互终端系统隔离、安全中心页面、自动保留清理、磁盘硬限额、安装升级、标准用户/平台矩阵、断电耐久性及独立安全审查继续按完整计划推进。当前用户窗口未重启;主进程/preload 新入口在完整重启后加载。
下一步优先处理宿主 Git 的安全导入与元数据事务,然后完善可写依赖和受控联网;相应验收仍逐项记录,不将本批长期草稿通过扩大为完整沙盒完成。