Files
ycode/docs/沙盒长期工作区接入-2026-10-18.md
T

131 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 沙盒长期工作区接入(2026-10-18)
> 当前状态:本文记录 0.6.0 长期草稿历史范围;0.7.0 已扩展宿主 Git 导入/写回/远程。本文后部关于“宿主 Git 尚未接通/下一步”的内容是当时状态,不代表当前;请以[完整 Git 接入](沙盒Git完整接入-2026-10-18.md)和[验收矩阵](沙盒Git接入验收矩阵-2026-10-18.md)为准。长期草稿的其他限制仍有效。
## 交付范围
组件升级为 **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"` 的命令。只读宿主文件桥仍读取绑定的宿主项目,也没有自动重定向到草稿。
## 使用方式
模型工具调用示例:
```json
{"command":"echo draft-value>draft.txt","workspace":"persistent"}
```
```json
{"command":"type draft.txt","workspace":"persistent"}
```
```json
{"action":"changes"}
```
```json
{"action":"commit","expectedRevision":"已观察到的版本 UUID"}
```
后两项调用 `sandbox_workspace`。`expectedRevision` 可省略;提供时版本变化会拒绝操作。`status` 只查看已保存状态,`changes` 才同步未冲突的宿主外部修改并计算待提交变更。`commit` 复用现有对话审批和原生 v3 宿主事务;拒绝审批会保留草稿。规划模式不能调用草稿管理工具。
私有 Git 示例:
```json
{"command":"git add . && git commit -m draft","workspace":"persistent","runtimes":["git"]}
```
Git 默认由应用携带,无需用户注册。此处提交只保存当前会话的沙盒私有历史,不触发宿主写回审批,不写宿主 `.git`,也不代表已经提交到用户原仓库。Node/Python 仍需维护者先导入;只读依赖通过已有 `dependencies` 参数显式选择。
```powershell
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 版本不被替换。
恢复支持进程中断,不承诺逐原生指令断电耐久性。原有宿主文件替换仍为禁止覆盖的两次重命名,有短暂缺名窗口,见[原生写回事务](沙盒原生写回事务-2026-10-18.md)。
若未确定的宿主提交同时遇到策略或宿主根身份变化,当前自动恢复会拒绝继续,丢弃也不会绕过该记录。此组合需要维护者核对原事务;尚无跨策略/换根自动迁移恢复入口。
## 源码与验证
| 文件 | 职责 |
| --- | --- |
| `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/交互终端系统隔离、安全中心页面、自动保留清理、磁盘硬限额、安装升级、标准用户/平台矩阵、断电耐久性及独立安全审查继续按[完整计划](沙盒完整接入计划-2026-10-18.md)推进。当前用户窗口未重启;主进程/preload 新入口在完整重启后加载。
下一步优先处理宿主 Git 的安全导入与元数据事务,然后完善可写依赖和受控联网;相应验收仍逐项记录,不将本批长期草稿通过扩大为完整沙盒完成。