# 分支沙盒

一瞬间把一个空间（或其中一个文件夹）复制成沙盒，在里面改，看改了什么，只合并想留下的部分。

分支（fork）是从另一个空间（或它的一个文件夹）复制出来的新空间，不搬任何字节。它和原空间共用文件、数据密钥和存储桶，所以几 TB 也是瞬间完成。在分支里照常读写（Finder、CLI、API、MCP 都行），然后列出改了什么，挑着合并回去。

常见用法：给 AI agent 一个沙盒去整理文件、重新打标签；剪一个备选版本；试一版调色而不碰已交付的文件。

```sh
sidespace fork create "Film A" "Film A – 调色试验" --path /Ep01
# …在分支里改文件、打标签、移动、删除…
sidespace fork changes "Film A – 调色试验"
sidespace fork apply "Film A – 调色试验" --dry-run
sidespace fork apply "Film A – 调色试验" /Ep01/color      # 只合并这个文件夹
sidespace fork apply "Film A – 调色试验" --force          # 连冲突一起覆盖
```

## API

| 要做的事 | 调用 |
|---|---|
| 开分支（任何成员；你是分支的管理员） | `POST /v1/spaces/{sid}/forks`，带 `name` 和可选的 `path` |
| 你加入的某空间的分支 | `GET /v1/spaces/{sid}/forks` |
| 分支里改了什么 | `GET /v1/spaces/{fork}/fork/changes` |
| 把改动合并回原空间 | `POST /v1/spaces/{fork}/fork/apply`，可选 `paths`、`force`、`dry_run` |

## 改动和冲突

每条改动是这五种之一：`added`、`modified`、`metadata`（内容没变、附加信息变了）、`moved`（含改名）、`deleted`。

开分支之后原空间里也改过的文件算**冲突**，默认跳过；加 `force` 会用分支的版本覆盖，被覆盖的人照常收到通知。什么都不会丢：他们的版本仍在历史里。

合并需要原空间的编辑权限，并以你的身份写入，所以变更日志、Webhook、通知、附加信息校验和命名空间归属都照常生效，就像你直接在原空间里改的一样。

## 给 AI agent 用的分支

只限某些空间的令牌也可以给这些空间开分支，开出来的分支会自动加入这个令牌的可用范围。agent 可以自己开沙盒干活，碰不到别的空间。

```ts tab=TypeScript
const sandbox = await side.fork("Film A", "Film A – agent", { path: "/Ep01" });
await side.upload(sandbox, "/notes.md", "# ideas\n");
console.log(await side.forkChanges(sandbox));     // [{ kind: "added", path: "/notes.md", … }]
await side.applyFork(sandbox, { dryRun: true });
await side.applyFork(sandbox);                     // 冲突默认跳过，除非 { force: true }
```

```python tab=Python
sandbox = side.fork("Film A", "Film A – agent", path="/Ep01")
side.upload(sandbox, "/notes.md", "# ideas\n")
print(side.fork_changes(sandbox))
side.apply_fork(sandbox, dry_run=True)
side.apply_fork(sandbox)
```

MCP 工具是 `fork_space`、`fork_changes` 和 `apply_fork`。
