跳转至

09 · Workspace、Environment 与隔离

Project WorkspaceExecution WorkspaceEnvironment LeaseSandboxRuntime Service

一句话结论: Paperclip 把长期代码根、一次执行位置、计算环境、租约和伴随服务建成不同对象;选择策略由 Project 默认、Issue 覆盖和 Trust Preset 联合决定,执行结束后还要显式 finalize/sync/cleanup。

1. 先区分五个对象

对象 生命周期 回答的问题
Project Workspace 长期、项目级 这个项目的代码/文件根在哪里
Execution Workspace 一次任务或一组相关任务 这次实际在哪个副本/分支/远端路径工作
Environment 可复用能力定义 用本机、SSH、sandbox 还是插件 provider 执行
Environment Lease Run 级占用 哪次执行暂时拥有哪个环境实例
Runtime Service 与 workspace/run 关联的进程/服务 preview、dev server、browser 等怎样启动和复用

它们分开的原因是生命周期不同。把它们全叫 cwd 无法表达远端、租约、复用和清理。

2. Project Workspace:稳定锚点

project_workspaces 记录:

  • company/project;
  • name、cwd;
  • repo URL/default ref;
  • setup/cleanup command;
  • remote provider/ref;
  • shared workspace key;
  • primary 标记;
  • runtime config。

Project 可以有零个、一个或多个 workspace。没有 workspace 的非代码项目仍然合法;monorepo 也可以为多个包配置不同根。

3. Execution Workspace:运行事实

execution_workspaces 记录:

  • company/project/project workspace/source issue;
  • mode/strategy/status;
  • cwd、repo/base/branch;
  • provider kind/reference;
  • derived workspace 关系;
  • cleanup state;
  • 可复用/关闭语义。

典型形态:

flowchart TD
  PW["Project Workspace\nmain checkout / remote source"]
  PW --> SHARED["Shared execution\nsame root"]
  PW --> ISO1["Isolated workspace\nissue A worktree"]
  PW --> ISO2["Isolated workspace\nissue B sandbox"]
  PW --> BR["Reusable operator branch\nseveral related issues"]

Issue 可以继承 Project policy、强制 shared/isolated、或复用已有 execution workspace。

4. Policy 选择过程

可以把最终模式理解为:

Project executionWorkspacePolicy
  + Issue executionWorkspacePreference/settings
  + Adapter capability
  + Environment availability
  + Source trust preset
  + Existing compatible workspace/session
  = Effective execution plan

4.1 Trust 会收紧而不会放宽

低信任来源可强制 isolated workspace、禁用共享目录或要求 review。即使 Project 默认 shared,trust policy 也能将结果收紧。

4.2 Issue override 受 Project policy 约束

如果项目禁止 Issue 覆盖,Issue 不能自行选择更宽松的 shared/reuse;服务端计算 effective policy,UI 选项只是输入建议。

5. Environment:在哪里执行

Environment 描述执行驱动和配置,常见 driver:

  • local;
  • SSH;
  • sandbox provider;
  • plugin-contributed environment driver。

环境可声明:

  • 配置、镜像、网络与 filesystem 能力;
  • provisioning/probe;
  • command execution/file transfer;
  • lease/cleanup 机制;
  • custom image template。

环境记录本身是可复用定义,不等同某次动态 sandbox 实例。

6. Lease:环境占用的事务边界

environment_leases 将 company、environment、execution workspace、issue 和 run 关联,并记录:

  • status/policy;
  • provider lease reference;
  • acquired/last used/expires/released 时间;
  • failure/cleanup metadata。
stateDiagram-v2
  [*] --> Acquiring
  Acquiring --> Active: provider allocated
  Acquiring --> Failed: provision error
  Active --> Active: heartbeat / lastUsed
  Active --> Releasing: run terminalized
  Active --> Expired: lease timeout
  Releasing --> Released: sync + cleanup
  Releasing --> Failed: cleanup failure recorded

Lease 让环境清理可以重试和审计,而不依赖某个 finally 恰好成功。

7. Realization:把抽象 workspace 变成可执行目录

不同 transport 的 realization 不同:

直接使用 project cwd 或创建 Git worktree/派生目录;通常不需要上传下载。

通过远程命令建立目录,必要时用 Git bundle/import/export 传递 repository 状态。

通过 archive upload/download 同步文件,在 provider 内创建隔离实例。

由 environment driver 定义 provision、exec、sync 和 cleanup,但仍返回核心可理解的 workspace/lease 记录。

核心 contract 明确不假设远端拥有 Git remote 凭据,也不自动 push。

8. Workspace Operation 是持久化步骤账本

workspace_operations 记录 prepare/finalize 等命令:

  • phase;
  • command/cwd;
  • status;
  • run/issue/workspace;
  • log metadata;
  • started/completed/error。

这解决两个问题:

  1. setup/cleanup 失败不再只存在 Server log;
  2. blocker completion 可以等待上游 finalize 真正 settled。

9. 一个隔离执行的时序

sequenceDiagram
  participant H as Heartbeat
  participant P as Policy Resolver
  participant W as Workspace Service
  participant E as Environment Driver
  participant DB as PostgreSQL
  participant A as Adapter

  H->>P: project + issue + trust + adapter
  P-->>H: isolated workspace plan
  H->>W: find or create execution workspace
  W->>DB: persist preparing workspace
  W->>E: acquire lease + provision
  E-->>W: providerRef / remote cwd
  W->>E: upload/bundle + setup command
  W->>DB: operation succeeded, workspace ready
  H->>A: execute in realized target
  A-->>H: terminal result
  H->>W: finalize
  W->>E: export/download changes + cleanup
  W->>DB: finalize operation settled
  H->>E: release lease

10. Runtime Service:伴随执行的可管理进程

Agent 可能启动 dev server、preview、browser bridge 等。workspace_runtime_services 记录:

  • scope/service kind;
  • status/lifecycle/reuse policy;
  • command/cwd/port/url;
  • provider、owner、run;
  • health/stop metadata。

如果只让 Agent npm run dev &:

  • Server 不知道进程属于谁;
  • 下轮可能重复占端口;
  • workspace 关闭时无法清理;
  • UI 无法把 preview 作为 work product;
  • server restart 后会变成孤儿。

Runtime service 把这类进程纳入控制面。

11. Local service supervisor

本地 service supervisor 负责:

  • 启动命令并保存 PID/process group;
  • 端口/URL 分配;
  • stdout/stderr 与健康状态;
  • reuse 或冲突处理;
  • 有界 stop;
  • startup orphan reconciliation。

远端 provider 可用 provider reference 代替本地 PID,但需要给核心提供同等生命周期信号。

12. Custom Image Setup 是另一条受控运行链

Environment custom image 允许交互式构建运行环境。它有专门的:

  • template;
  • setup session;
  • terminal session token;
  • terminal WebSocket;
  • finish/cancel/rollback。

Terminal WebSocket 自己做 token、session 和 environment 校验,不复用普通 live event socket。构建完成后才更新可选镜像版本,避免半成品成为默认环境。

13. Workspace 文件访问的安全边界

File resource service 不接受任意 host path。它:

  1. 只从 Issue 关联的 execution/project workspace 候选中选根;
  2. 对输入做相对路径规范化;
  3. 拒绝绝对路径、.. 逃逸、home/system/secret 目录;
  4. realpath 后再次确认目标仍在根内,抵抗 symlink escape;
  5. 对内容和 preview 设置大小上限;
  6. 远端 workspace 返回 provider resource,而不是假装本地可读。
用户路径
→ normalize segments
→ select authorized workspace root
→ realpath(root), realpath(target)
→ target must be inside root
→ type/size/content policy
→ preview/download

14. 多 Project Workspace 的当前边界

Issue 的主执行 workspace 可以被完整 realization。引用的附加 project workspace 在本地更容易直接可见;远端 transport 未必会把所有附加 workspace 一并同步。

这是阅读能力声明时要注意的边界:数据模型支持多 workspace,不等于每个 remote adapter 已实现多根一致同步。

15. Cleanup 不是删除目录这么简单

关闭 execution workspace 前要判断:

  • 是否还有 live run/lease;
  • runtime service 是否仍在使用;
  • pending finalize 是否完成;
  • work product/preview 是否需要保留;
  • reusable workspace 是否被其他 Issue 引用;
  • provider cleanup 能否重试;
  • 本地路径是否确实由 Paperclip 管理。

所以 UI 有 close-readiness,Server 有 workspace instance cleanup 与 operation ledger。系统不会对不明确的 host path 做激进递归删除。

16. Workspace 与 Work Product 的边界

Execution workspace 是工作发生地,Work product 是人应审查的输出摘要:

  • PR/branch/commit;
  • preview URL/runtime service;
  • uploaded artifact;
  • workspace file reference。

关闭 workspace 不应自动抹去已上传 artifact 和外部 PR 记录;反过来,文件仍在 workspace 也不代表已交付。

17. 常见故障与收敛

故障 处理方向
worktree 创建失败 operation failed,run setup error,不进入 adapter
sandbox acquire timeout lease failed/expired,按 provider 分类 retry
upload 完成但 DB 未 ready reconciliation 检查 provider ref 与 operation
adapter 成功但 download/finalize 失败 run 与 workspace finalize 分开记录;下游依赖继续等待
cleanup 失败 保留 workspace/lease 失败状态,后台重试/人工处置
runtime service 变孤儿 supervisor/recovery 按 PID/provider reference 扫描
symlink 指向 workspace 外 file resolver realpath 检查拒绝

18. 可复用经验

  1. 长期项目根、执行副本、计算环境和租约要分对象。
  2. Effective policy 应由默认、覆盖、capability 和 trust 共同解析。
  3. Workspace prepare/finalize 要有持久化 operation,而非隐藏 shell hook。
  4. Run 终态和 workspace finalize 是两个事实,下游 readiness 要看后者。
  5. 远端同步 contract 不应默认拥有 Git push 权限。
  6. 文件浏览必须基于注册 root + realpath containment,不能接收任意绝对路径。
  7. Runtime service 也需要 owner、health、reuse 和 cleanup。

源码入口

  • packages/db/src/schema/project_workspaces.ts
  • packages/db/src/schema/execution_workspaces.ts
  • packages/db/src/schema/environments.ts
  • packages/db/src/schema/environment_leases.ts
  • packages/db/src/schema/workspace_operations.ts
  • packages/db/src/schema/workspace_runtime_services.ts
  • server/src/services/workspace-realization.ts
  • server/src/services/execution-workspaces.ts
  • server/src/services/environment-run-orchestrator.ts
  • server/src/services/workspace-runtime.ts
  • server/src/services/workspace-file-resources.ts

执行位置确定后,还必须回答谁能做什么:10 · 身份、认证与细粒度授权。