diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 75c5a36188..59e7dd1de7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,49 +1,49 @@ -## Thinking Path +## 思路路径 -> - Paperclip orchestrates AI agents for zero-human companies -> - [Which subsystem or capability is involved] -> - [What problem or gap exists] -> - [Why it needs to be addressed] -> - This pull request ... -> - The benefit is ... +> - Paperclip 为零人力公司编排 AI 智能体 +> - [涉及哪个子系统或能力] +> - [存在什么问题或缺口] +> - [为什么需要解决] +> - 本 Pull Request ... +> - 带来的好处是 ... -## What Changed +## 变更内容 - + - -## Verification +## 验证方式 - -## Risks +## 风险 - -## Checklist +## 检查清单 -- [ ] I have included a thinking path that traces from project context to this change -- [ ] I have run tests locally and they pass -- [ ] I have added or updated tests where applicable -- [ ] If this change affects the UI, I have included before/after screenshots -- [ ] I have updated relevant documentation to reflect my changes -- [ ] I have considered and documented any risks above -- [ ] I will address all Greptile and reviewer comments before requesting merge +- [ ] 我已包含从项目上下文到本次变更的思路路径 +- [ ] 我已在本地运行测试并且通过 +- [ ] 我已在适用的地方添加或更新了测试 +- [ ] 如果此变更影响 UI,我已附上修改前/修改后的截图 +- [ ] 我已更新相关文档以反映我的变更 +- [ ] 我已考虑并在上方记录了所有风险 +- [ ] 我将在请求合并之前处理所有 Greptile 和审查者的评论 diff --git a/AGENTS.md b/AGENTS.md index bdfa3e5d4d..644b9b5034 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,15 +1,15 @@ # AGENTS.md -Guidance for human and AI contributors working in this repository. +为在本仓库工作的人类和 AI 贡献者提供的指导。 -## 1. Purpose +## 1. 项目目的 -Paperclip is a control plane for AI-agent companies. -The current implementation target is V1 and is defined in `doc/SPEC-implementation.md`. +Paperclip 是面向 AI 智能体公司的控制平面。 +当前实现目标为 V1,定义在 `doc/SPEC-implementation.md` 中。 -## 2. Read This First +## 2. 请先阅读以下内容 -Before making changes, read in this order: +在进行修改之前,请按以下顺序阅读: 1. `doc/GOAL.md` 2. `doc/PRODUCT.md` @@ -17,98 +17,98 @@ Before making changes, read in this order: 4. `doc/DEVELOPING.md` 5. `doc/DATABASE.md` -`doc/SPEC.md` is long-horizon product context. -`doc/SPEC-implementation.md` is the concrete V1 build contract. +`doc/SPEC.md` 是长期产品背景。 +`doc/SPEC-implementation.md` 是具体的 V1 构建合约。 -## 3. Repo Map +## 3. 仓库结构 -- `server/`: Express REST API and orchestration services -- `ui/`: React + Vite board UI -- `packages/db/`: Drizzle schema, migrations, DB clients -- `packages/shared/`: shared types, constants, validators, API path constants -- `packages/adapters/`: agent adapter implementations (Claude, Codex, Cursor, etc.) -- `packages/adapter-utils/`: shared adapter utilities -- `packages/plugins/`: plugin system packages -- `doc/`: operational and product docs +- `server/`:Express REST API 和编排服务 +- `ui/`:React + Vite 面板 UI +- `packages/db/`:Drizzle schema、迁移、数据库客户端 +- `packages/shared/`:共享类型、常量、验证器、API 路径常量 +- `packages/adapters/`:智能体适配器实现(Claude、Codex、Cursor 等) +- `packages/adapter-utils/`:共享适配器工具 +- `packages/plugins/`:插件系统包 +- `doc/`:运维和产品文档 -## 4. Dev Setup (Auto DB) +## 4. 开发环境搭建(自动数据库) -Use embedded PGlite in dev by leaving `DATABASE_URL` unset. +在开发环境中使用内嵌的 PGlite,不设置 `DATABASE_URL` 即可。 ```sh pnpm install pnpm dev ``` -This starts: +启动后包含: -- API: `http://localhost:3100` -- UI: `http://localhost:3100` (served by API server in dev middleware mode) +- API:`http://localhost:3100` +- UI:`http://localhost:3100`(在开发中间件模式下由 API 服务器提供) -Quick checks: +快速检查: ```sh curl http://localhost:3100/api/health curl http://localhost:3100/api/companies ``` -Reset local dev DB: +重置本地开发数据库: ```sh rm -rf data/pglite pnpm dev ``` -## 5. Core Engineering Rules +## 5. 核心工程规则 -1. Keep changes company-scoped. -Every domain entity should be scoped to a company and company boundaries must be enforced in routes/services. +1. 保持变更限定在公司范围内。 +每个领域实体都应限定在公司范围内,路由/服务中必须强制执行公司边界。 -2. Keep contracts synchronized. -If you change schema/API behavior, update all impacted layers: -- `packages/db` schema and exports -- `packages/shared` types/constants/validators -- `server` routes/services -- `ui` API clients and pages +2. 保持合约同步。 +如果你更改了 schema/API 行为,需更新所有受影响的层: +- `packages/db` schema 和导出 +- `packages/shared` 类型/常量/验证器 +- `server` 路由/服务 +- `ui` API 客户端和页面 -3. Preserve control-plane invariants. -- Single-assignee task model -- Atomic issue checkout semantics -- Approval gates for governed actions -- Budget hard-stop auto-pause behavior -- Activity logging for mutating actions +3. 保持控制平面不变量。 +- 单一指派人任务模型 +- 原子性的 issue 检出语义 +- 受治理操作的审批门控 +- 预算硬性停止自动暂停行为 +- 变更操作的活动日志记录 -4. Do not replace strategic docs wholesale unless asked. -Prefer additive updates. Keep `doc/SPEC.md` and `doc/SPEC-implementation.md` aligned. +4. 除非被要求,不要整体替换战略文档。 +优先进行增量更新。保持 `doc/SPEC.md` 和 `doc/SPEC-implementation.md` 的一致性。 -5. Keep plan docs dated and centralized. -New plan documents belong in `doc/plans/` and should use `YYYY-MM-DD-slug.md` filenames. +5. 保持计划文档标注日期并集中管理。 +新的计划文档应放在 `doc/plans/` 中,使用 `YYYY-MM-DD-slug.md` 文件命名格式。 -## 6. Database Change Workflow +## 6. 数据库变更工作流 -When changing data model: +更改数据模型时: -1. Edit `packages/db/src/schema/*.ts` -2. Ensure new tables are exported from `packages/db/src/schema/index.ts` -3. Generate migration: +1. 编辑 `packages/db/src/schema/*.ts` +2. 确保新表从 `packages/db/src/schema/index.ts` 导出 +3. 生成迁移: ```sh pnpm db:generate ``` -4. Validate compile: +4. 验证编译: ```sh pnpm -r typecheck ``` -Notes: -- `packages/db/drizzle.config.ts` reads compiled schema from `dist/schema/*.js` -- `pnpm db:generate` compiles `packages/db` first +注意事项: +- `packages/db/drizzle.config.ts` 从 `dist/schema/*.js` 读取编译后的 schema +- `pnpm db:generate` 会先编译 `packages/db` -## 7. Verification Before Hand-off +## 7. 提交前验证 -Run this full check before claiming done: +在声明完成之前运行以下完整检查: ```sh pnpm -r typecheck @@ -116,33 +116,33 @@ pnpm test:run pnpm build ``` -If anything cannot be run, explicitly report what was not run and why. +如果有任何检查无法运行,请明确报告哪些未运行及原因。 -## 8. API and Auth Expectations +## 8. API 和认证要求 -- Base path: `/api` -- Board access is treated as full-control operator context -- Agent access uses bearer API keys (`agent_api_keys`), hashed at rest -- Agent keys must not access other companies +- 基础路径:`/api` +- 面板访问视为具有完全控制权的操作员上下文 +- 智能体访问使用 Bearer API 密钥(`agent_api_keys`),静态存储时进行哈希处理 +- 智能体密钥不得访问其他公司的数据 -When adding endpoints: +添加接口时: -- apply company access checks -- enforce actor permissions (board vs agent) -- write activity log entries for mutations -- return consistent HTTP errors (`400/401/403/404/409/422/500`) +- 应用公司访问检查 +- 强制执行操作者权限(面板 vs 智能体) +- 为变更操作写入活动日志条目 +- 返回一致的 HTTP 错误(`400/401/403/404/409/422/500`) -## 9. UI Expectations +## 9. UI 要求 -- Keep routes and nav aligned with available API surface -- Use company selection context for company-scoped pages -- Surface failures clearly; do not silently ignore API errors +- 保持路由和导航与可用的 API 接口对齐 +- 在公司范围页面中使用公司选择上下文 +- 清晰地展示失败信息;不要静默忽略 API 错误 -## 10. Definition of Done +## 10. 完成的定义 -A change is done when all are true: +当以下条件全部满足时,变更才算完成: -1. Behavior matches `doc/SPEC-implementation.md` -2. Typecheck, tests, and build pass -3. Contracts are synced across db/shared/server/ui -4. Docs updated when behavior or commands change +1. 行为符合 `doc/SPEC-implementation.md` +2. 类型检查、测试和构建通过 +3. 合约在 db/shared/server/ui 之间保持同步 +4. 当行为或命令发生变更时,文档已更新 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1eba95e3eb..f108b7043e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,74 +1,74 @@ -# Contributing Guide +# 贡献指南 -Thanks for wanting to contribute! +感谢你愿意参与贡献! -We really appreciate both small fixes and thoughtful larger changes. +我们非常感谢小修复和深思熟虑的大改动。 -## Two Paths to Get Your Pull Request Accepted +## 让你的 Pull Request 被接受的两种方式 -### Path 1: Small, Focused Changes (Fastest way to get merged) +### 方式一:小而专注的改动(最快被合并的方式) -- Pick **one** clear thing to fix/improve -- Touch the **smallest possible number of files** -- Make sure the change is very targeted and easy to review -- All automated checks pass (including Greptile comments) -- No new lint/test failures +- 选择**一个**明确要修复/改进的内容 +- 涉及**尽可能少的文件** +- 确保改动非常有针对性且易于审查 +- 所有自动化检查通过(包括 Greptile 评论) +- 没有新的 lint/测试失败 -These almost always get merged quickly when they're clean. +这类改动在整洁的情况下几乎总能被快速合并。 -### Path 2: Bigger or Impactful Changes +### 方式二:更大或更有影响力的改动 -- **First** talk about it in Discord → #dev channel - → Describe what you're trying to solve - → Share rough ideas / approach -- Once there's rough agreement, build it -- In your PR include: - - Before / After screenshots (or short video if UI/behavior change) - - Clear description of what & why - - Proof it works (manual testing notes) - - All tests passing - - All Greptile + other PR comments addressed +- **首先**在 Discord 的 #dev 频道中讨论 + → 描述你想解决的问题 + → 分享初步想法/方案 +- 在大致达成一致后再开始构建 +- 在你的 PR 中包含: + - 修改前/修改后截图(如果是 UI/行为变更,附上短视频) + - 清晰描述做了什么以及为什么 + - 证明其可用(手动测试记录) + - 所有测试通过 + - 所有 Greptile 及其他 PR 评论已处理 -PRs that follow this path are **much** more likely to be accepted, even when they're large. +遵循这种方式的 PR **更有可能**被接受,即使改动很大。 -## General Rules (both paths) +## 通用规则(适用于两种方式) -- Write clear commit messages -- Keep PR title + description meaningful -- One PR = one logical change (unless it's a small related group) -- Run tests locally first -- Be kind in discussions 😄 +- 编写清晰的提交信息 +- PR 标题和描述要有意义 +- 一个 PR = 一个逻辑变更(除非是一组小的相关改动) +- 先在本地运行测试 +- 在讨论中保持友善 😄 -## Writing a Good PR message +## 编写良好的 PR 信息 -Please include a "thinking path" at the top of your PR message that explains from the top of the project down to what you fixed. E.g.: +请在 PR 信息顶部包含一个"思路路径",从项目顶层开始解释你修复的内容。例如: -### Thinking Path Example 1: +### 思路路径示例 1: -> - Paperclip orchestrates ai-agents for zero-human companies -> - There are many types of adapters for each LLM model provider -> - But LLM's have a context limit and not all agents can automatically compact their context -> - So we need to have an adapter-specific configuration for which adapters can and cannot automatically compact their context -> - This pull request adds per-adapter configuration of compaction, either auto or paperclip managed -> - That way we can get optimal performance from any adapter/provider in Paperclip +> - Paperclip 为零人力公司编排 AI 智能体 +> - 每个 LLM 模型提供商有多种类型的适配器 +> - 但 LLM 有上下文长度限制,并非所有智能体都能自动压缩上下文 +> - 因此我们需要针对每个适配器进行特定配置,设定哪些适配器可以或不可以自动压缩上下文 +> - 本 Pull Request 添加了按适配器配置压缩方式的功能,支持自动模式或 Paperclip 托管模式 +> - 这样我们就能从 Paperclip 中的任何适配器/提供商获得最佳性能 -### Thinking Path Example 2: +### 思路路径示例 2: -> - Paperclip orchestrates ai-agents for zero-human companies -> - But humans want to watch the agents and oversee their work -> - Human users also operate in teams and so they need their own logins, profiles, views etc. -> - So we have a multi-user system for humans -> - But humans want to be able to update their own profile picture and avatar -> - But the avatar upload form wasn't saving the avatar to the file storage system -> - So this PR fixes the avatar upload form to use the file storage service -> - The benefit is we don't have a one-off file storage for just one aspect of the system, which would cause confusion and extra configuration +> - Paperclip 为零人力公司编排 AI 智能体 +> - 但人类希望观察智能体并监督其工作 +> - 人类用户也以团队方式运作,因此他们需要自己的登录、个人资料、视图等 +> - 所以我们有一个面向人类的多用户系统 +> - 但人类希望能够更新自己的头像和个人照片 +> - 然而头像上传表单没有将头像保存到文件存储系统 +> - 因此本 PR 修复了头像上传表单,使其使用文件存储服务 +> - 这样做的好处是我们不会为系统的某一个方面单独维护一套文件存储,避免造成混乱和额外配置 -Then have the rest of your normal PR message after the Thinking Path. +在思路路径之后,继续编写正常的 PR 信息。 -This should include details about what you did, why you did it, why it matters & the benefits, how we can verify it works, and any risks. +信息应包含你做了什么、为什么这样做、为什么重要及其好处、如何验证其有效,以及任何风险。 -Please include screenshots if possible if you have a visible change. (use something like the [agent-browser skill](https://github.com/vercel-labs/agent-browser/blob/main/skills/agent-browser/SKILL.md) or similar to take screenshots). Ideally, you include before and after screenshots. +如果有可见的变更,请尽可能附上截图(可使用类似 [agent-browser skill](https://github.com/vercel-labs/agent-browser/blob/main/skills/agent-browser/SKILL.md) 的工具来截图)。理想情况下,请附上修改前和修改后的截图。 -Questions? Just ask in #dev — we're happy to help. +有问题?在 #dev 频道提问——我们很乐意帮忙。 -Happy hacking! +祝编码愉快! diff --git a/README.md b/README.md index f7ade1b389..ec9d900353 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@
-
+
- Quickstart · - Docs · + 快速开始 · + 文档 · GitHub · Discord
@@ -23,34 +23,34 @@| Works with |
+ 兼容 以下工具 |
OpenClaw |
Claude Code |
Codex |
@@ -60,124 +60,124 @@ It looks like a task manager — but under the hood it has org charts, budgets,
-🔌 Bring Your Own Agent-Any agent, any runtime, one org chart. If it can receive a heartbeat, it's hired. +🔌 自带智能体+任何智能体,任何运行时,统一的组织架构图。只要能接收心跳信号,就能被录用。 |
-🎯 Goal Alignment-Every task traces back to the company mission. Agents know what to do and why. +🎯 目标对齐+每个任务都可追溯到公司使命。智能体知道做什么以及为什么做。 |
-💓 Heartbeats-Agents wake on a schedule, check work, and act. Delegation flows up and down the org chart. +💓 心跳机制+智能体按计划唤醒,检查工作并执行。委派任务在组织架构中上下流转。 |
-💰 Cost Control-Monthly budgets per agent. When they hit the limit, they stop. No runaway costs. +💰 成本控制+每个智能体的月度预算。达到上限就停止。杜绝成本失控。 |
-🏢 Multi-Company-One deployment, many companies. Complete data isolation. One control plane for your portfolio. +🏢 多公司支持+一次部署,多家公司。完全数据隔离。一个控制平面管理你的所有业务。 |
-🎫 Ticket System-Every conversation traced. Every decision explained. Full tool-call tracing and immutable audit log. +🎫 工单系统+每次对话都有记录。每个决策都有说明。完整的工具调用追踪和不可篡改的审计日志。 |
-🛡️ Governance-You're the board. Approve hires, override strategy, pause or terminate any agent — at any time. +🛡️ 治理机制+你就是董事会。批准招聘、覆盖策略、暂停或终止任何智能体——随时可以。 |
-📊 Org Chart-Hierarchies, roles, reporting lines. Your agents have a boss, a title, and a job description. +📊 组织架构图+层级结构、角色、汇报关系。你的智能体有上级、有职位、有岗位描述。 |
-📱 Mobile Ready-Monitor and manage your autonomous businesses from anywhere. +📱 移动端适配+随时随地监控和管理你的自主业务。 |
- Open source under MIT. Built for people who want to run companies, not babysit agents. + 基于 MIT 协议开源。为想运营公司、而非守着智能体的人而建。
diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index d261b8a85d..977e35839b 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -2,10 +2,10 @@ ## 0.3.1 -### Patch Changes +### 补丁变更 -- Stable release preparation for 0.3.1 -- Updated dependencies +- 0.3.1 稳定版本发布准备 +- 更新依赖 - @paperclipai/adapter-utils@0.3.1 - @paperclipai/adapter-claude-local@0.3.1 - @paperclipai/adapter-codex-local@0.3.1 @@ -20,14 +20,14 @@ ## 0.3.0 -### Minor Changes +### 次要变更 -- Stable release preparation for 0.3.0 +- 0.3.0 稳定版本发布准备 -### Patch Changes +### 补丁变更 -- Updated dependencies [6077ae6] -- Updated dependencies +- 更新依赖 [6077ae6] +- 更新依赖 - @paperclipai/shared@0.3.0 - @paperclipai/adapter-utils@0.3.0 - @paperclipai/adapter-claude-local@0.3.0 @@ -41,10 +41,10 @@ ## 0.2.7 -### Patch Changes +### 补丁变更 -- Version bump (patch) -- Updated dependencies +- 版本号升级(补丁) +- 更新依赖 - @paperclipai/shared@0.2.7 - @paperclipai/adapter-utils@0.2.7 - @paperclipai/db@0.2.7 @@ -55,10 +55,10 @@ ## 0.2.6 -### Patch Changes +### 补丁变更 -- Version bump (patch) -- Updated dependencies +- 版本号升级(补丁) +- 更新依赖 - @paperclipai/shared@0.2.6 - @paperclipai/adapter-utils@0.2.6 - @paperclipai/db@0.2.6 @@ -69,10 +69,10 @@ ## 0.2.5 -### Patch Changes +### 补丁变更 -- Version bump (patch) -- Updated dependencies +- 版本号升级(补丁) +- 更新依赖 - @paperclipai/shared@0.2.5 - @paperclipai/adapter-utils@0.2.5 - @paperclipai/db@0.2.5 @@ -83,10 +83,10 @@ ## 0.2.4 -### Patch Changes +### 补丁变更 -- Version bump (patch) -- Updated dependencies +- 版本号升级(补丁) +- 更新依赖 - @paperclipai/shared@0.2.4 - @paperclipai/adapter-utils@0.2.4 - @paperclipai/db@0.2.4 @@ -97,10 +97,10 @@ ## 0.2.3 -### Patch Changes +### 补丁变更 -- Version bump (patch) -- Updated dependencies +- 版本号升级(补丁) +- 更新依赖 - @paperclipai/shared@0.2.3 - @paperclipai/adapter-utils@0.2.3 - @paperclipai/db@0.2.3 @@ -111,10 +111,10 @@ ## 0.2.2 -### Patch Changes +### 补丁变更 -- Version bump (patch) -- Updated dependencies +- 版本号升级(补丁) +- 更新依赖 - @paperclipai/shared@0.2.2 - @paperclipai/adapter-utils@0.2.2 - @paperclipai/db@0.2.2 @@ -125,10 +125,10 @@ ## 0.2.1 -### Patch Changes +### 补丁变更 -- Version bump (patch) -- Updated dependencies +- 版本号升级(补丁) +- 更新依赖 - @paperclipai/shared@0.2.1 - @paperclipai/adapter-utils@0.2.1 - @paperclipai/db@0.2.1 diff --git a/doc/AGENTCOMPANIES_SPEC_INVENTORY.md b/doc/AGENTCOMPANIES_SPEC_INVENTORY.md index 99de314d05..4b95943f7a 100644 --- a/doc/AGENTCOMPANIES_SPEC_INVENTORY.md +++ b/doc/AGENTCOMPANIES_SPEC_INVENTORY.md @@ -1,115 +1,115 @@ -# Agent Companies Spec Inventory +# Agent Companies 规范清单 -This document indexes every part of the Paperclip codebase that touches the [Agent Companies Specification](docs/companies/companies-spec.md) (`agentcompanies/v1-draft`). +本文档索引了 Paperclip 代码库中涉及 [Agent Companies 规范](docs/companies/companies-spec.md)(`agentcompanies/v1-draft`)的每个部分。 -Use it when you need to: +当你需要以下操作时可以使用本文档: -1. **Update the spec** — know which implementation code must change in lockstep. -2. **Change code that involves the spec** — find all related files quickly. -3. **Keep things aligned** — audit whether implementation matches the spec. +1. **更新规范** — 了解哪些实现代码必须同步修改。 +2. **修改涉及规范的代码** — 快速找到所有相关文件。 +3. **保持一致性** — 审核实现是否与规范匹配。 --- -## 1. Specification & Design Documents +## 1. 规范与设计文档 -| File | Role | +| 文件 | 角色 | |---|---| -| `docs/companies/companies-spec.md` | **Normative spec** — defines the markdown-first package format (COMPANY.md, TEAM.md, AGENTS.md, PROJECT.md, TASK.md, SKILL.md), reserved files, frontmatter schemas, and vendor extension conventions (`.paperclip.yaml`). | -| `doc/plans/2026-03-13-company-import-export-v2.md` | Implementation plan for the markdown-first package model cutover — phases, API changes, UI plan, and rollout strategy. | -| `doc/SPEC-implementation.md` | V1 implementation contract; references the portability system and `.paperclip.yaml` sidecar format. | -| `docs/specs/cliphub-plan.md` | Earlier blueprint bundle plan; partially superseded by the markdown-first spec (noted in the v2 plan). | -| `doc/plans/2026-02-16-module-system.md` | Module system plan; JSON-only company template sections superseded by the markdown-first model. | -| `doc/plans/2026-03-14-skills-ui-product-plan.md` | Skills UI plan; references portable skill files and `.paperclip.yaml`. | -| `doc/plans/2026-03-14-adapter-skill-sync-rollout.md` | Adapter skill sync rollout; companion to the v2 import/export plan. | +| `docs/companies/companies-spec.md` | **规范性规范** — 定义了以 markdown 为核心的包格式(COMPANY.md、TEAM.md、AGENTS.md、PROJECT.md、TASK.md、SKILL.md)、保留文件、frontmatter 模式以及厂商扩展约定(`.paperclip.yaml`)。 | +| `doc/plans/2026-03-13-company-import-export-v2.md` | 以 markdown 为核心的包模型切换的实现计划 — 阶段、API 变更、UI 计划和发布策略。 | +| `doc/SPEC-implementation.md` | V1 实现契约;引用了可移植性系统和 `.paperclip.yaml` sidecar 格式。 | +| `docs/specs/cliphub-plan.md` | 早期的蓝图包计划;已被以 markdown 为核心的规范部分取代(在 v2 计划中注明)。 | +| `doc/plans/2026-02-16-module-system.md` | 模块系统计划;仅支持 JSON 的公司模板部分已被以 markdown 为核心的模型取代。 | +| `doc/plans/2026-03-14-skills-ui-product-plan.md` | 技能 UI 计划;引用了可移植技能文件和 `.paperclip.yaml`。 | +| `doc/plans/2026-03-14-adapter-skill-sync-rollout.md` | 适配器技能同步发布;v2 导入/导出计划的配套文档。 | -## 2. Shared Types & Validators +## 2. 共享类型与验证器 -These define the contract between server, CLI, and UI. +这些定义了服务端、CLI 和 UI 之间的契约。 -| File | What it defines | +| 文件 | 定义内容 | |---|---| -| `packages/shared/src/types/company-portability.ts` | TypeScript interfaces: `CompanyPortabilityManifest`, `CompanyPortabilityFileEntry`, `CompanyPortabilityEnvInput`, export/import/preview request and result types, manifest entry types for agents, skills, projects, issues, recurring routines, companies. | -| `packages/shared/src/validators/company-portability.ts` | Zod schemas for all portability request/response shapes — used by both server routes and CLI. | -| `packages/shared/src/types/index.ts` | Re-exports portability types. | -| `packages/shared/src/validators/index.ts` | Re-exports portability validators. | +| `packages/shared/src/types/company-portability.ts` | TypeScript 接口:`CompanyPortabilityManifest`、`CompanyPortabilityFileEntry`、`CompanyPortabilityEnvInput`、导出/导入/预览请求和结果类型、代理、技能、项目、议题、定期例程、公司的清单条目类型。 | +| `packages/shared/src/validators/company-portability.ts` | 所有可移植性请求/响应形状的 Zod 模式 — 被服务端路由和 CLI 共同使用。 | +| `packages/shared/src/types/index.ts` | 重新导出可移植性类型。 | +| `packages/shared/src/validators/index.ts` | 重新导出可移植性验证器。 | -## 3. Server — Services +## 3. 服务端 — 服务 -| File | Responsibility | +| 文件 | 职责 | |---|---| -| `server/src/services/company-portability.ts` | **Core portability service.** Export (manifest generation, markdown file emission, `.paperclip.yaml` sidecars), import (graph resolution, collision handling, entity creation), preview (planned-action summary). Handles skill key derivation, recurring task <-> routine mapping, legacy recurrence migration, and package README generation. References `agentcompanies/v1` version string. | -| `server/src/services/routines.ts` | Paperclip routine runtime service. Portability now exports routines as recurring `TASK.md` entries and imports recurring tasks back through this service. | -| `server/src/services/company-export-readme.ts` | Generates `README.md` and Mermaid org-chart for exported company packages. | -| `server/src/services/index.ts` | Re-exports `companyPortabilityService`. | +| `server/src/services/company-portability.ts` | **核心可移植性服务。** 导出(清单生成、markdown 文件输出、`.paperclip.yaml` sidecars)、导入(图解析、冲突处理、实体创建)、预览(计划操作摘要)。处理技能键派生、定期任务 <-> 例程映射、旧版重复迁移和包 README 生成。引用 `agentcompanies/v1` 版本字符串。 | +| `server/src/services/routines.ts` | Paperclip 例程运行时服务。可移植性现在将例程导出为定期的 `TASK.md` 条目,并通过此服务将定期任务导入回来。 | +| `server/src/services/company-export-readme.ts` | 为导出的公司包生成 `README.md` 和 Mermaid 组织结构图。 | +| `server/src/services/index.ts` | 重新导出 `companyPortabilityService`。 | -## 4. Server — Routes +## 4. 服务端 — 路由 -| File | Endpoints | +| 文件 | 端点 | |---|---| -| `server/src/routes/companies.ts` | `POST /api/companies/:companyId/export` — legacy export bundle`
-- intended use: signed-in human claims board ownership
-- claim action:
- - promotes current signed-in user to `instance_admin`
- - demotes `local-board` admin role
- - ensures active owner membership for the claiming user across existing companies
+- URL 格式:`/board-claim/?code=`
+- 预期用途:已登录的人工用户声明董事会所有权
+- 声明操作:
+ - 将当前已登录用户提升为 `instance_admin`
+ - 降级 `local-board` 管理员角色
+ - 确保声明用户在现有公司中拥有活跃的所有者成员身份
-This prevents lockout when a user migrates from long-running local trusted usage to authenticated mode.
+这防止了用户从长期运行的本地受信使用迁移到认证模式时被锁定。
-## 8. Current Code Reality (As Of 2026-02-23)
+## 8. 当前代码实际情况(截至 2026-02-23)
-- runtime values are `local_trusted | authenticated`
-- `authenticated` uses Better Auth sessions and bootstrap invite flow
-- `local_trusted` ensures a real local Board user principal in `authUsers` with `instance_user_roles` admin access
-- company creation ensures creator membership in `company_memberships` so user assignment/access flows remain consistent
+- 运行时值为 `local_trusted | authenticated`
+- `authenticated` 使用 Better Auth 会话和引导邀请流程
+- `local_trusted` 确保 `authUsers` 中存在真实的本地董事会用户主体,并在 `instance_user_roles` 中拥有管理员访问权限
+- 公司创建确保创建者在 `company_memberships` 中拥有成员身份,以便用户分配/访问流程保持一致
-## 9. Naming and Compatibility Policy
+## 9. 命名和兼容性策略
-- canonical naming is `local_trusted` and `authenticated` with `private/public` exposure
-- no long-term compatibility alias layer for discarded naming variants
+- 规范命名为 `local_trusted` 和 `authenticated`,配合 `private/public` 暴露方式
+- 不为已弃用的命名变体提供长期兼容性别名层
-## 10. Relationship to Other Docs
+## 10. 与其他文档的关系
-- implementation plan: `doc/plans/deployment-auth-mode-consolidation.md`
-- V1 contract: `doc/SPEC-implementation.md`
-- operator workflows: `doc/DEVELOPING.md` and `doc/CLI.md`
+- 实施计划:`doc/plans/deployment-auth-mode-consolidation.md`
+- V1 约定:`doc/SPEC-implementation.md`
+- 操作员工作流:`doc/DEVELOPING.md` 和 `doc/CLI.md`
diff --git a/doc/DEVELOPING.md b/doc/DEVELOPING.md
index 7864b90edb..adc10c4a64 100644
--- a/doc/DEVELOPING.md
+++ b/doc/DEVELOPING.md
@@ -1,77 +1,77 @@
-# Developing
+# 开发指南
-This project can run fully in local dev without setting up PostgreSQL manually.
+本项目可以在不手动设置 PostgreSQL 的情况下完全在本地开发环境中运行。
-## Deployment Modes
+## 部署模式
-For mode definitions and intended CLI behavior, see `doc/DEPLOYMENT-MODES.md`.
+有关模式定义和预期的 CLI 行为,请参见 `doc/DEPLOYMENT-MODES.md`。
-Current implementation status:
+当前实施状态:
-- canonical model: `local_trusted` and `authenticated` (with `private/public` exposure)
+- 规范模型:`local_trusted` 和 `authenticated`(带有 `private/public` 暴露方式)
-## Prerequisites
+## 前提条件
- Node.js 20+
- pnpm 9+
-## Dependency Lockfile Policy
+## 依赖锁定文件策略
-GitHub Actions owns `pnpm-lock.yaml`.
+GitHub Actions 管理 `pnpm-lock.yaml`。
-- Do not commit `pnpm-lock.yaml` in pull requests.
-- Pull request CI validates dependency resolution when manifests change.
-- Pushes to `master` regenerate `pnpm-lock.yaml` with `pnpm install --lockfile-only --no-frozen-lockfile`, commit it back if needed, and then run verification with `--frozen-lockfile`.
+- 不要在 Pull Request 中提交 `pnpm-lock.yaml`。
+- Pull Request CI 在清单更改时验证依赖解析。
+- 推送到 `master` 时使用 `pnpm install --lockfile-only --no-frozen-lockfile` 重新生成 `pnpm-lock.yaml`,如需要则提交回去,然后使用 `--frozen-lockfile` 运行验证。
-## Start Dev
+## 启动开发
-From repo root:
+从仓库根目录:
```sh
pnpm install
pnpm dev
```
-This starts:
+这将启动:
-- API server: `http://localhost:3100`
-- UI: served by the API server in dev middleware mode (same origin as API)
+- API 服务器:`http://localhost:3100`
+- UI:由 API 服务器在开发中间件模式下提供(与 API 同源)
-`pnpm dev` runs the server in watch mode and restarts on changes from workspace packages (including adapter packages). Use `pnpm dev:once` to run without file watching.
+`pnpm dev` 以监视模式运行服务器,当工作区包(包括适配器包)发生变更时自动重启。使用 `pnpm dev:once` 运行而不进行文件监视。
-`pnpm dev:once` now tracks backend-relevant file changes and pending migrations. When the current boot is stale, the board UI shows a `Restart required` banner. You can also enable guarded auto-restart in `Instance Settings > Experimental`, which waits for queued/running local agent runs to finish before restarting the dev server.
+`pnpm dev:once` 现在会追踪后端相关的文件变更和待处理的迁移。当当前启动过期时,董事会 UI 会显示 `Restart required` 横幅。你还可以在 `Instance Settings > Experimental` 中启用受保护的自动重启,它会等待排队/运行中的本地代理任务完成后再重启开发服务器。
-Tailscale/private-auth dev mode:
+Tailscale/私有认证开发模式:
```sh
pnpm dev --tailscale-auth
```
-This runs dev as `authenticated/private` and binds the server to `0.0.0.0` for private-network access.
+这将以 `authenticated/private` 模式运行开发,并将服务器绑定到 `0.0.0.0` 以允许私有网络访问。
-Allow additional private hostnames (for example custom Tailscale hostnames):
+允许额外的私有主机名(例如自定义 Tailscale 主机名):
```sh
pnpm paperclipai allowed-hostname dotta-macbook-pro
```
-## One-Command Local Run
+## 一键本地运行
-For a first-time local install, you can bootstrap and run in one command:
+对于首次本地安装,你可以一条命令引导并运行:
```sh
pnpm paperclipai run
```
-`paperclipai run` does:
+`paperclipai run` 执行以下操作:
-1. auto-onboard if config is missing
-2. `paperclipai doctor` with repair enabled
-3. starts the server when checks pass
+1. 如果配置缺失则自动入门
+2. 启用修复的 `paperclipai doctor`
+3. 检查通过后启动服务器
-## Docker Quickstart (No local Node install)
+## Docker 快速启动(无需本地安装 Node)
-Build and run Paperclip in Docker:
+在 Docker 中构建和运行 Paperclip:
```sh
docker build -t paperclip-local .
@@ -83,120 +83,120 @@ docker run --name paperclip \
paperclip-local
```
-Or use Compose:
+或使用 Compose:
```sh
docker compose -f docker-compose.quickstart.yml up --build
```
-See `doc/DOCKER.md` for API key wiring (`OPENAI_API_KEY` / `ANTHROPIC_API_KEY`) and persistence details.
+有关 API 密钥配置(`OPENAI_API_KEY` / `ANTHROPIC_API_KEY`)和持久化详情,请参见 `doc/DOCKER.md`。
-## Docker For Untrusted PR Review
+## 用于不受信任 PR 审查的 Docker
-For a separate review-oriented container that keeps `codex`/`claude` login state in Docker volumes and checks out PRs into an isolated scratch workspace, see `doc/UNTRUSTED-PR-REVIEW.md`.
+如需一个单独的面向审查的容器,该容器将 `codex`/`claude` 登录状态保存在 Docker 卷中,并将 PR 检出到隔离的临时工作区中,请参见 `doc/UNTRUSTED-PR-REVIEW.md`。
-## Database in Dev (Auto-Handled)
+## 开发中的数据库(自动处理)
-For local development, leave `DATABASE_URL` unset.
-The server will automatically use embedded PostgreSQL and persist data at:
+对于本地开发,保持 `DATABASE_URL` 未设置。
+服务器将自动使用嵌入式 PostgreSQL 并将数据持久化在:
- `~/.paperclip/instances/default/db`
-Override home and instance:
+覆盖主目录和实例:
```sh
PAPERCLIP_HOME=/custom/path PAPERCLIP_INSTANCE_ID=dev pnpm paperclipai run
```
-No Docker or external database is required for this mode.
+此模式不需要 Docker 或外部数据库。
-## Storage in Dev (Auto-Handled)
+## 开发中的存储(自动处理)
-For local development, the default storage provider is `local_disk`, which persists uploaded images/attachments at:
+对于本地开发,默认存储提供者是 `local_disk`,将上传的图片/附件持久化在:
- `~/.paperclip/instances/default/data/storage`
-Configure storage provider/settings:
+配置存储提供者/设置:
```sh
pnpm paperclipai configure --section storage
```
-## Default Agent Workspaces
+## 默认代理工作区
-When a local agent run has no resolved project/session workspace, Paperclip falls back to an agent home workspace under the instance root:
+当本地代理运行没有已解析的项目/会话工作区时,Paperclip 回退到实例根目录下的代理主工作区:
- `~/.paperclip/instances/default/workspaces/`
-This path honors `PAPERCLIP_HOME` and `PAPERCLIP_INSTANCE_ID` in non-default setups.
+此路径在非默认设置中遵循 `PAPERCLIP_HOME` 和 `PAPERCLIP_INSTANCE_ID`。
-For `codex_local`, Paperclip also manages a per-company Codex home under the instance root and seeds it from the shared Codex login/config home (`$CODEX_HOME` or `~/.codex`):
+对于 `codex_local`,Paperclip 还在实例根目录下管理每个公司的 Codex 主目录,并从共享的 Codex 登录/配置主目录(`$CODEX_HOME` 或 `~/.codex`)中初始化:
- `~/.paperclip/instances/default/companies//codex-home`
-## Worktree-local Instances
+## 工作树本地实例
-When developing from multiple git worktrees, do not point two Paperclip servers at the same embedded PostgreSQL data directory.
+从多个 git 工作树开发时,不要将两个 Paperclip 服务器指向同一个嵌入式 PostgreSQL 数据目录。
-Instead, create a repo-local Paperclip config plus an isolated instance for the worktree:
+相反,为工作树创建一个仓库本地的 Paperclip 配置和隔离实例:
```sh
paperclipai worktree init
-# or create the git worktree and initialize it in one step:
+# 或者一步创建 git 工作树并初始化:
pnpm paperclipai worktree:make paperclip-pr-432
```
-This command:
+此命令:
-- writes repo-local files at `.paperclip/config.json` and `.paperclip/.env`
-- creates an isolated instance under `~/.paperclip-worktrees/instances//`
-- when run inside a linked git worktree, mirrors the effective git hooks into that worktree's private git dir
-- picks a free app port and embedded PostgreSQL port
-- by default seeds the isolated DB in `minimal` mode from the current effective Paperclip instance/config (repo-local worktree config when present, otherwise the default instance) via a logical SQL snapshot
+- 在 `.paperclip/config.json` 和 `.paperclip/.env` 中写入仓库本地文件
+- 在 `~/.paperclip-worktrees/instances//` 下创建隔离实例
+- 当在链接的 git 工作树中运行时,将有效的 git hooks 镜像到该工作树的私有 git 目录中
+- 选择空闲的应用端口和嵌入式 PostgreSQL 端口
+- 默认以 `minimal` 模式从当前有效的 Paperclip 实例/配置(存在仓库本地工作树配置时使用,否则使用默认实例)通过逻辑 SQL 快照初始化隔离数据库
-Seed modes:
+初始化模式:
-- `minimal` keeps core app state like companies, projects, issues, comments, approvals, and auth state, preserves schema for all tables, but omits row data from heavy operational history such as heartbeat runs, wake requests, activity logs, runtime services, and agent session state
-- `full` makes a full logical clone of the source instance
-- `--no-seed` creates an empty isolated instance
+- `minimal` 保留核心应用状态如公司、项目、issues、评论、审批和认证状态,保留所有表的 schema,但省略心跳运行、唤醒请求、活动日志、运行时服务和代理会话状态等重操作历史数据
+- `full` 对源实例进行完整的逻辑克隆
+- `--no-seed` 创建空的隔离实例
-After `worktree init`, both the server and the CLI auto-load the repo-local `.paperclip/.env` when run inside that worktree, so normal commands like `pnpm dev`, `paperclipai doctor`, and `paperclipai db:backup` stay scoped to the worktree instance.
+`worktree init` 之后,服务器和 CLI 在该工作树中运行时会自动加载仓库本地的 `.paperclip/.env`,因此 `pnpm dev`、`paperclipai doctor` 和 `paperclipai db:backup` 等正常命令仍然限定在工作树实例范围内。
-That repo-local env also sets:
+该仓库本地环境还设置了:
- `PAPERCLIP_IN_WORKTREE=true`
- `PAPERCLIP_WORKTREE_NAME=`
- `PAPERCLIP_WORKTREE_COLOR=`
-The server/UI use those values for worktree-specific branding such as the top banner and dynamically colored favicon.
+服务器/UI 使用这些值进行工作树特定的品牌标识,如顶部横幅和动态着色的 favicon。
-Print shell exports explicitly when needed:
+需要时显式打印 shell 导出:
```sh
paperclipai worktree env
-# or:
+# 或:
eval "$(paperclipai worktree env)"
```
-### Worktree CLI Reference
+### 工作树 CLI 参考
-**`pnpm paperclipai worktree init [options]`** — Create repo-local config/env and an isolated instance for the current worktree.
+**`pnpm paperclipai worktree init [options]`** — 为当前工作树创建仓库本地配置/环境和隔离实例。
-| Option | Description |
+| 选项 | 描述 |
|---|---|
-| `--name ` | Display name used to derive the instance id |
-| `--instance ` | Explicit isolated instance id |
-| `--home ` | Home root for worktree instances (default: `~/.paperclip-worktrees`) |
-| `--from-config ` | Source config.json to seed from |
-| `--from-data-dir ` | Source PAPERCLIP_HOME used when deriving the source config |
-| `--from-instance ` | Source instance id (default: `default`) |
-| `--server-port ` | Preferred server port |
-| `--db-port ` | Preferred embedded Postgres port |
-| `--seed-mode ` | Seed profile: `minimal` or `full` (default: `minimal`) |
-| `--no-seed` | Skip database seeding from the source instance |
-| `--force` | Replace existing repo-local config and isolated instance data |
-
-Examples:
+| `--name ` | 用于派生实例 ID 的显示名称 |
+| `--instance ` | 显式隔离实例 ID |
+| `--home ` | 工作树实例的主根目录(默认:`~/.paperclip-worktrees`) |
+| `--from-config ` | 用于初始化的源 config.json |
+| `--from-data-dir ` | 派生源配置时使用的源 PAPERCLIP_HOME |
+| `--from-instance ` | 源实例 ID(默认:`default`) |
+| `--server-port ` | 首选服务器端口 |
+| `--db-port ` | 首选嵌入式 Postgres 端口 |
+| `--seed-mode ` | 初始化配置:`minimal` 或 `full`(默认:`minimal`) |
+| `--no-seed` | 跳过从源实例初始化数据库 |
+| `--force` | 替换现有仓库本地配置和隔离实例数据 |
+
+示例:
```sh
paperclipai worktree init --no-seed
@@ -206,7 +206,7 @@ paperclipai worktree init --from-data-dir ~/.paperclip
paperclipai worktree init --force
```
-Repair an already-created repo-managed worktree and reseed its isolated instance from the main default install:
+修复已创建的仓库管理工作树并从主默认安装重新初始化其隔离实例:
```sh
cd ~/.paperclip/worktrees/PAP-884-ai-commits-component
@@ -215,25 +215,25 @@ pnpm paperclipai worktree init --force --seed-mode minimal \
--from-config ~/.paperclip/instances/default/config.json
```
-That rewrites the worktree-local `.paperclip/config.json` + `.paperclip/.env`, recreates the isolated instance under `~/.paperclip-worktrees/instances//`, and preserves the git worktree contents themselves.
+这将重写工作树本地的 `.paperclip/config.json` + `.paperclip/.env`,在 `~/.paperclip-worktrees/instances//` 下重新创建隔离实例,并保留 git 工作树内容本身。
-**`pnpm paperclipai worktree:make [options]`** — Create `~/NAME` as a git worktree, then initialize an isolated Paperclip instance inside it. This combines `git worktree add` with `worktree init` in a single step.
+**`pnpm paperclipai worktree:make [options]`** — 将 `~/NAME` 创建为 git 工作树,然后在其中初始化隔离的 Paperclip 实例。这将 `git worktree add` 和 `worktree init` 合并为一个步骤。
-| Option | Description |
+| 选项 | 描述 |
|---|---|
-| `--start-point ` | Remote ref to base the new branch on (e.g. `origin/main`) |
-| `--instance ` | Explicit isolated instance id |
-| `--home ` | Home root for worktree instances (default: `~/.paperclip-worktrees`) |
-| `--from-config ` | Source config.json to seed from |
-| `--from-data-dir ` | Source PAPERCLIP_HOME used when deriving the source config |
-| `--from-instance ` | Source instance id (default: `default`) |
-| `--server-port ` | Preferred server port |
-| `--db-port ` | Preferred embedded Postgres port |
-| `--seed-mode ` | Seed profile: `minimal` or `full` (default: `minimal`) |
-| `--no-seed` | Skip database seeding from the source instance |
-| `--force` | Replace existing repo-local config and isolated instance data |
-
-Examples:
+| `--start-point ` | 新分支基于的远程引用(例如 `origin/main`) |
+| `--instance ` | 显式隔离实例 ID |
+| `--home ` | 工作树实例的主根目录(默认:`~/.paperclip-worktrees`) |
+| `--from-config ` | 用于初始化的源 config.json |
+| `--from-data-dir ` | 派生源配置时使用的源 PAPERCLIP_HOME |
+| `--from-instance ` | 源实例 ID(默认:`default`) |
+| `--server-port ` | 首选服务器端口 |
+| `--db-port ` | 首选嵌入式 Postgres 端口 |
+| `--seed-mode ` | 初始化配置:`minimal` 或 `full`(默认:`minimal`) |
+| `--no-seed` | 跳过从源实例初始化数据库 |
+| `--force` | 替换现有仓库本地配置和隔离实例数据 |
+
+示例:
```sh
pnpm paperclipai worktree:make paperclip-pr-432
@@ -241,14 +241,14 @@ pnpm paperclipai worktree:make my-feature --start-point origin/main
pnpm paperclipai worktree:make experiment --no-seed
```
-**`pnpm paperclipai worktree env [options]`** — Print shell exports for the current worktree-local Paperclip instance.
+**`pnpm paperclipai worktree env [options]`** — 打印当前工作树本地 Paperclip 实例的 shell 导出。
-| Option | Description |
+| 选项 | 描述 |
|---|---|
-| `-c, --config ` | Path to config file |
-| `--json` | Print JSON instead of shell exports |
+| `-c, --config ` | 配置文件路径 |
+| `--json` | 打印 JSON 而不是 shell 导出 |
-Examples:
+示例:
```sh
pnpm paperclipai worktree env
@@ -256,112 +256,112 @@ pnpm paperclipai worktree env --json
eval "$(pnpm paperclipai worktree env)"
```
-For project execution worktrees, Paperclip can also run a project-defined provision command after it creates or reuses an isolated git worktree. Configure this on the project's execution workspace policy (`workspaceStrategy.provisionCommand`). The command runs inside the derived worktree and receives `PAPERCLIP_WORKSPACE_*`, `PAPERCLIP_PROJECT_ID`, `PAPERCLIP_AGENT_ID`, and `PAPERCLIP_ISSUE_*` environment variables so each repo can bootstrap itself however it wants.
+对于项目执行工作树,Paperclip 还可以在创建或复用隔离的 git 工作树后运行项目定义的配置命令。在项目的执行工作区策略(`workspaceStrategy.provisionCommand`)中配置。该命令在派生的工作树内运行,并接收 `PAPERCLIP_WORKSPACE_*`、`PAPERCLIP_PROJECT_ID`、`PAPERCLIP_AGENT_ID` 和 `PAPERCLIP_ISSUE_*` 环境变量,以便每个仓库可以按需引导自身。
-## Quick Health Checks
+## 快速健康检查
-In another terminal:
+在另一个终端中:
```sh
curl http://localhost:3100/api/health
curl http://localhost:3100/api/companies
```
-Expected:
+预期结果:
-- `/api/health` returns `{"status":"ok"}`
-- `/api/companies` returns a JSON array
+- `/api/health` 返回 `{"status":"ok"}`
+- `/api/companies` 返回一个 JSON 数组
-## Reset Local Dev Database
+## 重置本地开发数据库
-To wipe local dev data and start fresh:
+要清除本地开发数据并全新开始:
```sh
rm -rf ~/.paperclip/instances/default/db
pnpm dev
```
-## Optional: Use External Postgres
+## 可选:使用外部 Postgres
-If you set `DATABASE_URL`, the server will use that instead of embedded PostgreSQL.
+如果你设置了 `DATABASE_URL`,服务器将使用它而不是嵌入式 PostgreSQL。
-## Automatic DB Backups
+## 自动数据库备份
-Paperclip can run automatic DB backups on a timer. Defaults:
+Paperclip 可以按定时器运行自动数据库备份。默认值:
-- enabled
-- every 60 minutes
-- retain 30 days
-- backup dir: `~/.paperclip/instances/default/data/backups`
+- 已启用
+- 每 60 分钟
+- 保留 30 天
+- 备份目录:`~/.paperclip/instances/default/data/backups`
-Configure these in:
+在以下位置配置:
```sh
pnpm paperclipai configure --section database
```
-Run a one-off backup manually:
+手动运行一次性备份:
```sh
pnpm paperclipai db:backup
-# or:
+# 或:
pnpm db:backup
```
-Environment overrides:
+环境变量覆盖:
- `PAPERCLIP_DB_BACKUP_ENABLED=true|false`
- `PAPERCLIP_DB_BACKUP_INTERVAL_MINUTES=`
- `PAPERCLIP_DB_BACKUP_RETENTION_DAYS=`
- `PAPERCLIP_DB_BACKUP_DIR=/absolute/or/~/path`
-## Secrets in Dev
+## 开发中的密钥
-Agent env vars now support secret references. By default, secret values are stored with local encryption and only secret refs are persisted in agent config.
+代理环境变量现在支持密钥引用。默认情况下,密钥值使用本地加密存储,只有密钥引用持久化在代理配置中。
-- Default local key path: `~/.paperclip/instances/default/secrets/master.key`
-- Override key material directly: `PAPERCLIP_SECRETS_MASTER_KEY`
-- Override key file path: `PAPERCLIP_SECRETS_MASTER_KEY_FILE`
+- 默认本地密钥路径:`~/.paperclip/instances/default/secrets/master.key`
+- 直接覆盖密钥材料:`PAPERCLIP_SECRETS_MASTER_KEY`
+- 覆盖密钥文件路径:`PAPERCLIP_SECRETS_MASTER_KEY_FILE`
-Strict mode (recommended outside local trusted machines):
+严格模式(建议在非本地受信机器上使用):
```sh
PAPERCLIP_SECRETS_STRICT_MODE=true
```
-When strict mode is enabled, sensitive env keys (for example `*_API_KEY`, `*_TOKEN`, `*_SECRET`) must use secret references instead of inline plain values.
+当严格模式启用时,敏感环境变量键(例如 `*_API_KEY`、`*_TOKEN`、`*_SECRET`)必须使用密钥引用而不是内联明文值。
-CLI configuration support:
+CLI 配置支持:
-- `pnpm paperclipai onboard` writes a default `secrets` config section (`local_encrypted`, strict mode off, key file path set) and creates a local key file when needed.
-- `pnpm paperclipai configure --section secrets` lets you update provider/strict mode/key path and creates the local key file when needed.
-- `pnpm paperclipai doctor` validates secrets adapter configuration and can create a missing local key file with `--repair`.
+- `pnpm paperclipai onboard` 写入默认的 `secrets` 配置节(`local_encrypted`,严格模式关闭,密钥文件路径已设置),并在需要时创建本地密钥文件。
+- `pnpm paperclipai configure --section secrets` 允许你更新提供者/严格模式/密钥路径,并在需要时创建本地密钥文件。
+- `pnpm paperclipai doctor` 验证密钥适配器配置,并可使用 `--repair` 创建缺失的本地密钥文件。
-Migration helper for existing inline env secrets:
+现有内联环境密钥的迁移助手:
```sh
-pnpm secrets:migrate-inline-env # dry run
-pnpm secrets:migrate-inline-env --apply # apply migration
+pnpm secrets:migrate-inline-env # 试运行
+pnpm secrets:migrate-inline-env --apply # 应用迁移
```
-## Company Deletion Toggle
+## 公司删除开关
-Company deletion is intended as a dev/debug capability and can be disabled at runtime:
+公司删除旨在作为开发/调试功能,可在运行时禁用:
```sh
PAPERCLIP_ENABLE_COMPANY_DELETION=false
```
-Default behavior:
+默认行为:
-- `local_trusted`: enabled
-- `authenticated`: disabled
+- `local_trusted`:已启用
+- `authenticated`:已禁用
-## CLI Client Operations
+## CLI 客户端操作
-Paperclip CLI now includes client-side control-plane commands in addition to setup commands.
+Paperclip CLI 现在除了设置命令外还包含客户端控制平面命令。
-Quick examples:
+快速示例:
```sh
pnpm paperclipai issue list --company-id
@@ -369,82 +369,82 @@ pnpm paperclipai issue create --company-id --title "Investigate che
pnpm paperclipai issue update --status in_progress --comment "Started triage"
```
-Set defaults once with context profiles:
+使用上下文配置一次性设置默认值:
```sh
pnpm paperclipai context set --api-base http://localhost:3100 --company-id
```
-Then run commands without repeating flags:
+然后无需重复标志即可运行命令:
```sh
pnpm paperclipai issue list
pnpm paperclipai dashboard get
```
-See full command reference in `doc/CLI.md`.
+完整命令参考请参见 `doc/CLI.md`。
-## OpenClaw Invite Onboarding Endpoints
+## OpenClaw 邀请入门端点
-Agent-oriented invite onboarding now exposes machine-readable API docs:
+面向代理的邀请入门现在暴露机器可读的 API 文档:
-- `GET /api/invites/:token` returns invite summary plus onboarding and skills index links.
-- `GET /api/invites/:token/onboarding` returns onboarding manifest details (registration endpoint, claim endpoint template, skill install hints).
-- `GET /api/invites/:token/onboarding.txt` returns a plain-text onboarding doc intended for both human operators and agents (llm.txt-style handoff), including optional inviter message and suggested network host candidates.
-- `GET /api/skills/index` lists available skill documents.
-- `GET /api/skills/paperclip` returns the Paperclip heartbeat skill markdown.
+- `GET /api/invites/:token` 返回邀请摘要以及入门和技能索引链接。
+- `GET /api/invites/:token/onboarding` 返回入门清单详情(注册端点、声明端点模板、技能安装提示)。
+- `GET /api/invites/:token/onboarding.txt` 返回面向人工操作员和代理的纯文本入门文档(llm.txt 风格交接),包含可选的邀请者消息和建议的网络主机候选。
+- `GET /api/skills/index` 列出可用的技能文档。
+- `GET /api/skills/paperclip` 返回 Paperclip 心跳技能 markdown。
-## OpenClaw Join Smoke Test
+## OpenClaw 加入冒烟测试
-Run the end-to-end OpenClaw join smoke harness:
+运行端到端 OpenClaw 加入冒烟测试工具:
```sh
pnpm smoke:openclaw-join
```
-What it validates:
+验证内容:
-- invite creation for agent-only join
-- agent join request using `adapterType=openclaw`
-- board approval + one-time API key claim semantics
-- callback delivery on wakeup to a dockerized OpenClaw-style webhook receiver
+- 仅代理加入的邀请创建
+- 使用 `adapterType=openclaw` 的代理加入请求
+- 董事会审批 + 一次性 API 密钥声明语义
+- 对容器化 OpenClaw 风格 webhook 接收器的唤醒回调交付
-Required permissions:
+所需权限:
-- This script performs board-governed actions (create invite, approve join, wakeup another agent).
-- In authenticated mode, run with board auth via `PAPERCLIP_AUTH_HEADER` or `PAPERCLIP_COOKIE`.
+- 此脚本执行受董事会管理的操作(创建邀请、审批加入、唤醒另一个代理)。
+- 在认证模式下,通过 `PAPERCLIP_AUTH_HEADER` 或 `PAPERCLIP_COOKIE` 使用董事会认证运行。
-Optional auth flags (for authenticated mode):
+可选认证标志(用于认证模式):
-- `PAPERCLIP_AUTH_HEADER` (for example `Bearer ...`)
-- `PAPERCLIP_COOKIE` (session cookie header value)
+- `PAPERCLIP_AUTH_HEADER`(例如 `Bearer ...`)
+- `PAPERCLIP_COOKIE`(会话 cookie 头值)
-## OpenClaw Docker UI One-Command Script
+## OpenClaw Docker UI 一键脚本
-To boot OpenClaw in Docker and print a host-browser dashboard URL in one command:
+要在 Docker 中启动 OpenClaw 并一条命令打印主机浏览器仪表盘 URL:
```sh
pnpm smoke:openclaw-docker-ui
```
-This script lives at `scripts/smoke/openclaw-docker-ui.sh` and automates clone/build/config/start for Compose-based local OpenClaw UI testing.
+此脚本位于 `scripts/smoke/openclaw-docker-ui.sh`,自动化基于 Compose 的本地 OpenClaw UI 测试的克隆/构建/配置/启动流程。
-Pairing behavior for this smoke script:
+此冒烟脚本的配对行为:
-- default `OPENCLAW_DISABLE_DEVICE_AUTH=1` (no Control UI pairing prompt for local smoke; no extra pairing env vars required)
-- set `OPENCLAW_DISABLE_DEVICE_AUTH=0` to require standard device pairing
+- 默认 `OPENCLAW_DISABLE_DEVICE_AUTH=1`(本地冒烟测试无 Control UI 配对提示;不需要额外的配对环境变量)
+- 设置 `OPENCLAW_DISABLE_DEVICE_AUTH=0` 以要求标准设备配对
-Model behavior for this smoke script:
+此冒烟脚本的模型行为:
-- defaults to OpenAI models (`openai/gpt-5.2` + OpenAI fallback) so it does not require Anthropic auth by default
+- 默认使用 OpenAI 模型(`openai/gpt-5.2` + OpenAI 回退),因此默认不需要 Anthropic 认证
-State behavior for this smoke script:
+此冒烟脚本的状态行为:
-- defaults to isolated config dir `~/.openclaw-paperclip-smoke`
-- resets smoke agent state each run by default (`OPENCLAW_RESET_STATE=1`) to avoid stale provider/auth drift
+- 默认使用隔离的配置目录 `~/.openclaw-paperclip-smoke`
+- 每次运行默认重置冒烟代理状态(`OPENCLAW_RESET_STATE=1`)以避免陈旧的提供者/认证漂移
-Networking behavior for this smoke script:
+此冒烟脚本的网络行为:
-- auto-detects and prints a Paperclip host URL reachable from inside OpenClaw Docker
-- default container-side host alias is `host.docker.internal` (override with `PAPERCLIP_HOST_FROM_CONTAINER` / `PAPERCLIP_HOST_PORT`)
-- if Paperclip rejects container hostnames in authenticated/private mode, allow `host.docker.internal` via `pnpm paperclipai allowed-hostname host.docker.internal` and restart Paperclip
+- 自动检测并打印从 OpenClaw Docker 内部可达的 Paperclip 主机 URL
+- 默认容器端主机别名为 `host.docker.internal`(通过 `PAPERCLIP_HOST_FROM_CONTAINER` / `PAPERCLIP_HOST_PORT` 覆盖)
+- 如果 Paperclip 在 authenticated/private 模式下拒绝容器主机名,通过 `pnpm paperclipai allowed-hostname host.docker.internal` 允许 `host.docker.internal` 并重启 Paperclip
diff --git a/doc/DOCKER.md b/doc/DOCKER.md
index a7055e203c..1be76d25e5 100644
--- a/doc/DOCKER.md
+++ b/doc/DOCKER.md
@@ -1,8 +1,8 @@
-# Docker Quickstart
+# Docker 快速入门
-Run Paperclip in Docker without installing Node or pnpm locally.
+在 Docker 中运行 Paperclip,无需在本地安装 Node 或 pnpm。
-## One-liner (build + run)
+## 一行命令(构建 + 运行)
```sh
docker build -t paperclip-local . && \
@@ -14,39 +14,39 @@ docker run --name paperclip \
paperclip-local
```
-Open: `http://localhost:3100`
+打开:`http://localhost:3100`
-Data persistence:
+数据持久化:
-- Embedded PostgreSQL data
-- uploaded assets
-- local secrets key
-- local agent workspace data
+- 内嵌 PostgreSQL 数据
+- 已上传的资源
+- 本地密钥
+- 本地代理工作区数据
-All persisted under your bind mount (`./data/docker-paperclip` in the example above).
+所有数据都持久化在你的绑定挂载目录下(上面示例中的 `./data/docker-paperclip`)。
-## Compose Quickstart
+## Compose 快速入门
```sh
docker compose -f docker-compose.quickstart.yml up --build
```
-Defaults:
+默认值:
-- host port: `3100`
-- persistent data dir: `./data/docker-paperclip`
+- 主机端口:`3100`
+- 持久化数据目录:`./data/docker-paperclip`
-Optional overrides:
+可选覆盖:
```sh
PAPERCLIP_PORT=3200 PAPERCLIP_DATA_DIR=./data/pc docker compose -f docker-compose.quickstart.yml up --build
```
-If you change host port or use a non-local domain, set `PAPERCLIP_PUBLIC_URL` to the external URL you will use in browser/auth flows.
+如果你更改了主机端口或使用非本地域名,请将 `PAPERCLIP_PUBLIC_URL` 设置为你将在浏览器/认证流程中使用的外部 URL。
-## Authenticated Compose (Single Public URL)
+## 认证模式 Compose(单一公共 URL)
-For authenticated deployments, set one canonical public URL and let Paperclip derive auth/callback defaults:
+对于认证部署,设置一个规范的公共 URL,让 Paperclip 自动推导认证/回调默认值:
```yaml
services:
@@ -57,25 +57,25 @@ services:
PAPERCLIP_PUBLIC_URL: https://desk.koker.net
```
-`PAPERCLIP_PUBLIC_URL` is used as the primary source for:
+`PAPERCLIP_PUBLIC_URL` 被用作以下内容的主要来源:
-- auth public base URL
-- Better Auth base URL defaults
-- bootstrap invite URL defaults
-- hostname allowlist defaults (hostname extracted from URL)
+- 认证公共基础 URL
+- Better Auth 基础 URL 默认值
+- 引导邀请 URL 默认值
+- 主机名允许列表默认值(从 URL 中提取主机名)
-Granular overrides remain available if needed (`PAPERCLIP_AUTH_PUBLIC_BASE_URL`, `BETTER_AUTH_URL`, `BETTER_AUTH_TRUSTED_ORIGINS`, `PAPERCLIP_ALLOWED_HOSTNAMES`).
+如果需要,仍可使用细粒度覆盖(`PAPERCLIP_AUTH_PUBLIC_BASE_URL`、`BETTER_AUTH_URL`、`BETTER_AUTH_TRUSTED_ORIGINS`、`PAPERCLIP_ALLOWED_HOSTNAMES`)。
-Set `PAPERCLIP_ALLOWED_HOSTNAMES` explicitly only when you need additional hostnames beyond the public URL host (for example Tailscale/LAN aliases or multiple private hostnames).
+仅当你需要公共 URL 主机之外的额外主机名时(例如 Tailscale/LAN 别名或多个私有主机名),才需要显式设置 `PAPERCLIP_ALLOWED_HOSTNAMES`。
-## Claude + Codex Local Adapters in Docker
+## Docker 中的 Claude 和 Codex 本地适配器
-The image pre-installs:
+镜像预装了:
-- `claude` (Anthropic Claude Code CLI)
-- `codex` (OpenAI Codex CLI)
+- `claude`(Anthropic Claude Code CLI)
+- `codex`(OpenAI Codex CLI)
-If you want local adapter runs inside the container, pass API keys when starting the container:
+如果你想在容器内运行本地适配器,启动容器时传入 API 密钥:
```sh
docker run --name paperclip \
@@ -88,34 +88,34 @@ docker run --name paperclip \
paperclip-local
```
-Notes:
+注意:
-- Without API keys, the app still runs normally.
-- Adapter environment checks in Paperclip will surface missing auth/CLI prerequisites.
+- 不提供 API 密钥,应用仍然可以正常运行。
+- Paperclip 中的适配器环境检查会提示缺少的认证/CLI 前置条件。
-## Untrusted PR Review Container
+## 不可信 PR 审查容器
-If you want a separate Docker environment for reviewing untrusted pull requests with `codex` or `claude`, use the dedicated review workflow in `doc/UNTRUSTED-PR-REVIEW.md`.
+如果你想要一个独立的 Docker 环境,使用 `codex` 或 `claude` 审查不可信的拉取请求,请使用 `doc/UNTRUSTED-PR-REVIEW.md` 中的专用审查工作流。
-That setup keeps CLI auth state in Docker volumes instead of your host home directory and uses a separate scratch workspace for PR checkouts and preview runs.
+该设置将 CLI 认证状态保存在 Docker 卷中,而非你的主机 home 目录,并使用独立的临时工作区进行 PR 检出和预览运行。
-## Onboard Smoke Test (Ubuntu + npm only)
+## 入门冒烟测试(Ubuntu + npm 环境)
-Use this when you want to mimic a fresh machine that only has Ubuntu + npm and verify:
+当你想模拟一台只有 Ubuntu + npm 的全新机器并验证以下内容时使用:
-- `npx paperclipai onboard --yes` completes
-- the server binds to `0.0.0.0:3100` so host access works
-- onboard/run banners and startup logs are visible in your terminal
+- `npx paperclipai onboard --yes` 能顺利完成
+- 服务器绑定到 `0.0.0.0:3100`,使主机可以访问
+- 入门/运行横幅和启动日志在终端中可见
-Build + run:
+构建 + 运行:
```sh
./scripts/docker-onboard-smoke.sh
```
-Open: `http://localhost:3131` (default smoke host port)
+打开:`http://localhost:3131`(默认冒烟测试主机端口)
-Useful overrides:
+有用的覆盖参数:
```sh
HOST_PORT=3200 PAPERCLIPAI_VERSION=latest ./scripts/docker-onboard-smoke.sh
@@ -123,14 +123,14 @@ PAPERCLIP_DEPLOYMENT_MODE=authenticated PAPERCLIP_DEPLOYMENT_EXPOSURE=private ./
SMOKE_DETACH=true SMOKE_METADATA_FILE=/tmp/paperclip-smoke.env PAPERCLIPAI_VERSION=latest ./scripts/docker-onboard-smoke.sh
```
-Notes:
-
-- Persistent data is mounted at `./data/docker-onboard-smoke` by default.
-- Container runtime user id defaults to your local `id -u` so the mounted data dir stays writable while avoiding root runtime.
-- Smoke script defaults to `authenticated/private` mode so `HOST=0.0.0.0` can be exposed to the host.
-- Smoke script defaults host port to `3131` to avoid conflicts with local Paperclip on `3100`.
-- Smoke script also defaults `PAPERCLIP_PUBLIC_URL` to `http://localhost:` so bootstrap invite URLs and auth callbacks use the reachable host port instead of the container's internal `3100`.
-- In authenticated mode, the smoke script defaults `SMOKE_AUTO_BOOTSTRAP=true` and drives the real bootstrap path automatically: it signs up a real user, runs `paperclipai auth bootstrap-ceo` inside the container to mint a real bootstrap invite, accepts that invite over HTTP, and verifies board session access.
-- Run the script in the foreground to watch the onboarding flow; stop with `Ctrl+C` after validation.
-- Set `SMOKE_DETACH=true` to leave the container running for automation and optionally write shell-ready metadata to `SMOKE_METADATA_FILE`.
-- The image definition is in `Dockerfile.onboard-smoke`.
+注意:
+
+- 持久化数据默认挂载在 `./data/docker-onboard-smoke`。
+- 容器运行时用户 ID 默认使用你本地的 `id -u`,这样挂载的数据目录保持可写,同时避免以 root 身份运行。
+- 冒烟测试脚本默认使用 `authenticated/private` 模式,这样 `HOST=0.0.0.0` 可以暴露给主机。
+- 冒烟测试脚本默认主机端口为 `3131`,以避免与本地 Paperclip 的 `3100` 端口冲突。
+- 冒烟测试脚本还默认将 `PAPERCLIP_PUBLIC_URL` 设置为 `http://localhost:`,这样引导邀请 URL 和认证回调使用可达的主机端口,而非容器内部的 `3100`。
+- 在认证模式下,冒烟测试脚本默认设置 `SMOKE_AUTO_BOOTSTRAP=true`,并自动执行真实的引导流程:注册一个真实用户,在容器内运行 `paperclipai auth bootstrap-ceo` 生成真实的引导邀请,通过 HTTP 接受该邀请,并验证董事会会话访问。
+- 在前台运行脚本以观察入门流程;验证后按 `Ctrl+C` 停止。
+- 设置 `SMOKE_DETACH=true` 以保持容器运行用于自动化,并可选将 shell 可读的元数据写入 `SMOKE_METADATA_FILE`。
+- 镜像定义在 `Dockerfile.onboard-smoke` 中。
diff --git a/doc/GOAL.md b/doc/GOAL.md
index f32399ff16..3cba2b6b6b 100644
--- a/doc/GOAL.md
+++ b/doc/GOAL.md
@@ -1,55 +1,55 @@
# Paperclip
-**Paperclip is the backbone of the autonomous economy.** We are building the infrastructure that autonomous AI companies run on. Our goal is for Paperclip-powered companies to collectively generate economic output that rivals the GDP of the world's largest countries. Every decision we make should serve that: make autonomous companies more capable, more governable, more scalable, and more real.
+**Paperclip 是自主经济的骨干。** 我们正在构建自主 AI 公司运行所需的基础设施。我们的目标是让 Paperclip 驱动的公司集体产生的经济产出能够媲美世界最大国家的 GDP。我们做出的每一个决定都应该服务于此:让自主公司更有能力、更可治理、更可扩展、更加真实。
-## The Vision
+## 愿景
-Autonomous companies — AI workforces organized with real structure, governance, and accountability — will become a major force in the global economy. Not one company. Thousands. Millions. An entire economic layer that runs on AI labor, coordinated through Paperclip.
+自主公司 — 以真实的结构、治理和问责制组织的 AI 劳动力 — 将成为全球经济中的重要力量。不是一家公司,而是成千上万家。数百万家。一个完整的经济层,运行在 AI 劳动力上,通过 Paperclip 进行协调。
-Paperclip is not the company. Paperclip is what makes the companies possible. We are the control plane, the nervous system, the operating layer. Every autonomous company needs structure, task management, cost control, goal alignment, and human governance. That's us. We are to autonomous companies what the corporate operating system is to human ones — except this time, the operating system is real software, not metaphor.
+Paperclip 不是那家公司。Paperclip 是让这些公司成为可能的基础。我们是控制平面、神经系统、运营层。每家自主公司都需要结构、任务管理、成本控制、目标对齐和人类治理。这就是我们。我们之于自主公司,就像企业操作系统之于人类公司 — 只不过这一次,操作系统是真正的软件,而不是比喻。
-The measure of our success is not whether one company works. It's whether Paperclip becomes the default foundation that autonomous companies are built on — and whether those companies, collectively, become a serious economic force that rivals the output of nations.
+衡量我们成功的标准不是某一家公司是否运作良好。而是 Paperclip 是否成为自主公司构建的默认基础 — 以及这些公司是否集体成为一股能与国家产出相匹敌的严肃经济力量。
-## The Problem
+## 问题
-Task management software doesn't go far enough. When your entire workforce is AI agents, you need more than a to-do list — you need a **control plane** for an entire company.
+任务管理软件做得还不够。当你的整个劳动力都是 AI 代理时,你需要的不仅仅是一个待办事项列表 — 你需要一个完整公司的**控制平面**。
-## What This Is
+## 这是什么
-Paperclip is the command, communication, and control plane for a company of AI agents. It is the single place where you:
+Paperclip 是 AI 代理公司的指挥、通信和控制平面。它是你进行以下操作的唯一场所:
-- **Manage agents as employees** — hire, organize, and track who does what
-- **Define org structure** — org charts that agents themselves operate within
-- **Track work in real time** — see at any moment what every agent is working on
-- **Control costs** — token salary budgets per agent, spend tracking, burn rate
-- **Align to goals** — agents see how their work serves the bigger mission
-- **Store company knowledge** — a shared brain for the organization
+- **将代理作为员工管理** — 雇佣、组织和跟踪谁做什么
+- **定义组织结构** — 代理在其中运作的组织结构图
+- **实时跟踪工作** — 随时查看每个代理正在做什么
+- **控制成本** — 每个代理的 token 薪资预算、支出跟踪、消耗率
+- **对齐目标** — 代理了解他们的工作如何服务于更大的使命
+- **存储公司知识** — 组织的共享大脑
-## Architecture
+## 架构
-Two layers:
+两个层次:
-### 1. Control Plane (this software)
+### 1. 控制平面(本软件)
-The central nervous system. Manages:
+中枢神经系统。管理:
-- Agent registry and org chart
-- Task assignment and status
-- Budget and token spend tracking
-- Company knowledge base
-- Goal hierarchy (company → team → agent → task)
-- Heartbeat monitoring — know when agents are alive, idle, or stuck
+- 代理注册表和组织结构图
+- 任务分配和状态
+- 预算和 token 支出跟踪
+- 公司知识库
+- 目标层级(公司 → 团队 → 代理 → 任务)
+- 心跳监控 — 了解代理是否存活、空闲或卡住
-### 2. Execution Services (adapters)
+### 2. 执行服务(适配器)
-Agents run externally and report into the control plane. An agent is just Python code that gets kicked off and does work. Adapters connect different execution environments:
+代理在外部运行并向控制平面汇报。代理只是被启动并执行工作的 Python 代码。适配器连接不同的执行环境:
-- **OpenClaw** — initial adapter target
-- **Heartbeat loop** — simple custom Python that loops, checks in, does work
-- **Others** — any runtime that can call an API
+- **OpenClaw** — 初始适配器目标
+- **心跳循环** — 简单的自定义 Python,循环、签到、执行工作
+- **其他** — 任何能调用 API 的运行时
-The control plane doesn't run agents. It orchestrates them. Agents run wherever they run and phone home.
+控制平面不运行代理。它编排代理。代理在任何地方运行,然后回报状态。
-## Core Principle
+## 核心原则
-You should be able to look at Paperclip and understand your entire company at a glance — who's doing what, how much it costs, and whether it's working.
+你应该能够查看 Paperclip 并一目了然地了解你的整个公司 — 谁在做什么、花费多少、是否有效。
diff --git a/doc/OPENCLAW_ONBOARDING.md b/doc/OPENCLAW_ONBOARDING.md
index bdb098b371..bfe2433b26 100644
--- a/doc/OPENCLAW_ONBOARDING.md
+++ b/doc/OPENCLAW_ONBOARDING.md
@@ -1,94 +1,94 @@
-Use this exact checklist.
+请使用以下检查清单。
-1. Start Paperclip in auth mode.
+1. 以认证模式启动 Paperclip。
```bash
cd
pnpm dev --tailscale-auth
```
-Then verify:
+然后验证:
```bash
curl -sS http://127.0.0.1:3100/api/health | jq
```
-2. Start a clean/stock OpenClaw Docker.
+2. 启动一个全新/默认的 OpenClaw Docker。
```bash
OPENCLAW_RESET_STATE=1 OPENCLAW_BUILD=1 ./scripts/smoke/openclaw-docker-ui.sh
```
-Open the printed `Dashboard URL` (includes `#token=...`) in your browser.
+在浏览器中打开输出的 `Dashboard URL`(包含 `#token=...`)。
-3. In Paperclip UI, go to `http://127.0.0.1:3100/CLA/company/settings`.
+3. 在 Paperclip UI 中,访问 `http://127.0.0.1:3100/CLA/company/settings`。
-4. Use the OpenClaw invite prompt flow.
-- In the Invites section, click `Generate OpenClaw Invite Prompt`.
-- Copy the generated prompt from `OpenClaw Invite Prompt`.
-- Paste it into OpenClaw main chat as one message.
-- If it stalls, send one follow-up: `How is onboarding going? Continue setup now.`
+4. 使用 OpenClaw 邀请提示流程。
+- 在"邀请"部分,点击 `Generate OpenClaw Invite Prompt`。
+- 从 `OpenClaw Invite Prompt` 复制生成的提示。
+- 将其作为一条消息粘贴到 OpenClaw 主聊天中。
+- 如果卡住了,发送一条跟进消息:`How is onboarding going? Continue setup now.`
-Security/control note:
-- The OpenClaw invite prompt is created from a controlled endpoint:
+安全/控制说明:
+- OpenClaw 邀请提示通过受控端点创建:
- `POST /api/companies/{companyId}/openclaw/invite-prompt`
- - board users with invite permission can call it
- - agent callers are limited to the company CEO agent
+ - 具有邀请权限的董事会用户可以调用
+ - 代理调用者仅限公司 CEO 代理
-5. Approve the join request in Paperclip UI, then confirm the OpenClaw agent appears in CLA agents.
+5. 在 Paperclip UI 中批准加入请求,然后确认 OpenClaw 代理出现在 CLA 代理列表中。
-6. Gateway preflight (required before task tests).
-- Confirm the created agent uses `openclaw_gateway` (not `openclaw`).
-- Confirm gateway URL is `ws://...` or `wss://...`.
-- Confirm gateway token is non-trivial (not empty / not 1-char placeholder).
-- The OpenClaw Gateway adapter UI should not expose `disableDeviceAuth` for normal onboarding.
-- Confirm pairing mode is explicit:
- - required default: device auth enabled (`adapterConfig.disableDeviceAuth` false/absent) with persisted `adapterConfig.devicePrivateKeyPem`
- - do not rely on `disableDeviceAuth` for normal onboarding
-- If you can run API checks with board auth:
+6. 网关预检(任务测试前必需)。
+- 确认创建的代理使用 `openclaw_gateway`(不是 `openclaw`)。
+- 确认网关 URL 是 `ws://...` 或 `wss://...`。
+- 确认网关 token 不是简单值(非空/非单字符占位符)。
+- OpenClaw Gateway 适配器 UI 在正常入门流程中不应暴露 `disableDeviceAuth`。
+- 确认配对模式是显式的:
+ - 必须的默认值:设备认证已启用(`adapterConfig.disableDeviceAuth` 为 false/未设置)且已持久化 `adapterConfig.devicePrivateKeyPem`
+ - 正常入门流程中不要依赖 `disableDeviceAuth`
+- 如果你能使用董事会认证运行 API 检查:
```bash
AGENT_ID=""
curl -sS -H "Cookie: $PAPERCLIP_COOKIE" "http://127.0.0.1:3100/api/agents/$AGENT_ID" | jq '{adapterType,adapterConfig:{url:.adapterConfig.url,tokenLen:(.adapterConfig.headers["x-openclaw-token"] // .adapterConfig.headers["x-openclaw-auth"] // "" | length),disableDeviceAuth:(.adapterConfig.disableDeviceAuth // false),hasDeviceKey:(.adapterConfig.devicePrivateKeyPem // "" | length > 0)}}'
```
-- Expected: `adapterType=openclaw_gateway`, `tokenLen >= 16`, `hasDeviceKey=true`, and `disableDeviceAuth=false`.
+- 预期结果:`adapterType=openclaw_gateway`、`tokenLen >= 16`、`hasDeviceKey=true`、`disableDeviceAuth=false`。
-Pairing handshake note:
-- Clean run expectation: first task should succeed without manual pairing commands.
-- The adapter attempts one automatic pairing approval + retry on first `pairing required` (when shared gateway auth token/password is valid).
-- If auto-pair cannot complete (for example token mismatch or no pending request), the first gateway run may still return `pairing required`.
-- This is a separate approval from Paperclip invite approval. You must approve the pending device in OpenClaw itself.
-- Approve it in OpenClaw, then retry the task.
-- For local docker smoke, you can approve from host:
+配对握手说明:
+- 干净运行的预期:首次任务应该无需手动配对命令即可成功。
+- 适配器在首次收到 `pairing required` 时会尝试一次自动配对批准 + 重试(当共享网关认证 token/密码有效时)。
+- 如果自动配对无法完成(例如 token 不匹配或没有待处理的请求),首次网关运行可能仍会返回 `pairing required`。
+- 这与 Paperclip 邀请批准是分开的。你必须在 OpenClaw 本身中批准待处理的设备。
+- 在 OpenClaw 中批准后,重试任务。
+- 对于本地 docker 冒烟测试,你可以从主机批准:
```bash
docker exec openclaw-docker-openclaw-gateway-1 sh -lc 'openclaw devices approve --latest --json --url "ws://127.0.0.1:18789" --token "$(node -p \"require(process.env.HOME+\\\"/.openclaw/openclaw.json\\\").gateway.auth.token\")"'
```
-- You can inspect pending vs paired devices:
+- 你可以检查待处理与已配对的设备:
```bash
docker exec openclaw-docker-openclaw-gateway-1 sh -lc 'TOK="$(node -e \"const fs=require(\\\"fs\\\");const c=JSON.parse(fs.readFileSync(\\\"/home/node/.openclaw/openclaw.json\\\",\\\"utf8\\\"));process.stdout.write(c.gateway?.auth?.token||\\\"\\\");\")\"; openclaw devices list --json --url \"ws://127.0.0.1:18789\" --token \"$TOK\"'
```
-7. Case A (manual issue test).
-- Create an issue assigned to the OpenClaw agent.
-- Put instructions: “post comment `OPENCLAW_CASE_A_OK_` and mark done.”
-- Verify in UI: issue status becomes `done` and comment exists.
+7. 案例 A(手动议题测试)。
+- 创建一个分配给 OpenClaw 代理的议题。
+- 添加指令:"post comment `OPENCLAW_CASE_A_OK_` and mark done."
+- 在 UI 中验证:议题状态变为 `done` 且评论存在。
-8. Case B (message tool test).
-- Create another issue assigned to OpenClaw.
-- Instructions: “send `OPENCLAW_CASE_B_OK_` to main webchat via message tool, then comment same marker on issue, then mark done.”
-- Verify both:
- - marker comment on issue
- - marker text appears in OpenClaw main chat
+8. 案例 B(消息工具测试)。
+- 创建另一个分配给 OpenClaw 的议题。
+- 指令:"send `OPENCLAW_CASE_B_OK_` to main webchat via message tool, then comment same marker on issue, then mark done."
+- 验证两项:
+ - 议题上的标记评论
+ - 标记文本出现在 OpenClaw 主聊天中
-9. Case C (new session memory/skills test).
-- In OpenClaw, start `/new` session.
-- Ask it to create a new CLA issue in Paperclip with unique title `OPENCLAW_CASE_C_CREATED_`.
-- Verify in Paperclip UI that new issue exists.
+9. 案例 C(新会话记忆/技能测试)。
+- 在 OpenClaw 中,启动 `/new` 会话。
+- 要求它在 Paperclip 中创建一个具有唯一标题 `OPENCLAW_CASE_C_CREATED_` 的新 CLA 议题。
+- 在 Paperclip UI 中验证新议题是否存在。
-10. Watch logs during test (optional but helpful):
+10. 测试期间查看日志(可选但有帮助):
```bash
docker compose -f /tmp/openclaw-docker/docker-compose.yml -f /tmp/openclaw-docker/.paperclip-openclaw.override.yml logs -f openclaw-gateway
```
-11. Expected pass criteria.
-- Preflight: `openclaw_gateway` + non-placeholder token (`tokenLen >= 16`).
-- Pairing mode: stable `devicePrivateKeyPem` configured with device auth enabled (default path).
-- Case A: `done` + marker comment.
-- Case B: `done` + marker comment + main-chat message visible.
-- Case C: original task done and new issue created from `/new` session.
+11. 预期通过标准。
+- 预检:`openclaw_gateway` + 非占位符 token(`tokenLen >= 16`)。
+- 配对模式:已配置稳定的 `devicePrivateKeyPem` 且设备认证已启用(默认路径)。
+- 案例 A:`done` + 标记评论。
+- 案例 B:`done` + 标记评论 + 主聊天消息可见。
+- 案例 C:原始任务完成且从 `/new` 会话创建了新议题。
-If you want, I can also give you a single “observer mode” command that runs the stock smoke harness while you watch the same steps live in UI.
+如果需要,我还可以提供一个"观察模式"命令,在你通过 UI 实时观看相同步骤的同时运行默认冒烟测试套件。
diff --git a/doc/PRODUCT.md b/doc/PRODUCT.md
index f835889cca..c965806ade 100644
--- a/doc/PRODUCT.md
+++ b/doc/PRODUCT.md
@@ -1,47 +1,47 @@
-# Paperclip — Product Definition
+# Paperclip — 产品定义
-## What It Is
+## 是什么
-Paperclip is the control plane for autonomous AI companies. One instance of Paperclip can run multiple companies. A **company** is a first-order object.
+Paperclip 是自主 AI 公司的控制平面。一个 Paperclip 实例可以运行多家公司。**公司**是一个一等对象。
-## Core Concepts
+## 核心概念
-### Company
+### 公司
-A company has:
+一家公司具有:
-- A **goal** — the reason it exists ("Create the #1 AI note-taking app that does $1M MRR within 3 months")
-- **Employees** — every employee is an AI agent
-- **Org structure** — who reports to whom
-- **Revenue & expenses** — tracked at the company level
-- **Task hierarchy** — all work traces back to the company goal
+- 一个**目标** — 它存在的原因("创建排名第一的 AI 笔记应用,在3个月内达到100万美元月经常性收入")
+- **员工** — 每个员工都是一个 AI 代理
+- **组织结构** — 谁向谁汇报
+- **收入与支出** — 在公司层面跟踪
+- **任务层级** — 所有工作追溯到公司目标
-### Employees & Agents
+### 员工与代理
-Every employee is an agent. When you create a company, you start by defining the CEO, then build out from there.
+每个员工都是一个代理。创建公司时,你首先定义 CEO,然后从此展开。
-Each employee has:
+每个员工具有:
-- **Adapter type + config** — how this agent runs and what defines its identity/behavior. This is adapter-specific (e.g., an OpenClaw agent might use SOUL.md and HEARTBEAT.md files; a Claude Code agent might use CLAUDE.md; a bare script might use CLI args). Paperclip doesn't prescribe the format — the adapter does.
-- **Role & reporting** — their title, who they report to, who reports to them
-- **Capabilities description** — a short paragraph on what this agent does and when they're relevant (helps other agents discover who can help with what)
+- **适配器类型 + 配置** — 此代理如何运行以及什么定义了它的身份/行为。这是适配器特定的(例如,OpenClaw 代理可能使用 SOUL.md 和 HEARTBEAT.md 文件;Claude Code 代理可能使用 CLAUDE.md;裸脚本可能使用 CLI 参数)。Paperclip 不规定格式 — 适配器规定。
+- **角色与汇报关系** — 他们的职位、向谁汇报、谁向他们汇报
+- **能力描述** — 关于此代理做什么以及何时相关的简短段落(帮助其他代理发现谁能帮助什么)
-Example: A CEO agent's adapter config tells it to "review what your executives are doing, check company metrics, reprioritize if needed, assign new strategic initiatives" on each heartbeat. An engineer's config tells it to "check assigned tasks, pick the highest priority, and work it."
+示例:CEO 代理的适配器配置告诉它在每次心跳时"审查你的高管在做什么、检查公司指标、必要时重新排序优先级、分配新的战略举措"。工程师的配置告诉它"检查分配的任务、选择最高优先级的、执行它"。
-Then you define who reports to the CEO: a CTO managing programmers, a CMO managing the marketing team, and so on. Every agent in the tree gets their own adapter configuration.
+然后你定义谁向 CEO 汇报:管理程序员的 CTO、管理市场团队的 CMO,等等。树中的每个代理都有自己的适配器配置。
-### Agent Execution
+### 代理执行
-There are two fundamental modes for running an agent's heartbeat:
+运行代理心跳有两种基本模式:
-1. **Run a command** — Paperclip kicks off a process (shell command, Python script, etc.) and tracks it. The heartbeat is "execute this and monitor it."
-2. **Fire and forget a request** — Paperclip sends a webhook/API call to an externally running agent. The heartbeat is "notify this agent to wake up." (OpenClaw hooks work this way.)
+1. **运行命令** — Paperclip 启动一个进程(shell 命令、Python 脚本等)并跟踪它。心跳就是"执行这个并监控它"。
+2. **发射后不管的请求** — Paperclip 发送 webhook/API 调用给外部运行的代理。心跳就是"通知此代理醒来"(OpenClaw 钩子就是这样工作的。)
-We provide sensible defaults — a default agent that shells out to Claude Code or Codex with your configuration, remembers session IDs, runs basic scripts. But you can plug in anything.
+我们提供合理的默认值 — 一个默认代理,它调用 Claude Code 或 Codex,带上你的配置、记住会话 ID、运行基本脚本。但你可以接入任何东西。
-### Task Management
+### 任务管理
-Task management is hierarchical. At any moment, every piece of work must trace back to the company's top-level goal through a chain of parent tasks:
+任务管理是层级化的。在任何时刻,每一项工作都必须通过一系列父任务追溯到公司的顶层目标:
```
I am researching the Facebook ads Granola uses (current task)
@@ -52,95 +52,95 @@ I am researching the Facebook ads Granola uses (current task)
because → We're building the #1 AI note-taking app to $1M MRR in 3 months
```
-Tasks have parentage. Every task exists in service of a parent task, all the way up to the company goal. This is what keeps autonomous agents aligned — they can always answer "why am I doing this?"
+任务具有层级关系。每个任务都服务于一个父任务,一直追溯到公司目标。这就是保持自主代理对齐的方式 — 它们始终能回答"我为什么在做这件事?"
-More detailed task structure TBD.
+更详细的任务结构待定。
-## Principles
+## 原则
-1. **Unopinionated about how you run your agents.** Your agents could be OpenClaw bots, Python scripts, Node scripts, Claude Code sessions, Codex instances — we don't care. Paperclip defines the control plane for communication and provides utility infrastructure for heartbeats. It does not mandate an agent runtime.
+1. **对你如何运行代理不做限定。** 你的代理可以是 OpenClaw 机器人、Python 脚本、Node 脚本、Claude Code 会话、Codex 实例 — 我们不关心。Paperclip 定义通信的控制平面并提供心跳的基础设施。它不强制要求代理运行时。
-2. **Company is the unit of organization.** Everything lives under a company. One Paperclip instance, many companies.
+2. **公司是组织单位。** 所有东西都在公司下。一个 Paperclip 实例,多家公司。
-3. **Adapter config defines the agent.** Every agent has an adapter type and configuration that controls its identity and behavior. The minimum contract is just "be callable."
+3. **适配器配置定义代理。** 每个代理都有一个适配器类型和配置来控制其身份和行为。最低契约就是"可被调用"。
-4. **All work traces to the goal.** Hierarchical task management means nothing exists in isolation. If you can't explain why a task matters to the company goal, it shouldn't exist.
+4. **所有工作追溯到目标。** 层级化任务管理意味着没有任何东西是孤立存在的。如果你无法解释一个任务为什么对公司目标重要,它就不应该存在。
-5. **Control plane, not execution plane.** Paperclip orchestrates. Agents run wherever they run and phone home.
+5. **控制平面,而非执行平面。** Paperclip 进行编排。代理在任何地方运行,然后回报状态。
-## User Flow (Dream Scenario)
+## 用户流程(理想场景)
-1. Open Paperclip, create a new company
-2. Define the company's goal: "Create the #1 AI note-taking app, $1M MRR in 3 months"
-3. Create the CEO
- - Choose an adapter (e.g., process adapter for Claude Code, HTTP adapter for OpenClaw)
- - Configure the adapter (agent identity, loop behavior, execution settings)
- - CEO proposes strategic breakdown → board approves
-4. Define the CEO's reports: CTO, CMO, CFO, etc.
- - Each gets their own adapter config and role definition
-5. Define their reports: engineers under CTO, marketers under CMO, etc.
-6. Set budgets, define initial strategic tasks
-7. Hit go — agents start their heartbeats and the company runs
+1. 打开 Paperclip,创建一家新公司
+2. 定义公司目标:"创建排名第一的 AI 笔记应用,3个月内达到100万美元月经常性收入"
+3. 创建 CEO
+ - 选择一个适配器(例如,用于 Claude Code 的进程适配器,用于 OpenClaw 的 HTTP 适配器)
+ - 配置适配器(代理身份、循环行为、执行设置)
+ - CEO 提出战略分解 → 董事会批准
+4. 定义 CEO 的下属:CTO、CMO、CFO 等
+ - 每人获得自己的适配器配置和角色定义
+5. 定义他们的下属:CTO 下的工程师、CMO 下的市场人员等
+6. 设置预算,定义初始战略任务
+7. 启动 — 代理开始心跳循环,公司运转起来
-## Guidelines
+## 准则
-There are two runtime modes Paperclip must support:
+Paperclip 必须支持两种运行模式:
-- `local_trusted` (default): single-user local trusted deployment with no login friction
-- `authenticated`: login-required mode that supports both private-network and public deployment exposure policies
+- `local_trusted`(默认):单用户本地可信部署,无登录摩擦
+- `authenticated`:需要登录的模式,支持私有网络和公共部署暴露策略
-Canonical mode design and command expectations live in `doc/DEPLOYMENT-MODES.md`.
+规范模式设计和命令期望详见 `doc/DEPLOYMENT-MODES.md`。
-## Further Detail
+## 更多详情
-See [SPEC.md](./SPEC.md) for the full technical specification and [TASKS.md](./TASKS.md) for the task management data model.
+完整技术规范参见 [SPEC.md](./SPEC.md),任务管理数据模型参见 [TASKS.md](./TASKS.md)。
---
-Paperclip’s core identity is a **control plane for autonomous AI companies**, centered on **companies, org charts, goals, issues/comments, heartbeats, budgets, approvals, and board governance**. The public docs are also explicit about the current boundaries: **tasks/comments are the built-in communication model**, Paperclip is **not a chatbot**, and it is **not a code review tool**. The roadmap already points toward **easier onboarding, cloud agents, easier agent configuration, plugins, better docs, and ClipMart/ClipHub-style reusable companies/templates**.
+Paperclip 的核心定位是**自主 AI 公司的控制平面**,围绕**公司、组织结构图、目标、议题/评论、心跳、预算、审批和董事会治理**。公开文档也明确了当前的边界:**任务/评论是内置的通信模型**,Paperclip **不是聊天机器人**,也**不是代码审查工具**。路线图已指向**更简便的入门流程、云端代理、更简便的代理配置、插件、更好的文档以及 ClipMart/ClipHub 风格的可复用公司/模板**。
-## What Paperclip should do vs. not do
+## Paperclip 应该做什么与不应该做什么
-**Do**
+**应该做**
-- Stay **board-level and company-level**. Users should manage goals, orgs, budgets, approvals, and outputs.
-- Make the first five minutes feel magical: install, answer a few questions, see a CEO do something real.
-- Keep work anchored to **issues/comments/projects/goals**, even if the surface feels conversational.
-- Treat **agency / internal team / startup** as the same underlying abstraction with different templates and labels.
-- Make outputs first-class: files, docs, reports, previews, links, screenshots.
-- Provide **hooks into engineering workflows**: worktrees, preview servers, PR links, external review tools.
-- Use **plugins** for edge cases like rich chat, knowledge bases, doc editors, custom tracing.
+- 保持**董事会级和公司级**定位。用户应管理目标、组织、预算、审批和产出。
+- 让最初五分钟感觉神奇:安装、回答几个问题、看到 CEO 做了一些真实的事情。
+- 保持工作锚定在**议题/评论/项目/目标**上,即使界面感觉像对话。
+- 将**代理公司/内部团队/创业公司**视为相同的底层抽象,使用不同的模板和标签。
+- 让产出成为一等公民:文件、文档、报告、预览、链接、截图。
+- 提供**对接工程工作流的钩子**:worktree、预览服务器、PR 链接、外部审查工具。
+- 使用**插件**处理边缘场景,如富聊天、知识库、文档编辑器、自定义追踪。
-**Do not**
+**不应该做**
-- Do not make the core product a general chat app. The current product definition is explicitly task/comment-centric and “not a chatbot,” and that boundary is valuable.
-- Do not build a complete Jira/GitHub replacement. The repo/docs already position Paperclip as organization orchestration, not focused on pull-request review.
-- Do not build enterprise-grade RBAC first. The current V1 spec still treats multi-board governance and fine-grained human permissions as out of scope, so the first multi-user version should be coarse and company-scoped.
-- Do not lead with raw bash logs and transcripts. Default view should be human-readable intent/progress, with raw detail beneath.
-- Do not force users to understand provider/API-key plumbing unless absolutely necessary. There are active onboarding/auth issues already; friction here is clearly real.
+- 不要让核心产品成为通用聊天应用。当前产品定义明确以任务/评论为中心且"不是聊天机器人",这个边界很有价值。
+- 不要构建完整的 Jira/GitHub 替代品。仓库/文档已将 Paperclip 定位为组织编排,而非专注于拉取请求审查。
+- 不要先构建企业级 RBAC。当前 V1 规范仍将多董事会治理和细粒度人类权限视为不在范围内,所以第一个多用户版本应该是粗粒度的、以公司为范围的。
+- 不要以原始 bash 日志和记录作为主导。默认视图应该是人类可读的意图/进度,原始细节在下层。
+- 除非绝对必要,不要强迫用户理解提供商/API 密钥的配置细节。已经存在活跃的入门/认证问题;这里的摩擦显然是真实的。
-## Specific design goals
+## 具体设计目标
-1. **Time-to-first-success under 5 minutes**
- A fresh user should go from install to “my CEO completed a first task” in one sitting.
+1. **首次成功时间在5分钟以内**
+ 新用户应该能在一个会话中从安装到"我的 CEO 完成了第一个任务"。
-2. **Board-level abstraction always wins**
- The default UI should answer: what is the company doing, who is doing it, why does it matter, what did it cost, and what needs my approval.
+2. **董事会级抽象始终优先**
+ 默认 UI 应该回答:公司在做什么、谁在做、为什么重要、花费多少、什么需要我的批准。
-3. **Conversation stays attached to work objects**
- “Chat with CEO” should still resolve to strategy threads, decisions, tasks, or approvals.
+3. **对话始终附着在工作对象上**
+ "与 CEO 聊天"仍应解析为策略线程、决策、任务或审批。
-4. **Progressive disclosure**
- Top layer: human-readable summary. Middle layer: checklist/steps/artifacts. Bottom layer: raw logs/tool calls/transcript.
+4. **渐进式披露**
+ 顶层:人类可读的摘要。中间层:检查清单/步骤/工件。底层:原始日志/工具调用/记录。
-5. **Output-first**
- Work is not done until the user can see the result: file, document, preview link, screenshot, plan, or PR.
+5. **产出优先**
+ 工作在用户看到结果之前不算完成:文件、文档、预览链接、截图、计划或 PR。
-6. **Local-first, cloud-ready**
- The mental model should not change between local solo use and shared/private or public/cloud deployment.
+6. **本地优先,云端就绪**
+ 心智模型在本地单独使用和共享/私有或公共/云端部署之间不应改变。
-7. **Safe autonomy**
- Auto mode is allowed; hidden token burn is not.
+7. **安全的自主性**
+ 允许自动模式;不允许隐藏的 token 消耗。
-8. **Thin core, rich edges**
- Put optional chat, knowledge, and special surfaces into plugins/extensions rather than bloating the control plane.
+8. **精简核心,丰富边缘**
+ 将可选聊天、知识库和特殊界面放入插件/扩展中,而非膨胀控制平面。
diff --git a/doc/PUBLISHING.md b/doc/PUBLISHING.md
index 32e4b1312a..9040f99d4c 100644
--- a/doc/PUBLISHING.md
+++ b/doc/PUBLISHING.md
@@ -1,148 +1,148 @@
-# Publishing to npm
+# 发布到 npm
-Low-level reference for how Paperclip packages are prepared and published to npm.
+关于 Paperclip 包如何准备和发布到 npm 的底层参考。
-For the maintainer workflow, use [doc/RELEASING.md](RELEASING.md). This document focuses on packaging internals.
+维护者工作流请使用 [doc/RELEASING.md](RELEASING.md)。本文档专注于打包内部细节。
-## Current Release Entry Points
+## 当前发布入口点
-Use these scripts:
+使用以下脚本:
-- [`scripts/release.sh`](../scripts/release.sh) for canary and stable publish flows
-- [`scripts/create-github-release.sh`](../scripts/create-github-release.sh) after pushing a stable tag
-- [`scripts/rollback-latest.sh`](../scripts/rollback-latest.sh) to repoint `latest`
-- [`scripts/build-npm.sh`](../scripts/build-npm.sh) for the CLI packaging build
+- [`scripts/release.sh`](../scripts/release.sh) 用于 canary 和稳定版发布流程
+- [`scripts/create-github-release.sh`](../scripts/create-github-release.sh) 推送稳定版标签后使用
+- [`scripts/rollback-latest.sh`](../scripts/rollback-latest.sh) 用于重新指向 `latest`
+- [`scripts/build-npm.sh`](../scripts/build-npm.sh) 用于 CLI 打包构建
-Paperclip no longer uses release branches or Changesets for publishing.
+Paperclip 不再使用发布分支或 Changesets 进行发布。
-## Why the CLI needs special packaging
+## 为什么 CLI 需要特殊打包
-The CLI package, `paperclipai`, imports code from workspace packages such as:
+CLI 包 `paperclipai` 从工作区包导入代码,例如:
- `@paperclipai/server`
- `@paperclipai/db`
- `@paperclipai/shared`
-- adapter packages under `packages/adapters/`
+- `packages/adapters/` 下的适配器包
-Those workspace references are valid in development but not in a publishable npm package. The release flow rewrites versions temporarily, then builds a publishable CLI bundle.
+这些工作区引用在开发中有效,但在可发布的 npm 包中无效。发布流程会临时重写版本,然后构建可发布的 CLI 包。
## `build-npm.sh`
-Run:
+运行:
```bash
./scripts/build-npm.sh
```
-This script:
+此脚本:
-1. runs the forbidden token check unless `--skip-checks` is supplied
-2. runs `pnpm -r typecheck`
-3. bundles the CLI entrypoint with esbuild into `cli/dist/index.js`
-4. verifies the bundled entrypoint with `node --check`
-5. rewrites `cli/package.json` into a publishable npm manifest and stores the dev copy as `cli/package.dev.json`
-6. copies the repo `README.md` into `cli/README.md` for npm metadata
+1. 运行禁止 token 检查(除非提供 `--skip-checks`)
+2. 运行 `pnpm -r typecheck`
+3. 使用 esbuild 将 CLI 入口点打包到 `cli/dist/index.js`
+4. 使用 `node --check` 验证打包的入口点
+5. 将 `cli/package.json` 重写为可发布的 npm 清单,并将开发副本存储为 `cli/package.dev.json`
+6. 将仓库 `README.md` 复制到 `cli/README.md` 用于 npm 元数据
-After the release script exits, the dev manifest and temporary files are restored automatically.
+发布脚本退出后,开发清单和临时文件会自动恢复。
-## Package discovery and versioning
+## 包发现和版本管理
-Public packages are discovered from:
+公共包从以下位置发现:
- `packages/`
- `server/`
- `ui/`
- `cli/`
-The version rewrite step now uses [`scripts/release-package-map.mjs`](../scripts/release-package-map.mjs), which:
+版本重写步骤现在使用 [`scripts/release-package-map.mjs`](../scripts/release-package-map.mjs),它:
-- finds all public packages
-- sorts them topologically by internal dependencies
-- rewrites each package version to the target release version
-- rewrites internal `workspace:*` dependency references to the exact target version
-- updates the CLI's displayed version string
+- 查找所有公共包
+- 按内部依赖关系进行拓扑排序
+- 将每个包版本重写为目标发布版本
+- 将内部 `workspace:*` 依赖引用重写为精确的目标版本
+- 更新 CLI 的显示版本字符串
-Those rewrites are temporary. The working tree is restored after publish or dry-run.
+这些重写是临时的。工作树在发布或试运行后恢复。
-## `@paperclipai/ui` packaging
+## `@paperclipai/ui` 打包
-The UI package publishes prebuilt static assets, not the source workspace.
+UI 包发布预构建的静态资源,而非源工作区。
-The `ui` package uses [`scripts/generate-ui-package-json.mjs`](../scripts/generate-ui-package-json.mjs) during `prepack` to swap in a lean publish manifest that:
+`ui` 包在 `prepack` 期间使用 [`scripts/generate-ui-package-json.mjs`](../scripts/generate-ui-package-json.mjs) 替换为一个精简的发布清单,该清单:
-- keeps the release-managed `name` and `version`
-- publishes only `dist/`
-- omits the source-only dependency graph from downstream installs
+- 保留发布管理的 `name` 和 `version`
+- 仅发布 `dist/`
+- 从下游安装中省略仅用于源码的依赖图
-After packing or publishing, `postpack` restores the development manifest automatically.
+打包或发布后,`postpack` 自动恢复开发清单。
-## Version formats
+## 版本格式
-Paperclip uses calendar versions:
+Paperclip 使用日历版本:
-- stable: `YYYY.MDD.P`
-- canary: `YYYY.MDD.P-canary.N`
+- 稳定版:`YYYY.MDD.P`
+- canary 版:`YYYY.MDD.P-canary.N`
-Examples:
+示例:
-- stable: `2026.318.0`
-- canary: `2026.318.1-canary.2`
+- 稳定版:`2026.318.0`
+- canary 版:`2026.318.1-canary.2`
-## Publish model
+## 发布模型
### Canary
-Canaries publish under the npm dist-tag `canary`.
+canary 在 npm dist-tag `canary` 下发布。
-Example:
+示例:
- `paperclipai@2026.318.1-canary.2`
-This keeps the default install path unchanged while allowing explicit installs with:
+这保持默认安装路径不变,同时允许通过以下方式显式安装:
```bash
npx paperclipai@canary onboard
```
-### Stable
+### 稳定版
-Stable publishes use the npm dist-tag `latest`.
+稳定版使用 npm dist-tag `latest` 发布。
-Example:
+示例:
- `paperclipai@2026.318.0`
-Stable publishes do not create a release commit. Instead:
+稳定版发布不创建发布提交。而是:
-- package versions are rewritten temporarily
-- packages are published from the chosen source commit
-- git tag `vYYYY.MDD.P` points at that original commit
+- 包版本被临时重写
+- 包从选定的源提交发布
+- git 标签 `vYYYY.MDD.P` 指向该原始提交
-## Trusted publishing
+## 可信发布
-The intended CI model is npm trusted publishing through GitHub OIDC.
+预期的 CI 模型是通过 GitHub OIDC 的 npm 可信发布。
-That means:
+这意味着:
-- no long-lived `NPM_TOKEN` in repository secrets
-- GitHub Actions obtains short-lived publish credentials
-- trusted publisher rules are configured per workflow file
+- 仓库密钥中没有长期有效的 `NPM_TOKEN`
+- GitHub Actions 获取短期发布凭据
+- 可信发布规则按工作流文件配置
-See [doc/RELEASE-AUTOMATION-SETUP.md](RELEASE-AUTOMATION-SETUP.md) for the GitHub/npm setup steps.
+GitHub/npm 设置步骤参见 [doc/RELEASE-AUTOMATION-SETUP.md](RELEASE-AUTOMATION-SETUP.md)。
-## Rollback model
+## 回滚模型
-Rollback does not unpublish anything.
+回滚不会取消发布任何内容。
-It repoints the `latest` dist-tag to a prior stable version:
+它将 `latest` dist-tag 重新指向先前的稳定版:
```bash
./scripts/rollback-latest.sh 2026.318.0
```
-This is the fastest way to restore the default install path if a stable release is bad.
+如果稳定版有问题,这是恢复默认安装路径的最快方式。
-## Related Files
+## 相关文件
- [`scripts/build-npm.sh`](../scripts/build-npm.sh)
- [`scripts/generate-npm-package-json.mjs`](../scripts/generate-npm-package-json.mjs)
diff --git a/doc/README-draft.md b/doc/README-draft.md
index a8a65d3b76..f9096de986 100644
--- a/doc/README-draft.md
+++ b/doc/README-draft.md
@@ -1,78 +1,78 @@
-# Instructions for writing the README.md
+# 编写 README.md 的说明
-The readme should be visually interesting, to the point, not too long.
-Use the copy from the website in cases where we need some.
+README 应该视觉上有趣、直奔主题、不要太长。
+在需要文案的地方使用网站上的文案。
-- gives the pitch why, e.g. from the homepage.
+- 给出理由,例如来自首页的宣传语。
-## Outline
+## 大纲
-- image header up top
+- 顶部的图片头部
- Paperclip
-- Manage autonomous AI Businesses
-- The open-source AI-agent orchestrator teams of agents that run companies
+- 管理自主 AI 业务
+- 开源 AI 代理编排器,协调代理团队运营公司
-- a video
+- 一个视频
-# What is it
+# 它是什么
-Paperclip is a node server & UI that orchestrates a team of agents to run businesses.
+Paperclip 是一个 Node 服务器和 UI,协调代理团队来运营企业。
-Bring-your-own agents, assign goals, and track your agent's work and costs.
+自带你的代理,分配目标,跟踪你的代理的工作和成本。
-It looks like a task manager but has specialized skills and agent coordination
+它看起来像一个任务管理器,但具有专业技能和代理协调能力
-**It's high taste, and feels good to use**
+**它品味高端,使用起来感觉很好**
-# Paperclip is right for you if:
+# Paperclip 适合你,如果:
-- You want to build autonomous companies
-- You want to coordinate many different types agents (OpenClaw, Codex, Claude, Cursor, etc.) to collaborate towards a common goal
-- You have 20 simultaneous Claude Code terminals open (and lose track of what everyone is working on)
-- You want to let your agents run autonomously 24/7, but still audit their work and chime in when needed
-- You want to monitor costs
-- You want a process for managing your agents that feels like using a task manager
-- You want to manage your autonomous businesses from your phone
+- 你想构建自主公司
+- 你想协调多种不同类型的代理(OpenClaw、Codex、Claude、Cursor 等)朝共同目标协作
+- 你同时打开了20个 Claude Code 终端(并且搞不清每个人在做什么)
+- 你想让你的代理全天候自主运行,但仍然审核它们的工作并在需要时介入
+- 你想监控成本
+- 你想要一个管理代理的流程,感觉像使用任务管理器
+- 你想从手机管理你的自主业务
-# What is not
+# 它不是什么
-Paperclip is not:
+Paperclip 不是:
-- a code review tool
-- opinionated about what agent you use
+- 代码审查工具
+- 对你使用什么代理有主见的
-# the problem
+# 问题
-If you want to be maximally effective with agents, you need to
+如果你想最大化利用代理的效率,你需要
-# quickstart
+# 快速入门
-# faq
+# 常见问题
-# comparison
+# 对比
-# contributing
+# 贡献
-# community
+# 社区
-# license
+# 许可证
-# footer
+# 页脚
-## Examples:
+## 示例:
-- https://github.com/klawsh/klaw.sh - nice header, nice tables
- - what is it
- - the problem
- - quickstart
- - faq
- - comparison
- - contributing
- - community
- - license
- - footer
-- https://github.com/nearai/ironclaw - nice header
- - philosophy
-- https://github.com/TinyAGI/tinyclaw - nice header, nice video
-- https://github.com/ryoppippi/ccusage - nice header,
-- https://github.com/can1357/oh-my-pi - a little long
+- https://github.com/klawsh/klaw.sh - 漂亮的头部,漂亮的表格
+ - 它是什么
+ - 问题
+ - 快速入门
+ - 常见问题
+ - 对比
+ - 贡献
+ - 社区
+ - 许可证
+ - 页脚
+- https://github.com/nearai/ironclaw - 漂亮的头部
+ - 理念
+- https://github.com/TinyAGI/tinyclaw - 漂亮的头部,漂亮的视频
+- https://github.com/ryoppippi/ccusage - 漂亮的头部
+- https://github.com/can1357/oh-my-pi - 有点长
diff --git a/doc/RELEASE-AUTOMATION-SETUP.md b/doc/RELEASE-AUTOMATION-SETUP.md
index 25982892d3..da057c77f5 100644
--- a/doc/RELEASE-AUTOMATION-SETUP.md
+++ b/doc/RELEASE-AUTOMATION-SETUP.md
@@ -1,176 +1,176 @@
-# Release Automation Setup
+# 发布自动化设置
-This document covers the GitHub and npm setup required for the current Paperclip release model:
+本文档涵盖了当前 Paperclip 发布模型所需的 GitHub 和 npm 设置:
-- automatic canaries from `master`
-- manual stable promotion from a chosen source ref
-- npm trusted publishing via GitHub OIDC
-- protected release infrastructure in a public repository
+- 从 `master` 自动发布 canary
+- 从选定源引用手动提升稳定版
+- 通过 GitHub OIDC 的 npm 可信发布
+- 公共仓库中受保护的发布基础设施
-Repo-side files that depend on this setup:
+依赖于此设置的仓库文件:
- `.github/workflows/release.yml`
- `.github/CODEOWNERS`
-Note:
+注意:
-- the release workflows intentionally use `pnpm install --no-frozen-lockfile`
-- this matches the repo's current policy where `pnpm-lock.yaml` is refreshed by GitHub automation after manifest changes land on `master`
-- the publish jobs then restore `pnpm-lock.yaml` before running `scripts/release.sh`, so the release script still sees a clean worktree
+- 发布工作流有意使用 `pnpm install --no-frozen-lockfile`
+- 这与仓库当前的策略一致,即 `pnpm-lock.yaml` 在清单变更合并到 `master` 后由 GitHub 自动化刷新
+- 发布作业然后在运行 `scripts/release.sh` 之前恢复 `pnpm-lock.yaml`,因此发布脚本仍然看到干净的工作树
-## 1. Merge the Repo Changes First
+## 1. 先合并仓库变更
-Before touching GitHub or npm settings, merge the release automation code so the referenced workflow filenames already exist on the default branch.
+在修改 GitHub 或 npm 设置之前,先合并发布自动化代码,使引用的工作流文件名已存在于默认分支上。
-Required files:
+必需文件:
- `.github/workflows/release.yml`
- `.github/CODEOWNERS`
-## 2. Configure npm Trusted Publishing
+## 2. 配置 npm 可信发布
-Do this for every public package that Paperclip publishes.
+对 Paperclip 发布的每个公共包执行此操作。
-At minimum that includes:
+至少包括:
- `paperclipai`
- `@paperclipai/server`
- `@paperclipai/ui`
-- public packages under `packages/`
+- `packages/` 下的公共包
-### 2.1. In npm, open each package settings page
+### 2.1. 在 npm 中打开每个包的设置页面
-For each package:
+对于每个包:
-1. open npm as an owner of the package
-2. go to the package settings / publishing access area
-3. add a trusted publisher for the GitHub repository `paperclipai/paperclip`
+1. 以包所有者身份打开 npm
+2. 进入包设置/发布访问区域
+3. 为 GitHub 仓库 `paperclipai/paperclip` 添加可信发布者
-### 2.2. Add one trusted publisher entry per package
+### 2.2. 为每个包添加一个可信发布者条目
-npm currently allows one trusted publisher configuration per package.
+npm 目前允许每个包一个可信发布者配置。
-Configure:
+配置:
-- workflow: `.github/workflows/release.yml`
+- 工作流:`.github/workflows/release.yml`
-Repository:
+仓库:
- `paperclipai/paperclip`
-Environment name:
+环境名称:
-- leave the npm trusted-publisher environment field blank
+- 将 npm 可信发布者环境字段留空
-Why:
+原因:
-- the single `release.yml` workflow handles both canary and stable publishing
-- GitHub environments `npm-canary` and `npm-stable` still enforce different approval rules on the GitHub side
+- 单个 `release.yml` 工作流同时处理 canary 和稳定版发布
+- GitHub 环境 `npm-canary` 和 `npm-stable` 仍在 GitHub 端实施不同的审批规则
-### 2.3. Verify trusted publishing before removing old auth
+### 2.3. 在移除旧认证之前验证可信发布
-After the workflows are live:
+工作流上线后:
-1. run a canary publish
-2. confirm npm publish succeeds without any `NPM_TOKEN`
-3. run a stable dry-run
-4. run one real stable publish
+1. 运行一次 canary 发布
+2. 确认 npm 发布成功,无需任何 `NPM_TOKEN`
+3. 运行稳定版试运行
+4. 运行一次真实的稳定版发布
-Only after that should you remove old token-based access.
+只有在此之后才应移除旧的基于 token 的访问。
-## 3. Remove Legacy npm Tokens
+## 3. 移除遗留 npm Token
-After trusted publishing works:
+可信发布正常工作后:
-1. revoke any repository or organization `NPM_TOKEN` secrets used for publish
-2. revoke any personal automation token that used to publish Paperclip
-3. if npm offers a package-level setting to restrict publishing to trusted publishers, enable it
+1. 撤销任何用于发布的仓库或组织 `NPM_TOKEN` 密钥
+2. 撤销任何曾用于发布 Paperclip 的个人自动化 token
+3. 如果 npm 提供了限制仅通过可信发布者发布的包级设置,请启用它
-Goal:
+目标:
-- no long-lived npm publishing token should remain in GitHub Actions
+- GitHub Actions 中不应残留长期有效的 npm 发布 token
-## 4. Create GitHub Environments
+## 4. 创建 GitHub 环境
-Create two environments in the GitHub repository:
+在 GitHub 仓库中创建两个环境:
- `npm-canary`
- `npm-stable`
-Path:
+路径:
-1. GitHub repository
+1. GitHub 仓库
2. `Settings`
3. `Environments`
4. `New environment`
-## 5. Configure `npm-canary`
+## 5. 配置 `npm-canary`
-Recommended settings for `npm-canary`:
+`npm-canary` 的推荐设置:
-- environment name: `npm-canary`
-- required reviewers: none
-- wait timer: none
-- deployment branches and tags:
- - selected branches only
- - allow `master`
+- 环境名称:`npm-canary`
+- 必需审查者:无
+- 等待计时器:无
+- 部署分支和标签:
+ - 仅选定分支
+ - 允许 `master`
-Reasoning:
+原因:
-- every push to `master` should be able to publish a canary automatically
-- no human approval should be required for canaries
+- 每次推送到 `master` 都应该能自动发布 canary
+- canary 不应需要人工审批
-## 6. Configure `npm-stable`
+## 6. 配置 `npm-stable`
-Recommended settings for `npm-stable`:
+`npm-stable` 的推荐设置:
-- environment name: `npm-stable`
-- required reviewers: at least one maintainer other than the person triggering the workflow when possible
-- prevent self-review: enabled
-- admin bypass: disabled if your team can tolerate it
-- wait timer: optional
-- deployment branches and tags:
- - selected branches only
- - allow `master`
+- 环境名称:`npm-stable`
+- 必需审查者:尽可能至少一名非触发工作流本人的维护者
+- 防止自我审查:启用
+- 管理员绕过:如果你的团队能接受,则禁用
+- 等待计时器:可选
+- 部署分支和标签:
+ - 仅选定分支
+ - 允许 `master`
-Reasoning:
+原因:
-- stable publishes should require an explicit human approval gate
-- the workflow is manual, but the environment should still be the real control point
+- 稳定版发布应需要明确的人工审批门控
+- 工作流是手动的,但环境仍应是真正的控制点
-## 7. Protect `master`
+## 7. 保护 `master`
-Open the branch protection settings for `master`.
+打开 `master` 的分支保护设置。
-Recommended rules:
+推荐规则:
-1. require pull requests before merging
-2. require status checks to pass before merging
-3. require review from code owners
-4. dismiss stale approvals when new commits are pushed
-5. restrict who can push directly to `master`
+1. 合并前需要拉取请求
+2. 合并前需要状态检查通过
+3. 需要代码所有者审查
+4. 新提交推送时取消过期审批
+5. 限制谁可以直接推送到 `master`
-At minimum, make sure workflow and release script changes cannot land without review.
+至少确保工作流和发布脚本的变更在没有审查的情况下无法合并。
-## 8. Enforce CODEOWNERS Review
+## 8. 强制 CODEOWNERS 审查
-This repo now includes `.github/CODEOWNERS`, but GitHub only enforces it if branch protection requires code owner reviews.
+此仓库现在包含 `.github/CODEOWNERS`,但 GitHub 只有在分支保护要求代码所有者审查时才会强制执行。
-In branch protection for `master`, enable:
+在 `master` 的分支保护中启用:
- `Require review from Code Owners`
-Then verify the owner entries are correct for your actual maintainer set.
+然后验证所有者条目对你的实际维护者团队是正确的。
-Current file:
+当前文件:
- `.github/CODEOWNERS`
-If `@cryppadotta` is not the right reviewer identity in the public repo, change it before enabling enforcement.
+如果 `@cryppadotta` 不是公共仓库中正确的审查者身份,在启用强制执行之前更改它。
-## 9. Protect Release Infrastructure Specifically
+## 9. 专门保护发布基础设施
-These files should always trigger code owner review:
+以下文件应始终触发代码所有者审查:
- `.github/workflows/release.yml`
- `scripts/release.sh`
@@ -181,101 +181,101 @@ These files should always trigger code owner review:
- `doc/RELEASING.md`
- `doc/PUBLISHING.md`
-If you want stronger controls, add a repository ruleset that explicitly blocks direct pushes to:
+如果你想要更强的控制,添加仓库规则集,明确阻止对以下路径的直接推送:
- `.github/workflows/**`
- `scripts/release*`
-## 10. Do Not Store a Claude Token in GitHub Actions
+## 10. 不要在 GitHub Actions 中存储 Claude Token
-Do not add a personal Claude or Anthropic token for automatic changelog generation.
+不要添加个人 Claude 或 Anthropic token 用于自动变更日志生成。
-Recommended policy:
+推荐策略:
-- stable changelog generation happens locally from a trusted maintainer machine
-- canaries never generate changelogs
+- 稳定版变更日志生成在可信维护者机器上本地完成
+- canary 永远不生成变更日志
-This keeps LLM spending intentional and avoids a high-value token sitting in Actions.
+这使 LLM 支出保持有意控制,并避免高价值 token 存放在 Actions 中。
-## 11. Verify the Canary Workflow
+## 11. 验证 Canary 工作流
-After setup:
+设置完成后:
-1. merge a harmless commit to `master`
-2. open the `Release` workflow run triggered by that push
-3. confirm it passes verification
-4. confirm publish succeeds under the `npm-canary` environment
-5. confirm npm now shows a new `canary` release
-6. confirm a git tag named `canary/vYYYY.MDD.P-canary.N` was pushed
+1. 将一个无害的提交合并到 `master`
+2. 打开该推送触发的 `Release` 工作流运行
+3. 确认验证通过
+4. 确认在 `npm-canary` 环境下发布成功
+5. 确认 npm 现在显示一个新的 `canary` 发布
+6. 确认推送了名为 `canary/vYYYY.MDD.P-canary.N` 的 git 标签
-Install-path check:
+安装路径检查:
```bash
npx paperclipai@canary onboard
```
-## 12. Verify the Stable Workflow
+## 12. 验证稳定版工作流
-After at least one good canary exists:
+在至少一个好的 canary 存在之后:
-1. resolve the target stable version with `./scripts/release.sh stable --date YYYY-MM-DD --print-version`
-2. prepare `releases/vYYYY.MDD.P.md` on the source commit you want to promote
-3. open `Actions` -> `Release`
-4. run it with:
- - `source_ref`: the tested commit SHA or canary tag source commit
- - `stable_date`: leave blank or set the intended UTC date like `2026-03-18`
- do not enter a version like `2026.318.0`; the workflow computes that from the date
- - `dry_run`: `true`
-5. confirm the dry-run succeeds
-6. rerun with `dry_run: false`
-7. approve the `npm-stable` environment when prompted
-8. confirm npm `latest` points to the new stable version
-9. confirm git tag `vYYYY.MDD.P` exists
-10. confirm the GitHub Release was created
+1. 使用 `./scripts/release.sh stable --date YYYY-MM-DD --print-version` 解析目标稳定版本
+2. 在你想要提升的源提交上准备 `releases/vYYYY.MDD.P.md`
+3. 打开 `Actions` -> `Release`
+4. 使用以下参数运行:
+ - `source_ref`:已测试的提交 SHA 或 canary 标签的源提交
+ - `stable_date`:留空或设置预期的 UTC 日期如 `2026-03-18`
+ 不要输入版本如 `2026.318.0`;工作流会从日期计算版本
+ - `dry_run`:`true`
+5. 确认试运行成功
+6. 使用 `dry_run: false` 重新运行
+7. 在提示时批准 `npm-stable` 环境
+8. 确认 npm `latest` 指向新的稳定版本
+9. 确认 git 标签 `vYYYY.MDD.P` 存在
+10. 确认 GitHub Release 已创建
-Implementation note:
+实现说明:
-- the GitHub Actions stable workflow calls `create-github-release.sh` with `PUBLISH_REMOTE=origin`
-- local maintainer usage can still pass `PUBLISH_REMOTE=public-gh` explicitly when needed
+- GitHub Actions 稳定版工作流使用 `PUBLISH_REMOTE=origin` 调用 `create-github-release.sh`
+- 本地维护者使用时仍可在需要时显式传递 `PUBLISH_REMOTE=public-gh`
-## 13. Suggested Maintainer Policy
+## 13. 建议的维护者策略
-Use this policy going forward:
+今后使用此策略:
-- canaries are automatic and cheap
-- stables are manual and approved
-- only stables get public notes and announcements
-- release notes are committed before stable publish
-- rollback uses `npm dist-tag`, not unpublish
+- canary 是自动的且成本低
+- 稳定版是手动的且需审批
+- 只有稳定版获得公开说明和公告
+- 发布说明在稳定版发布前提交
+- 回滚使用 `npm dist-tag`,而非取消发布
-## 14. Troubleshooting
+## 14. 故障排除
-### Trusted publishing fails with an auth error
+### 可信发布因认证错误失败
-Check:
+检查:
-1. the workflow filename on GitHub exactly matches the filename configured in npm
-2. the package has the trusted publisher entry for the correct repository
-3. the job has `id-token: write`
-4. the job is running from the expected repository, not a fork
+1. GitHub 上的工作流文件名与 npm 中配置的文件名完全匹配
+2. 包具有正确仓库的可信发布者条目
+3. 作业具有 `id-token: write`
+4. 作业从预期的仓库运行,而非 fork
-### Stable workflow runs but never asks for approval
+### 稳定版工作流运行但从不要求审批
-Check:
+检查:
-1. the `publish` job uses environment `npm-stable`
-2. the environment actually has required reviewers configured
-3. the workflow is running in the canonical repository, not a fork
+1. `publish` 作业使用环境 `npm-stable`
+2. 环境确实配置了必需审查者
+3. 工作流在规范仓库中运行,而非 fork
-### CODEOWNERS does not trigger
+### CODEOWNERS 不触发
-Check:
+检查:
-1. `.github/CODEOWNERS` is on the default branch
-2. branch protection on `master` requires code owner review
-3. the owner identities in the file are valid reviewers with repository access
+1. `.github/CODEOWNERS` 在默认分支上
+2. `master` 上的分支保护要求代码所有者审查
+3. 文件中的所有者身份是具有仓库访问权限的有效审查者
-## Related Docs
+## 相关文档
- [doc/RELEASING.md](RELEASING.md)
- [doc/PUBLISHING.md](PUBLISHING.md)
diff --git a/doc/RELEASING.md b/doc/RELEASING.md
index 61d094c4df..8ff528410b 100644
--- a/doc/RELEASING.md
+++ b/doc/RELEASING.md
@@ -1,132 +1,132 @@
-# Releasing Paperclip
+# 发布 Paperclip
-Maintainer runbook for shipping Paperclip across npm, GitHub, and the website-facing changelog surface.
+Paperclip 在 npm、GitHub 和面向网站的变更日志中的发布维护手册。
-The release model is now commit-driven:
+发布模型现在是提交驱动的:
-1. Every push to `master` publishes a canary automatically.
-2. Stable releases are manually promoted from a chosen tested commit or canary tag.
-3. Stable release notes live in `releases/vYYYY.MDD.P.md`.
-4. Only stable releases get GitHub Releases.
+1. 每次推送到 `master` 都会自动发布一个 canary 版本。
+2. 稳定版本从选定的已测试提交或 canary 标签手动提升。
+3. 稳定版本发布说明位于 `releases/vYYYY.MDD.P.md`。
+4. 只有稳定版本才会创建 GitHub Releases。
-## Versioning Model
+## 版本模型
-Paperclip uses calendar versions that still fit semver syntax:
+Paperclip 使用符合 semver 语法的日历版本:
-- stable: `YYYY.MDD.P`
-- canary: `YYYY.MDD.P-canary.N`
+- 稳定版:`YYYY.MDD.P`
+- canary 版:`YYYY.MDD.P-canary.N`
-Examples:
+示例:
-- first stable on March 18, 2026: `2026.318.0`
-- second stable on March 18, 2026: `2026.318.1`
-- fourth canary for the `2026.318.1` line: `2026.318.1-canary.3`
+- 2026年3月18日的第一个稳定版:`2026.318.0`
+- 2026年3月18日的第二个稳定版:`2026.318.1`
+- `2026.318.1` 系列的第四个 canary:`2026.318.1-canary.3`
-Important constraints:
+重要约束:
-- the middle numeric slot is `MDD`, where `M` is the UTC month and `DD` is the zero-padded UTC day
-- use `2026.303.0` for March 3, not `2026.33.0`
-- do not use leading zeroes such as `2026.0318.0`
-- do not use four numeric segments such as `2026.3.18.1`
-- the semver-safe canary form is `2026.318.0-canary.1`
+- 中间数字段是 `MDD`,其中 `M` 是 UTC 月份,`DD` 是补零的 UTC 日期
+- 3月3日使用 `2026.303.0`,而不是 `2026.33.0`
+- 不要使用前导零如 `2026.0318.0`
+- 不要使用四段数字如 `2026.3.18.1`
+- semver 安全的 canary 格式为 `2026.318.0-canary.1`
-## Release Surfaces
+## 发布面
-Every stable release has four separate surfaces:
+每个稳定版本有四个独立的发布面:
-1. **Verification** — the exact git SHA passes typecheck, tests, and build
-2. **npm** — `paperclipai` and public workspace packages are published
-3. **GitHub** — the stable release gets a git tag and GitHub Release
-4. **Website / announcements** — the stable changelog is published externally and announced
+1. **验证** — 精确的 git SHA 通过类型检查、测试和构建
+2. **npm** — `paperclipai` 和公共工作区包被发布
+3. **GitHub** — 稳定版本获得 git 标签和 GitHub Release
+4. **网站/公告** — 稳定版变更日志对外发布并公告
-A stable release is done only when all four surfaces are handled.
+只有当所有四个发布面都处理完毕,稳定版本才算完成。
-Canaries only cover the first two surfaces plus an internal traceability tag.
+canary 版本只覆盖前两个发布面加上内部可追溯性标签。
-## Core Invariants
+## 核心不变量
-- canaries publish from `master`
-- stables publish from an explicitly chosen source ref
-- tags point at the original source commit, not a generated release commit
-- stable notes are always `releases/vYYYY.MDD.P.md`
-- canaries never create GitHub Releases
-- canaries never require changelog generation
+- canary 从 `master` 发布
+- 稳定版从明确选定的源引用发布
+- 标签指向原始源提交,而非生成的发布提交
+- 稳定版发布说明始终位于 `releases/vYYYY.MDD.P.md`
+- canary 永远不创建 GitHub Releases
+- canary 永远不需要变更日志生成
-## TL;DR
+## 简要总结
### Canary
-Every push to `master` runs the canary path inside [`.github/workflows/release.yml`](../.github/workflows/release.yml).
+每次推送到 `master` 都会运行 [`.github/workflows/release.yml`](../.github/workflows/release.yml) 中的 canary 路径。
-It:
+它会:
-- verifies the pushed commit
-- computes the canary version for the current UTC date
-- publishes under npm dist-tag `canary`
-- creates a git tag `canary/vYYYY.MDD.P-canary.N`
+- 验证推送的提交
+- 计算当前 UTC 日期的 canary 版本
+- 在 npm dist-tag `canary` 下发布
+- 创建 git 标签 `canary/vYYYY.MDD.P-canary.N`
-Users install canaries with:
+用户通过以下方式安装 canary:
```bash
npx paperclipai@canary onboard
-# or
+# 或
npx paperclipai@canary onboard --data-dir "$(mktemp -d /tmp/paperclip-canary.XXXXXX)"
```
-### Stable
+### 稳定版
-Use [`.github/workflows/release.yml`](../.github/workflows/release.yml) from the Actions tab with the manual `workflow_dispatch` inputs.
+从 Actions 标签页使用 [`.github/workflows/release.yml`](../.github/workflows/release.yml) 的手动 `workflow_dispatch` 输入。
-[Run the action here](https://github.com/paperclipai/paperclip/actions/workflows/release.yml)
+[在这里运行操作](https://github.com/paperclipai/paperclip/actions/workflows/release.yml)
-Inputs:
+输入参数:
- `source_ref`
- - commit SHA, branch, or tag
+ - 提交 SHA、分支或标签
- `stable_date`
- - optional UTC date override in `YYYY-MM-DD`
- - enter a date like `2026-03-18`, not a version like `2026.318.0`
+ - 可选的 UTC 日期覆盖,格式为 `YYYY-MM-DD`
+ - 输入日期如 `2026-03-18`,而非版本如 `2026.318.0`
- `dry_run`
- - preview only when true
+ - 为 true 时仅预览
-Before running stable:
+运行稳定版之前:
-1. pick the canary commit or tag you trust
-2. resolve the target stable version with `./scripts/release.sh stable --date "$(date +%F)" --print-version`
-3. create or update `releases/vYYYY.MDD.P.md` on that source ref
-4. run the stable workflow from that source ref
+1. 选择你信任的 canary 提交或标签
+2. 使用 `./scripts/release.sh stable --date "$(date +%F)" --print-version` 解析目标稳定版本
+3. 在该源引用上创建或更新 `releases/vYYYY.MDD.P.md`
+4. 从该源引用运行稳定版工作流
-Example:
+示例:
-- `source_ref`: `master`
-- `stable_date`: `2026-03-18`
-- resulting stable version: `2026.318.0`
+- `source_ref`:`master`
+- `stable_date`:`2026-03-18`
+- 生成的稳定版本:`2026.318.0`
-The workflow:
+工作流会:
-- re-verifies the exact source ref
-- computes the next stable patch slot for the chosen UTC date
-- publishes `YYYY.MDD.P` under npm dist-tag `latest`
-- creates git tag `vYYYY.MDD.P`
-- creates or updates the GitHub Release from `releases/vYYYY.MDD.P.md`
+- 重新验证精确的源引用
+- 计算选定 UTC 日期的下一个稳定补丁槽位
+- 在 npm dist-tag `latest` 下发布 `YYYY.MDD.P`
+- 创建 git 标签 `vYYYY.MDD.P`
+- 从 `releases/vYYYY.MDD.P.md` 创建或更新 GitHub Release
-## Local Commands
+## 本地命令
-### Preview a canary locally
+### 本地预览 canary
```bash
./scripts/release.sh canary --dry-run
```
-### Preview a stable locally
+### 本地预览稳定版
```bash
./scripts/release.sh stable --dry-run
```
-### Publish a stable locally
+### 本地发布稳定版
-This is mainly for emergency/manual use. The normal path is the GitHub workflow.
+这主要用于紧急/手动使用。正常路径是 GitHub 工作流。
```bash
./scripts/release.sh stable
@@ -134,114 +134,114 @@ git push public-gh refs/tags/vYYYY.MDD.P
PUBLISH_REMOTE=public-gh ./scripts/create-github-release.sh YYYY.MDD.P
```
-## Stable Changelog Workflow
+## 稳定版变更日志工作流
-Stable changelog files live at:
+稳定版变更日志文件位于:
- `releases/vYYYY.MDD.P.md`
-Canaries do not get changelog files.
+canary 不生成变更日志文件。
-Recommended local generation flow:
+推荐的本地生成流程:
```bash
VERSION="$(./scripts/release.sh stable --date 2026-03-18 --print-version)"
claude --print --output-format stream-json --verbose --dangerously-skip-permissions --model claude-opus-4-6 "Use the release-changelog skill to draft or update releases/v${VERSION}.md for Paperclip. Read doc/RELEASING.md and .agents/skills/release-changelog/SKILL.md, then generate the stable changelog for v${VERSION} from commits since the last stable tag. Do not create a canary changelog."
```
-The repo intentionally does not run this through GitHub Actions because:
+仓库有意不通过 GitHub Actions 运行此操作,因为:
-- canaries are too frequent
-- stable notes are the only public narrative surface that needs LLM help
-- maintainer LLM tokens should not live in Actions
+- canary 太频繁
+- 稳定版发布说明是唯一需要 LLM 帮助的公共叙事面
+- 维护者的 LLM token 不应该存放在 Actions 中
-## Smoke Testing
+## 冒烟测试
-For a canary:
+canary 版本:
```bash
PAPERCLIPAI_VERSION=canary ./scripts/docker-onboard-smoke.sh
```
-For the current stable:
+当前稳定版:
```bash
PAPERCLIPAI_VERSION=latest ./scripts/docker-onboard-smoke.sh
```
-Useful isolated variants:
+有用的隔离变体:
```bash
HOST_PORT=3232 DATA_DIR=./data/release-smoke-canary PAPERCLIPAI_VERSION=canary ./scripts/docker-onboard-smoke.sh
HOST_PORT=3233 DATA_DIR=./data/release-smoke-stable PAPERCLIPAI_VERSION=latest ./scripts/docker-onboard-smoke.sh
```
-Automated browser smoke is also available:
+自动化浏览器冒烟测试也可用:
```bash
gh workflow run release-smoke.yml -f paperclip_version=canary
gh workflow run release-smoke.yml -f paperclip_version=latest
```
-Minimum checks:
+最低检查项:
-- `npx paperclipai@canary onboard` installs
-- onboarding completes without crashes
-- authenticated login works with the smoke credentials
-- the browser lands in onboarding on a fresh instance
-- company creation succeeds
-- the first CEO agent is created
-- the first CEO heartbeat run is triggered
+- `npx paperclipai@canary onboard` 能安装
+- 入门流程完成且无崩溃
+- 认证登录使用冒烟测试凭据正常工作
+- 浏览器在全新实例上进入入门页面
+- 公司创建成功
+- 第一个 CEO 代理被创建
+- 第一次 CEO 心跳运行被触发
-## Rollback
+## 回滚
-Rollback does not unpublish versions.
+回滚不会取消发布版本。
-It only moves the `latest` dist-tag back to a previous stable:
+它只将 `latest` dist-tag 移回到之前的稳定版:
```bash
./scripts/rollback-latest.sh 2026.318.0 --dry-run
./scripts/rollback-latest.sh 2026.318.0
```
-Then fix forward with a new stable patch slot or release date.
+然后通过新的稳定补丁槽位或发布日期向前修复。
-## Failure Playbooks
+## 故障处理手册
-### If the canary publishes but smoke testing fails
+### 如果 canary 已发布但冒烟测试失败
-Do not run stable.
+不要运行稳定版。
-Instead:
+改为:
-1. fix the issue on `master`
-2. merge the fix
-3. wait for the next automatic canary
-4. rerun smoke testing
+1. 在 `master` 上修复问题
+2. 合并修复
+3. 等待下一个自动 canary
+4. 重新运行冒烟测试
-### If stable npm publish succeeds but tag push or GitHub release creation fails
+### 如果稳定版 npm 发布成功但标签推送或 GitHub release 创建失败
-This is a partial release. npm is already live.
+这是一个不完整的发布。npm 已经上线。
-Do this immediately:
+立即执行以下操作:
-1. push the missing tag
-2. rerun `PUBLISH_REMOTE=public-gh ./scripts/create-github-release.sh YYYY.MDD.P`
-3. verify the GitHub Release notes point at `releases/vYYYY.MDD.P.md`
+1. 推送缺失的标签
+2. 重新运行 `PUBLISH_REMOTE=public-gh ./scripts/create-github-release.sh YYYY.MDD.P`
+3. 验证 GitHub Release 发布说明指向 `releases/vYYYY.MDD.P.md`
-Do not republish the same version.
+不要重新发布同一版本。
-### If `latest` is broken after stable publish
+### 如果稳定版发布后 `latest` 出现问题
-Roll back the dist-tag:
+回滚 dist-tag:
```bash
./scripts/rollback-latest.sh YYYY.MDD.P
```
-Then fix forward with a new stable release.
+然后通过新的稳定版发布向前修复。
-## Related Files
+## 相关文件
- [`scripts/release.sh`](../scripts/release.sh)
- [`scripts/release-package-map.mjs`](../scripts/release-package-map.mjs)
diff --git a/doc/SPEC-implementation.md b/doc/SPEC-implementation.md
index b51a044708..9065d5852c 100644
--- a/doc/SPEC-implementation.md
+++ b/doc/SPEC-implementation.md
@@ -1,121 +1,121 @@
-# Paperclip V1 Implementation Spec
+# Paperclip V1 实现规范
-Status: Implementation contract for first release (V1)
-Date: 2026-02-17
-Audience: Product, engineering, and agent-integration authors
-Source inputs: `GOAL.md`, `PRODUCT.md`, `SPEC.md`, `DATABASE.md`, current monorepo code
+状态:首次发布(V1)的实现契约
+日期:2026-02-17
+受众:产品、工程及智能体集成开发者
+来源输入:`GOAL.md`、`PRODUCT.md`、`SPEC.md`、`DATABASE.md`、当前 monorepo 代码
-## 1. Document Role
+## 1. 文档定位
-`SPEC.md` remains the long-horizon product spec.
-This document is the concrete, build-ready V1 contract.
-When there is a conflict, `SPEC-implementation.md` controls V1 behavior.
+`SPEC.md` 仍为长期产品规范。
+本文档是具体的、可直接构建的 V1 契约。
+如有冲突,以 `SPEC-implementation.md` 为 V1 行为的准则。
-## 2. V1 Outcomes
+## 2. V1 目标成果
-Paperclip V1 must provide a full control-plane loop for autonomous agents:
+Paperclip V1 必须为自主智能体提供完整的控制平面循环:
-1. A human board creates a company and defines goals.
-2. The board creates and manages agents in an org tree.
-3. Agents receive and execute tasks via heartbeat invocations.
-4. All work is tracked through tasks/comments with audit visibility.
-5. Token/cost usage is reported and budget limits can stop work.
-6. The board can intervene anywhere (pause agents/tasks, override decisions).
+1. 人类董事会创建公司并定义目标。
+2. 董事会在组织树中创建并管理智能体。
+3. 智能体通过心跳调用接收并执行任务。
+4. 所有工作通过任务/评论进行跟踪,并具备审计可见性。
+5. Token/成本用量被上报,预算限制可终止工作。
+6. 董事会可随时介入(暂停智能体/任务、覆盖决策)。
-Success means one operator can run a small AI-native company end-to-end with clear visibility and control.
+成功标准:单个运营者能够端到端运营一家小型 AI 原生公司,具备清晰的可见性与控制力。
-## 3. Explicit V1 Product Decisions
+## 3. V1 明确产品决策
-These decisions close open questions from `SPEC.md` for V1.
+这些决策针对 V1 关闭了 `SPEC.md` 中的未解问题。
-| Topic | V1 Decision |
+| 主题 | V1 决策 |
|---|---|
-| Tenancy | Single-tenant deployment, multi-company data model |
-| Company model | Company is first-order; all business entities are company-scoped |
-| Board | Single human board operator per deployment |
-| Org graph | Strict tree (`reports_to` nullable root); no multi-manager reporting |
-| Visibility | Full visibility to board and all agents in same company |
-| Communication | Tasks + comments only (no separate chat system) |
-| Task ownership | Single assignee; atomic checkout required for `in_progress` transition |
-| Recovery | No automatic reassignment; work recovery stays manual/explicit |
-| Agent adapters | Built-in `process` and `http` adapters |
-| Auth | Mode-dependent human auth (`local_trusted` implicit board in current code; authenticated mode uses sessions), API keys for agents |
-| Budget period | Monthly UTC calendar window |
-| Budget enforcement | Soft alerts + hard limit auto-pause |
-| Deployment modes | Canonical model is `local_trusted` + `authenticated` with `private/public` exposure policy (see `doc/DEPLOYMENT-MODES.md`) |
+| 租户模式 | 单租户部署,多公司数据模型 |
+| 公司模型 | 公司为一等实体;所有业务实体均属于公司范围 |
+| 董事会 | 每个部署对应单一人类董事会运营者 |
+| 组织图 | 严格树形结构(`reports_to` 可为 null 的根节点);不支持多上级汇报 |
+| 可见性 | 董事会及同公司所有智能体拥有完全可见性 |
+| 沟通方式 | 仅通过任务 + 评论(无独立聊天系统) |
+| 任务归属 | 单一受理人;`in_progress` 状态转换需要原子检出 |
+| 恢复机制 | 无自动重新分配;工作恢复保持手动/明确方式 |
+| 智能体适配器 | 内置 `process` 和 `http` 适配器 |
+| 认证 | 与模式相关的人类认证(当前代码中 `local_trusted` 为隐式董事会;认证模式使用会话),智能体使用 API 密钥 |
+| 预算周期 | 每月 UTC 日历窗口 |
+| 预算执行 | 软性警报 + 硬上限自动暂停 |
+| 部署模式 | 规范模型为 `local_trusted` + `authenticated`,配合 `private/public` 暴露策略(参见 `doc/DEPLOYMENT-MODES.md`) |
-## 4. Current Baseline (Repo Snapshot)
+## 4. 当前基线(代码库快照)
-As of 2026-02-17, the repo already includes:
+截至 2026-02-17,代码库已包含:
-- Node + TypeScript backend with REST CRUD for `agents`, `projects`, `goals`, `issues`, `activity`
-- React UI pages for dashboard/agents/projects/goals/issues lists
-- PostgreSQL schema via Drizzle with embedded PostgreSQL fallback when `DATABASE_URL` is unset
+- Node + TypeScript 后端,为 `agents`、`projects`、`goals`、`issues`、`activity` 提供 REST CRUD
+- React UI 页面,用于仪表盘/智能体/项目/目标/问题列表
+- 通过 Drizzle 管理的 PostgreSQL 架构,当 `DATABASE_URL` 未设置时回退到内嵌 PostgreSQL
-V1 implementation extends this baseline into a company-centric, governance-aware control plane.
+V1 实现在此基线上扩展为以公司为中心、具备治理意识的控制平面。
-## 5. V1 Scope
+## 5. V1 范围
-## 5.1 In Scope
+## 5.1 范围内
-- Company lifecycle (create/list/get/update/archive)
-- Goal hierarchy linked to company mission
-- Agent lifecycle with org structure and adapter configuration
-- Task lifecycle with parent/child hierarchy and comments
-- Atomic task checkout and explicit task status transitions
-- Board approvals for hires and CEO strategy proposal
-- Heartbeat invocation, status tracking, and cancellation
-- Cost event ingestion and rollups (agent/task/project/company)
-- Budget settings and hard-stop enforcement
-- Board web UI for dashboard, org chart, tasks, agents, approvals, costs
-- Agent-facing API contract (task read/write, heartbeat report, cost report)
-- Auditable activity log for all mutating actions
+- 公司生命周期(创建/列出/获取/更新/归档)
+- 与公司使命关联的目标层级
+- 含组织结构和适配器配置的智能体生命周期
+- 含父子层级和评论的任务生命周期
+- 原子任务检出和明确的任务状态转换
+- 董事会对招聘及 CEO 战略提案的审批
+- 心跳调用、状态追踪及取消
+- 成本事件采集和汇总(智能体/任务/项目/公司)
+- 预算设置和硬停止执行
+- 董事会 Web UI(仪表盘、组织图、任务、智能体、审批、成本)
+- 面向智能体的 API 契约(任务读写、心跳上报、成本上报)
+- 所有变更操作的可审计活动日志
-## 5.2 Out of Scope (V1)
+## 5.2 范围外(V1)
-- Plugin framework and third-party extension SDK
-- Revenue/expense accounting beyond model/token costs
-- Knowledge base subsystem
-- Public marketplace (ClipHub)
-- Multi-board governance or role-based human permission granularity
-- Automatic self-healing orchestration (auto-reassign/retry planners)
+- 插件框架和第三方扩展 SDK
+- 超出模型/Token 成本的收入/支出核算
+- 知识库子系统
+- 公共市场(ClipHub)
+- 多董事会治理或基于角色的人类权限细粒度管理
+- 自动自愈编排(自动重新分配/重试规划器)
-## 6. Architecture
+## 6. 架构
-## 6.1 Runtime Components
+## 6.1 运行时组件
-- `server/`: REST API, auth, orchestration services
-- `ui/`: Board operator interface
-- `packages/db/`: Drizzle schema, migrations, DB clients (Postgres)
-- `packages/shared/`: Shared API types, validators, constants
+- `server/`:REST API、认证、编排服务
+- `ui/`:董事会运营者界面
+- `packages/db/`:Drizzle 架构、迁移、数据库客户端(Postgres)
+- `packages/shared/`:共享 API 类型、验证器、常量
-## 6.2 Data Stores
+## 6.2 数据存储
-- Primary: PostgreSQL
-- Local default: embedded PostgreSQL at `~/.paperclip/instances/default/db`
-- Optional local prod-like: Docker Postgres
-- Optional hosted: Supabase/Postgres-compatible
-- File/object storage:
- - local default: `~/.paperclip/instances/default/data/storage` (`local_disk`)
- - cloud: S3-compatible object storage (`s3`)
+- 主数据库:PostgreSQL
+- 本地默认:内嵌 PostgreSQL,路径为 `~/.paperclip/instances/default/db`
+- 可选的本地类生产环境:Docker Postgres
+- 可选托管方案:Supabase/Postgres 兼容
+- 文件/对象存储:
+ - 本地默认:`~/.paperclip/instances/default/data/storage`(`local_disk`)
+ - 云端:S3 兼容对象存储(`s3`)
-## 6.3 Background Processing
+## 6.3 后台处理
-A lightweight scheduler/worker in the server process handles:
+服务进程中的轻量级调度器/工作进程负责处理:
-- heartbeat trigger checks
-- stuck run detection
-- budget threshold checks
+- 心跳触发检查
+- 卡住运行检测
+- 预算阈值检查
-Separate queue infrastructure is not required for V1.
+V1 不需要独立的队列基础设施。
-## 7. Canonical Data Model (V1)
+## 7. 规范数据模型(V1)
-All core tables include `id`, `created_at`, `updated_at` unless noted.
+除特别说明外,所有核心表均包含 `id`、`created_at`、`updated_at` 字段。
-## 7.0 Auth Tables
+## 7.0 认证表
-Human auth tables (`users`, `sessions`, and provider-specific auth artifacts) are managed by the selected auth library. This spec treats them as required dependencies and references `users.id` where user attribution is needed.
+人类认证表(`users`、`sessions` 及特定提供商的认证工件)由所选认证库管理。本规范将其视为必需依赖,在需要用户归属时引用 `users.id`。
## 7.1 `companies`
@@ -124,7 +124,7 @@ Human auth tables (`users`, `sessions`, and provider-specific auth artifacts) ar
- `description` text null
- `status` enum: `active | paused | archived`
-Invariant: every business record belongs to exactly one company.
+不变量:每条业务记录恰好属于一个公司。
## 7.2 `agents`
@@ -143,11 +143,11 @@ Invariant: every business record belongs to exactly one company.
- `spent_monthly_cents` int not null default 0
- `last_heartbeat_at` timestamptz null
-Invariants:
+不变量:
-- agent and manager must be in same company
-- no cycles in reporting tree
-- `terminated` agents cannot be resumed
+- 智能体与其上级必须属于同一公司
+- 汇报树中不允许出现循环
+- `terminated` 状态的智能体无法恢复
## 7.3 `agent_api_keys`
@@ -159,7 +159,7 @@ Invariants:
- `last_used_at` timestamptz null
- `revoked_at` timestamptz null
-Invariant: plaintext key shown once at creation; only hash stored.
+不变量:明文密钥仅在创建时展示一次;仅存储哈希值。
## 7.4 `goals`
@@ -172,7 +172,7 @@ Invariant: plaintext key shown once at creation; only hash stored.
- `owner_agent_id` uuid fk `agents.id` null
- `status` enum: `planned | active | achieved | cancelled`
-Invariant: at least one root `company` level goal per company.
+不变量:每个公司至少有一个根级 `company` 层级目标。
## 7.5 `projects`
@@ -185,7 +185,7 @@ Invariant: at least one root `company` level goal per company.
- `lead_agent_id` uuid fk `agents.id` null
- `target_date` date null
-## 7.6 `issues` (core task entity)
+## 7.6 `issues`(核心任务实体)
- `id` uuid pk
- `company_id` uuid fk not null
@@ -205,12 +205,12 @@ Invariant: at least one root `company` level goal per company.
- `completed_at` timestamptz null
- `cancelled_at` timestamptz null
-Invariants:
+不变量:
-- single assignee only
-- task must trace to company goal chain via `goal_id`, `parent_id`, or project-goal linkage
-- `in_progress` requires assignee
-- terminal states: `done | cancelled`
+- 仅允许单一受理人
+- 任务必须通过 `goal_id`、`parent_id` 或项目-目标关联追溯到公司目标链
+- `in_progress` 状态需要受理人
+- 终止状态:`done | cancelled`
## 7.7 `issue_comments`
@@ -236,6 +236,7 @@ Invariants:
## 7.9 `cost_events`
+
- `id` uuid pk
- `company_id` uuid fk not null
- `agent_id` uuid fk `agents.id` not null
@@ -250,7 +251,7 @@ Invariants:
- `cost_cents` int not null
- `occurred_at` timestamptz not null
-Invariant: each event must attach to agent and company; rollups are aggregation, never manually edited.
+不变量:每个事件必须关联智能体和公司;汇总值为聚合计算结果,绝不手动编辑。
## 7.10 `approvals`
@@ -279,19 +280,19 @@ Invariant: each event must attach to agent and company; rollups are aggregation,
## 7.12 `company_secrets` + `company_secret_versions`
-- Secret values are not stored inline in `agents.adapter_config.env`.
-- Agent env entries should use secret refs for sensitive values.
-- `company_secrets` tracks identity/provider metadata per company.
-- `company_secret_versions` stores encrypted/reference material per version.
-- Default provider in local deployments: `local_encrypted`.
+- 密钥值不在 `agents.adapter_config.env` 中内联存储。
+- 智能体的环境变量条目应对敏感值使用密钥引用。
+- `company_secrets` 追踪每个公司的身份/提供商元数据。
+- `company_secret_versions` 按版本存储加密/引用材料。
+- 本地部署的默认提供商:`local_encrypted`。
-Operational policy:
+运营策略:
-- Config read APIs redact sensitive plain values.
-- Activity and approval payloads must not persist raw sensitive values.
-- Config revisions may include redacted placeholders; such revisions are non-restorable for redacted fields.
+- 配置读取 API 对敏感明文值进行脱敏处理。
+- 活动和审批负载不得持久化原始敏感值。
+- 配置修订版本可能包含脱敏占位符;此类修订对脱敏字段不可恢复。
-## 7.13 Required Indexes
+## 7.13 必需索引
- `agents(company_id, status)`
- `agents(company_id, reports_to)`
@@ -312,7 +313,7 @@ Operational policy:
## 7.14 `assets` + `issue_attachments`
-- `assets` stores provider-backed object metadata (not inline bytes):
+- `assets` 存储提供商支持的对象元数据(不内联字节):
- `id` uuid pk
- `company_id` uuid fk not null
- `provider` enum/text (`local_disk | s3`)
@@ -323,7 +324,7 @@ Operational policy:
- `original_filename` text null
- `created_by_agent_id` uuid fk null
- `created_by_user_id` uuid/text fk null
-- `issue_attachments` links assets to issues/comments:
+- `issue_attachments` 将资产关联到问题/评论:
- `id` uuid pk
- `company_id` uuid fk not null
- `issue_id` uuid fk not null
@@ -332,7 +333,7 @@ Operational policy:
## 7.15 `documents` + `document_revisions` + `issue_documents`
-- `documents` stores editable text-first documents:
+- `documents` 存储可编辑的文本优先文档:
- `id` uuid pk
- `company_id` uuid fk not null
- `title` text null
@@ -344,98 +345,98 @@ Operational policy:
- `created_by_user_id` uuid/text fk null
- `updated_by_agent_id` uuid fk null
- `updated_by_user_id` uuid/text fk null
-- `document_revisions` stores append-only history:
+- `document_revisions` 存储只追加的历史记录:
- `id` uuid pk
- `company_id` uuid fk not null
- `document_id` uuid fk not null
- `revision_number` int not null
- `body` text not null
- `change_summary` text null
-- `issue_documents` links documents to issues with a stable workflow key:
+- `issue_documents` 通过稳定的工作流键将文档关联到问题:
- `id` uuid pk
- `company_id` uuid fk not null
- `issue_id` uuid fk not null
- `document_id` uuid fk not null
- - `key` text not null (`plan`, `design`, `notes`, etc.)
+ - `key` text not null(`plan`、`design`、`notes` 等)
-## 8. State Machines
+## 8. 状态机
-## 8.1 Agent Status
+## 8.1 智能体状态
-Allowed transitions:
+允许的转换:
- `idle -> running`
- `running -> idle`
- `running -> error`
- `error -> idle`
- `idle -> paused`
-- `running -> paused` (requires cancel flow)
+- `running -> paused`(需要取消流程)
- `paused -> idle`
-- `* -> terminated` (board only, irreversible)
+- `* -> terminated`(仅董事会,不可逆)
-## 8.2 Issue Status
+## 8.2 问题状态
-Allowed transitions:
+允许的转换:
- `backlog -> todo | cancelled`
- `todo -> in_progress | blocked | cancelled`
- `in_progress -> in_review | blocked | done | cancelled`
- `in_review -> in_progress | done | cancelled`
- `blocked -> todo | in_progress | cancelled`
-- terminal: `done`, `cancelled`
+- 终止状态:`done`、`cancelled`
-Side effects:
+副作用:
-- entering `in_progress` sets `started_at` if null
-- entering `done` sets `completed_at`
-- entering `cancelled` sets `cancelled_at`
+- 进入 `in_progress` 时若 `started_at` 为 null 则设置该字段
+- 进入 `done` 时设置 `completed_at`
+- 进入 `cancelled` 时设置 `cancelled_at`
-## 8.3 Approval Status
+## 8.3 审批状态
- `pending -> approved | rejected | cancelled`
-- terminal after decision
+- 决策后进入终止状态
-## 9. Auth and Permissions
+## 9. 认证与权限
-## 9.1 Board Auth
+## 9.1 董事会认证
-- Session-based auth for human operator
-- Board has full read/write across all companies in deployment
-- Every board mutation writes to `activity_log`
+- 人类运营者使用基于会话的认证
+- 董事会对部署中所有公司拥有完整的读写权限
+- 每次董事会变更操作均写入 `activity_log`
-## 9.2 Agent Auth
+## 9.2 智能体认证
-- Bearer API key mapped to one agent and company
-- Agent key scope:
- - read org/task/company context for own company
- - read/write own assigned tasks and comments
- - create tasks/comments for delegation
- - report heartbeat status
- - report cost events
-- Agent cannot:
- - bypass approval gates
- - modify company-wide budgets directly
- - mutate auth/keys
+- Bearer API 密钥映射到一个智能体和公司
+- 智能体密钥范围:
+ - 读取本公司的组织/任务/公司上下文
+ - 读写自己受理的任务和评论
+ - 创建任务/评论用于委派
+ - 上报心跳状态
+ - 上报成本事件
+- 智能体不能:
+ - 绕过审批关卡
+ - 直接修改公司级预算
+ - 变更认证/密钥
-## 9.3 Permission Matrix (V1)
+## 9.3 权限矩阵(V1)
-| Action | Board | Agent |
+| 操作 | 董事会 | 智能体 |
|---|---|---|
-| Create company | yes | no |
-| Hire/create agent | yes (direct) | request via approval |
-| Pause/resume agent | yes | no |
-| Create/update task | yes | yes |
-| Force reassign task | yes | limited |
-| Approve strategy/hire requests | yes | no |
-| Report cost | yes | yes |
-| Set company budget | yes | no |
-| Set subordinate budget | yes | yes (manager subtree only) |
+| 创建公司 | 是 | 否 |
+| 招聘/创建智能体 | 是(直接) | 通过审批申请 |
+| 暂停/恢复智能体 | 是 | 否 |
+| 创建/更新任务 | 是 | 是 |
+| 强制重新分配任务 | 是 | 受限 |
+| 审批战略/招聘申请 | 是 | 否 |
+| 上报成本 | 是 | 是 |
+| 设置公司预算 | 是 | 否 |
+| 设置下属预算 | 是 | 是(仅限管理子树) |
-## 10. API Contract (REST)
+## 10. API 契约(REST)
-All endpoints are under `/api` and return JSON.
+所有端点均位于 `/api` 下,返回 JSON。
-## 10.1 Companies
+## 10.1 公司
- `GET /companies`
- `POST /companies`
@@ -444,15 +445,15 @@ All endpoints are under `/api` and return JSON.
- `PATCH /companies/:companyId/branding`
- `POST /companies/:companyId/archive`
-## 10.2 Goals
+## 10.2 目标
- `GET /companies/:companyId/goals`
- `POST /companies/:companyId/goals`
- `GET /goals/:goalId`
- `PATCH /goals/:goalId`
-- `DELETE /goals/:goalId` (soft delete optional, hard delete board-only)
+- `DELETE /goals/:goalId`(软删除可选,硬删除仅限董事会)
-## 10.3 Agents
+## 10.3 智能体
- `GET /companies/:companyId/agents`
- `POST /companies/:companyId/agents`
@@ -461,10 +462,10 @@ All endpoints are under `/api` and return JSON.
- `POST /agents/:agentId/pause`
- `POST /agents/:agentId/resume`
- `POST /agents/:agentId/terminate`
-- `POST /agents/:agentId/keys` (create API key)
+- `POST /agents/:agentId/keys`(创建 API 密钥)
- `POST /agents/:agentId/heartbeat/invoke`
-## 10.4 Tasks (Issues)
+## 10.4 任务(Issues)
- `GET /companies/:companyId/issues`
- `POST /companies/:companyId/issues`
@@ -479,14 +480,14 @@ All endpoints are under `/api` and return JSON.
- `POST /issues/:issueId/release`
- `POST /issues/:issueId/comments`
- `GET /issues/:issueId/comments`
-- `POST /companies/:companyId/issues/:issueId/attachments` (multipart upload)
+- `POST /companies/:companyId/issues/:issueId/attachments`(multipart 上传)
- `GET /issues/:issueId/attachments`
- `GET /attachments/:attachmentId/content`
- `DELETE /attachments/:attachmentId`
-### 10.4.1 Atomic Checkout Contract
+### 10.4.1 原子检出契约
-`POST /issues/:issueId/checkout` request:
+`POST /issues/:issueId/checkout` 请求:
```json
{
@@ -495,27 +496,27 @@ All endpoints are under `/api` and return JSON.
}
```
-Server behavior:
+服务端行为:
-1. single SQL update with `WHERE id = ? AND status IN (?) AND (assignee_agent_id IS NULL OR assignee_agent_id = :agentId)`
-2. if updated row count is 0, return `409` with current owner/status
-3. successful checkout sets `assignee_agent_id`, `status = in_progress`, and `started_at`
+1. 单条 SQL 更新,条件为 `WHERE id = ? AND status IN (?) AND (assignee_agent_id IS NULL OR assignee_agent_id = :agentId)`
+2. 若更新行数为 0,返回 `409` 并附带当前归属人/状态
+3. 检出成功后设置 `assignee_agent_id`、`status = in_progress` 及 `started_at`
-## 10.5 Projects
+## 10.5 项目
- `GET /companies/:companyId/projects`
- `POST /companies/:companyId/projects`
- `GET /projects/:projectId`
- `PATCH /projects/:projectId`
-## 10.6 Approvals
+## 10.6 审批
- `GET /companies/:companyId/approvals?status=pending`
- `POST /companies/:companyId/approvals`
- `POST /approvals/:approvalId/approve`
- `POST /approvals/:approvalId/reject`
-## 10.7 Cost and Budgets
+## 10.7 成本与预算
- `POST /companies/:companyId/cost-events`
- `GET /companies/:companyId/costs/summary`
@@ -524,31 +525,31 @@ Server behavior:
- `PATCH /companies/:companyId/budgets`
- `PATCH /agents/:agentId/budgets`
-## 10.8 Activity and Dashboard
+## 10.8 活动与仪表盘
- `GET /companies/:companyId/activity`
- `GET /companies/:companyId/dashboard`
-Dashboard payload must include:
+仪表盘负载必须包含:
-- active/running/paused/error agent counts
-- open/in-progress/blocked/done issue counts
-- month-to-date spend and budget utilization
-- pending approvals count
+- 活跃/运行中/已暂停/错误状态的智能体数量
+- 开放/进行中/已阻塞/已完成的问题数量
+- 本月累计支出和预算使用率
+- 待处理审批数量
-## 10.9 Error Semantics
+## 10.9 错误语义
-- `400` validation error
-- `401` unauthenticated
-- `403` unauthorized
-- `404` not found
-- `409` state conflict (checkout conflict, invalid transition)
-- `422` semantic rule violation
-- `500` server error
+- `400` 验证错误
+- `401` 未认证
+- `403` 未授权
+- `404` 未找到
+- `409` 状态冲突(检出冲突、无效转换)
+- `422` 语义规则违反
+- `500` 服务器错误
-## 11. Heartbeat and Adapter Contract
+## 11. 心跳与适配器契约
-## 11.1 Adapter Interface
+## 11.1 适配器接口
```ts
interface AgentAdapter {
@@ -558,9 +559,9 @@ interface AgentAdapter {
}
```
-## 11.2 Process Adapter
+## 11.2 进程适配器
-Config shape:
+配置结构:
```json
{
@@ -573,16 +574,16 @@ Config shape:
}
```
-Behavior:
+行为:
-- spawn child process
-- stream stdout/stderr to run logs
-- mark run status on exit code/timeout
-- cancel sends SIGTERM then SIGKILL after grace
+- 派生子进程
+- 将 stdout/stderr 流式传输到运行日志
+- 根据退出码/超时标记运行状态
+- 取消时先发送 SIGTERM,宽限期后发送 SIGKILL
-## 11.3 HTTP Adapter
+## 11.3 HTTP 适配器
-Config shape:
+配置结构:
```json
{
@@ -594,81 +595,81 @@ Config shape:
}
```
-Behavior:
+行为:
-- invoke by outbound HTTP request
-- 2xx means accepted
-- non-2xx marks failed invocation
-- optional callback endpoint allows asynchronous completion updates
+- 通过出站 HTTP 请求调用
+- 2xx 表示已接受
+- 非 2xx 标记调用失败
+- 可选的回调端点允许异步完成状态更新
-## 11.4 Context Delivery
+## 11.4 上下文传递
-- `thin`: send IDs and pointers only; agent fetches context via API
-- `fat`: include current assignments, goal summary, budget snapshot, and recent comments
+- `thin`:仅发送 ID 和指针;智能体通过 API 获取上下文
+- `fat`:包含当前分配、目标摘要、预算快照和最近评论
-## 11.5 Scheduler Rules
+## 11.5 调度规则
-Per-agent schedule fields in `adapter_config`:
+`adapter_config` 中每个智能体的调度字段:
-- `enabled` boolean
-- `intervalSec` integer (minimum 30)
-- `maxConcurrentRuns` fixed at `1` for V1
+- `enabled` 布尔值
+- `intervalSec` 整数(最小值为 30)
+- `maxConcurrentRuns` V1 中固定为 `1`
-Scheduler must skip invocation when:
+调度器在以下情况必须跳过调用:
-- agent is paused/terminated
-- an existing run is active
-- hard budget limit has been hit
+- 智能体已暂停/已终止
+- 存在活跃的运行
+- 已触达硬预算上限
-## 12. Governance and Approval Flows
+## 12. 治理与审批流程
-## 12.1 Hiring
+## 12.1 招聘
-1. Agent or board creates `approval(type=hire_agent, status=pending, payload=agent draft)`.
-2. Board approves or rejects.
-3. On approval, server creates agent row and initial API key (optional).
-4. Decision is logged in `activity_log`.
+1. 智能体或董事会创建 `approval(type=hire_agent, status=pending, payload=agent draft)`。
+2. 董事会批准或拒绝。
+3. 批准后,服务端创建智能体记录和初始 API 密钥(可选)。
+4. 决策记录到 `activity_log`。
-Board can bypass request flow and create agents directly via UI; direct create is still logged as a governance action.
+董事会可绕过申请流程直接通过 UI 创建智能体;直接创建仍作为治理操作记录。
-## 12.2 CEO Strategy Approval
+## 12.2 CEO 战略审批
-1. CEO posts strategy proposal as `approval(type=approve_ceo_strategy)`.
-2. Board reviews payload (plan text, initial structure, high-level tasks).
-3. Approval unlocks execution state for CEO-created delegated work.
+1. CEO 提交战略提案,形式为 `approval(type=approve_ceo_strategy)`。
+2. 董事会审阅负载(计划文本、初始结构、高层级任务)。
+3. 审批通过后解锁 CEO 创建的委派工作的执行状态。
-Before first strategy approval, CEO may only draft tasks, not transition them to active execution states.
+在首次战略审批通过之前,CEO 只能起草任务,不能将其转换为活跃执行状态。
-## 12.3 Board Override
+## 12.3 董事会覆盖
-Board can at any time:
+董事会可随时:
-- pause/resume/terminate any agent
-- reassign or cancel any task
-- edit budgets and limits
-- approve/reject/cancel pending approvals
+- 暂停/恢复/终止任意智能体
+- 重新分配或取消任意任务
+- 编辑预算和限制
+- 批准/拒绝/取消待处理的审批
-## 13. Cost and Budget System
+## 13. 成本与预算系统
-## 13.1 Budget Layers
+## 13.1 预算层级
-- company monthly budget
-- agent monthly budget
-- optional project budget (if configured)
+- 公司月度预算
+- 智能体月度预算
+- 可选的项目预算(若已配置)
-## 13.2 Enforcement Rules
+## 13.2 执行规则
-- soft alert default threshold: 80%
-- hard limit: at 100%, trigger:
- - set agent status to `paused`
- - block new checkout/invocation for that agent
- - emit high-priority activity event
+- 软性警报默认阈值:80%
+- 硬上限:达到 100% 时触发:
+ - 将智能体状态设为 `paused`
+ - 阻止该智能体的新检出/调用
+ - 发出高优先级活动事件
-Board may override by raising budget or explicitly resuming agent.
+董事会可通过提升预算或明确恢复智能体来覆盖此行为。
-## 13.3 Cost Event Ingestion
+## 13.3 成本事件采集
-`POST /companies/:companyId/cost-events` body:
+`POST /companies/:companyId/cost-events` 请求体:
```json
{
@@ -684,16 +685,16 @@ Board may override by raising budget or explicitly resuming agent.
}
```
-Validation:
+验证:
-- non-negative token counts
+- Token 数量不能为负
- `costCents >= 0`
-- company ownership checks for all linked entities
+- 对所有关联实体进行公司归属检查
-## 13.4 Rollups
+## 13.4 汇总
-Read-time aggregate queries are acceptable for V1.
-Materialized rollups can be added later if query latency exceeds targets.
+V1 可接受读取时聚合查询。
+若查询延迟超出目标,后续可添加物化汇总。
## 14. UI Requirements (Board App)
diff --git a/doc/SPEC.md b/doc/SPEC.md
index 6a7039ca67..acd3440d9c 100644
--- a/doc/SPEC.md
+++ b/doc/SPEC.md
@@ -1,210 +1,210 @@
-# Paperclip Specification
+# Paperclip 规范
-Target specification for the Paperclip control plane. Living document — updated incrementally during spec interviews.
+Paperclip 控制平面的目标规范。活文档——在规范访谈过程中增量更新。
---
-## 1. Company Model [DRAFT]
+## 1. 公司模型 [草案]
-A Company is a first-order object. One Paperclip instance runs multiple Companies. A Company does not have a standalone "goal" field — its direction is defined by its set of Initiatives (see Task Hierarchy Mapping).
+公司是一级对象。一个 Paperclip 实例运行多个公司。公司没有独立的"目标"字段——其方向由其一组战略计划(Initiative)定义(见任务层级映射)。
-### Fields (Draft)
+### 字段(草案)
-| Field | Type | Notes |
+| 字段 | 类型 | 说明 |
| ----------- | ------------- | --------------------------------- |
-| `id` | uuid | Primary key |
-| `name` | string | Company name |
+| `id` | uuid | 主键 |
+| `name` | string | 公司名称 |
| `createdAt` | timestamp | |
| `updatedAt` | timestamp | |
-### Board Governance [DRAFT]
+### 董事会治理 [草案]
-Every Company has a **Board** that governs high-impact decisions. The Board is the human oversight layer.
+每个公司都有一个**董事会**来管理高影响力决策。董事会是人类监督层。
-**V1: Single human Board.** One human operator.
+**V1:单人董事会。** 一名人类操作员。
-#### Board Approval Gates (V1)
+#### 董事会审批门控(V1)
-- New Agent hires (creating new Agents)
-- CEO's initial strategic breakdown (CEO proposes, Board approves before execution begins)
-- [TBD: other governance-gated actions — goal changes, firing Agents?]
+- 新代理招聘(创建新代理)
+- CEO 的初始战略分解(CEO 提议,董事会在执行开始前批准)
+- [待定:其他治理门控操作——目标变更、解雇代理?]
-#### Board Powers (Always Available)
+#### 董事会权力(始终可用)
-The Board has **unrestricted access** to the entire system at all times:
+董事会在任何时候都对整个系统拥有**无限制访问权**:
-- **Set and modify Company budgets** — the Board sets top-level token/LLM cost budgets
-- **Pause/resume any Agent** — stop an Agent's heartbeat immediately
-- **Pause/resume any work item** — pause a task, project, subtask tree, milestone. Paused items are not picked up by Agents.
-- **Full project management access** — create, edit, comment on, modify, delete, reassign any task/project/milestone through the UI
-- **Override any Agent decision** — reassign tasks, change priorities, modify descriptions
-- **Manually change any budget** at any level
+- **设置和修改公司预算** —— 董事会设置顶层 token/LLM 成本预算
+- **暂停/恢复任何代理** —— 立即停止代理的心跳
+- **暂停/恢复任何工作项** —— 暂停任务、项目、子任务树、里程碑。暂停的项目不会被代理接取。
+- **完整的项目管理访问权** —— 通过 UI 创建、编辑、评论、修改、删除、重新分配任何任务/项目/里程碑
+- **覆盖任何代理决策** —— 重新分配任务、更改优先级、修改描述
+- **手动更改任何级别的预算**
-The Board is not just an approval gate — it's a live control surface. The human can intervene at any level at any time.
+董事会不仅仅是审批门控——它是一个实时控制面板。人类可以在任何时间、任何层级进行干预。
-#### Budget Delegation
+#### 预算委托
-The Board sets Company-level budgets. The CEO can set budgets for Agents below them, and every manager Agent can do the same for their reports. How this cascading budget delegation works in practice is TBD, but the permission structure supports it. The Board can manually override any budget at any level.
+董事会设置公司级预算。CEO 可以为其下属代理设置预算,每个管理代理也可以为其下属做同样的事情。这种级联预算委托在实践中如何运作尚待确定,但权限结构支持它。董事会可以手动覆盖任何级别的任何预算。
-**Future governance models** (not V1):
+**未来治理模型**(非 V1):
-- Hiring budgets (auto-approve hires within $X/month)
-- Multi-member boards
-- Delegated authority (CEO can hire within limits)
+- 招聘预算(在 $X/月内自动批准招聘)
+- 多成员董事会
+- 委托权限(CEO 可以在限制内招聘)
-### Open Questions
+### 开放问题
-- External revenue/expense tracking — future plugin. Token/LLM cost budgeting is core.
-- Company-level settings and configuration?
-- Company lifecycle (pause, archive, delete)?
-- What governance-gated actions exist beyond hiring and CEO strategy approval?
+- 外部收入/支出跟踪——未来的插件。Token/LLM 成本预算是核心功能。
+- 公司级设置和配置?
+- 公司生命周期(暂停、归档、删除)?
+- 除招聘和 CEO 战略审批外,还有哪些治理门控操作?
---
-## 2. Agent Model [DRAFT]
+## 2. 代理模型 [草案]
-Every employee is an agent. Agents are the workforce.
+每个员工都是一个代理。代理是劳动力。
-### Agent Identity (Adapter-Level)
+### 代理身份(适配器层)
-Concepts like SOUL.md (identity/mission) and HEARTBEAT.md (loop definition) are **not part of the Paperclip protocol**. They are adapter-specific configurations. For example, an OpenClaw adapter might use SOUL.md and HEARTBEAT.md files. A Claude Code adapter might use CLAUDE.md. A bare Python script might use command-line args.
+SOUL.md(身份/使命)和 HEARTBEAT.md(循环定义)等概念**不是 Paperclip 协议的一部分**。它们是适配器特定的配置。例如,OpenClaw 适配器可能使用 SOUL.md 和 HEARTBEAT.md 文件。Claude Code 适配器可能使用 CLAUDE.md。纯 Python 脚本可能使用命令行参数。
-Paperclip doesn't prescribe how an agent defines its identity or behavior. It provides the control plane; the adapter defines the agent's inner workings.
+Paperclip 不规定代理如何定义其身份或行为。它提供控制平面;适配器定义代理的内部工作机制。
-### Agent Configuration [DRAFT]
+### 代理配置 [草案]
-Each agent has an **adapter type** and an **adapter-specific configuration blob**. The adapter defines what config fields exist.
+每个代理都有一个**适配器类型**和一个**适配器特定的配置数据块**。适配器定义存在哪些配置字段。
-#### Paperclip Protocol (What Paperclip Knows)
+#### Paperclip 协议(Paperclip 所知的)
-At the protocol level, Paperclip tracks:
+在协议层面,Paperclip 跟踪:
-- Agent identity (id, name, role, title)
-- Org position (who they report to, who reports to them)
-- Adapter type + adapter config
-- Status (active, paused, terminated)
-- Cost tracking data (if the agent reports it)
+- 代理身份(id、名称、角色、头衔)
+- 组织位置(向谁汇报、谁向其汇报)
+- 适配器类型 + 适配器配置
+- 状态(活跃、暂停、已终止)
+- 成本跟踪数据(如果代理报告的话)
-#### Adapter Configuration (Agent-Specific)
+#### 适配器配置(代理特定)
-Each adapter type defines its own config schema. Examples:
+每种适配器类型定义自己的配置模式。示例:
-- **OpenClaw adapter**: SOUL.md content, HEARTBEAT.md content, OpenClaw-specific settings
-- **Process adapter**: command to run, environment variables, working directory
-- **HTTP adapter**: endpoint URL, auth headers, payload template
+- **OpenClaw 适配器**:SOUL.md 内容、HEARTBEAT.md 内容、OpenClaw 特定设置
+- **进程适配器**:要运行的命令、环境变量、工作目录
+- **HTTP 适配器**:端点 URL、认证头、载荷模板
-#### Exportable Org Configs
+#### 可导出的组织配置
-A key goal: **the entire org's agent configurations are exportable.** You can export a company's complete agent setup — every agent, their adapter configs, org structure — as a portable artifact. This enables:
+关键目标:**整个组织的代理配置是可导出的。** 你可以将公司的完整代理设置——每个代理、它们的适配器配置、组织结构——导出为可移植的产物。这使得以下操作成为可能:
-- Sharing company templates ("here's a pre-built marketing agency org")
-- Version controlling your company configuration
-- Duplicating/forking companies
+- 共享公司模板("这是一个预构建的营销公司组织")
+- 对公司配置进行版本控制
+- 复制/分叉公司
-#### Context Delivery
+#### 上下文传递
-Configurable per agent. Two ends of the spectrum:
+每个代理可配置。两个极端:
-- **Fat payload** — Paperclip bundles relevant context (current tasks, messages, company state, metrics) into the heartbeat invocation. Suited for simple/stateless agents that can't call back to Paperclip.
-- **Thin ping** — Heartbeat is just a wake-up signal. Agent calls Paperclip's API to fetch whatever context it needs. Suited for sophisticated agents that manage their own state.
+- **胖载荷** —— Paperclip 将相关上下文(当前任务、消息、公司状态、指标)打包到心跳调用中。适合无法回调 Paperclip 的简单/无状态代理。
+- **瘦 ping** —— 心跳只是一个唤醒信号。代理调用 Paperclip 的 API 来获取所需的上下文。适合管理自己状态的复杂代理。
-#### Minimum Contract
+#### 最低契约
-The minimum requirement to be a Paperclip agent: **be callable.** That's it. Paperclip can invoke you via command or webhook. No requirement to report back — Paperclip infers basic status from process liveness when it can.
+成为 Paperclip 代理的最低要求:**可调用。** 就这样。Paperclip 可以通过命令或 webhook 调用你。不要求回报——Paperclip 在可能时从进程存活状态推断基本状态。
-#### Integration Levels
+#### 集成级别
-Beyond the minimum, Paperclip provides progressively richer integration:
+在最低要求之上,Paperclip 提供逐步丰富的集成:
-1. **Callable** (minimum) — Paperclip can start you. That's the only contract.
-2. **Status reporting** — Agent reports back success/failure/in-progress after execution.
-3. **Fully instrumented** — Agent reports status, cost/token usage, task updates, and logs. Bidirectional integration with the control plane.
+1. **可调用**(最低)—— Paperclip 可以启动你。这是唯一的契约。
+2. **状态报告** —— 代理在执行后报告成功/失败/进行中。
+3. **完全仪表化** —— 代理报告状态、成本/token 使用、任务更新和日志。与控制平面的双向集成。
-Paperclip ships **default agents** that demonstrate full integration: progress tracking, cost instrumentation, and a **Paperclip skill** (a Claude Code skill for interacting with the Paperclip API) for task management. These serve as both useful defaults and reference implementations for adapter authors.
+Paperclip 附带**默认代理**,展示完整集成:进度跟踪、成本仪表化,以及用于任务管理的 **Paperclip 技能**(与 Paperclip API 交互的 Claude Code 技能)。这些既是有用的默认设置,也是适配器作者的参考实现。
-#### Export Formats
+#### 导出格式
-Two export modes:
+两种导出模式:
-1. **Template export** (default) — structure only: agent definitions, org chart, adapter configs, role descriptions. Optionally includes a few seed tasks to help get started. This is the blueprint for spinning up a new company.
-2. **Snapshot export** — full state: structure + current tasks, progress, agent status. A complete picture you could restore or fork.
+1. **模板导出**(默认)—— 仅结构:代理定义、组织图、适配器配置、角色描述。可选包含一些种子任务以帮助入门。这是启动新公司的蓝图。
+2. **快照导出** —— 完整状态:结构 + 当前任务、进度、代理状态。可以恢复或分叉的完整画面。
-The usual workflow: export a template, create a new company from it, add a couple initial tasks, go.
+通常的工作流程:导出模板,从中创建新公司,添加几个初始任务,开始。
---
-## 3. Org Structure [DRAFT]
+## 3. 组织结构 [草案]
-Hierarchical reporting structure. CEO at top, reports cascade down.
+层级汇报结构。CEO 在顶部,汇报关系向下级联。
-### Agent Visibility
+### 代理可见性
-**Full visibility across the org.** Every agent can see the entire org chart, all tasks, all agents. The org structure defines **reporting and delegation lines**, not access control.
+**组织内完全可见。** 每个代理都可以看到整个组织图、所有任务、所有代理。组织结构定义**汇报和委托线**,而非访问控制。
-Each agent publishes a short description of their responsibilities and capabilities — almost like skills ("when I'm relevant"). This lets other agents discover who can help with what.
+每个代理发布其职责和能力的简短描述——几乎像技能("当我相关时")。这让其他代理发现谁可以帮助什么。
-### Cross-Team Work
+### 跨团队工作
-Agents can create tasks and assign them to agents outside their reporting line. This is the mechanism for cross-team collaboration. These rules are primarily encoded in the Paperclip SKILL.md which is recommended for all agents. Paperclip the app enforces the tooling and some light governance, but the cross-team rules below are mainly implemented by agent decisions.
+代理可以创建任务并将其分配给其汇报线之外的代理。这是跨团队协作的机制。这些规则主要编码在推荐所有代理使用的 Paperclip SKILL.md 中。Paperclip 应用强制执行工具和一些轻量级治理,但以下跨团队规则主要由代理决策实现。
-#### Task Acceptance Rules
+#### 任务接受规则
-When an agent receives a task from outside their team:
+当代理从团队外部收到任务时:
-1. **Agrees it's appropriate + can do it** → complete it directly
-2. **Agrees it's appropriate + can't do it** → mark as blocked
-3. **Questions whether it's worth doing** → **cannot cancel it themselves.** Must reassign to their own manager, explain the situation. Manager decides whether to accept, reassign, or escalate.
+1. **同意适当 + 能做** → 直接完成
+2. **同意适当 + 做不了** → 标记为阻塞
+3. **质疑是否值得做** → **不能自己取消。** 必须重新分配给自己的经理,解释情况。经理决定是否接受、重新分配或升级。
-#### Manager Escalation Protocol
+#### 经理升级协议
-It's any manager's responsibility to understand why their subordinates are blocked and resolve it:
+任何经理都有责任了解其下属被阻塞的原因并解决:
-0. **Decide** — as a manager, is this work worth doing?
-1. **Delegate down** — ask someone under them to help unblock
-2. **Escalate up** — ask the manager above them for help
+0. **决定** —— 作为经理,这项工作值得做吗?
+1. **向下委托** —— 让下属帮助解除阻塞
+2. **向上升级** —— 向上级经理寻求帮助
-#### Request Depth Tracking
+#### 请求深度跟踪
-When a task originates from a cross-team request, track the **depth** as an integer — how many delegation hops from the original requester. This provides visibility into how far work cascades through the org.
+当任务源自跨团队请求时,将**深度**作为整数跟踪——从原始请求者到当前经过了多少次委托跳转。这提供了工作在组织中级联程度的可见性。
-#### Billing Codes
+#### 计费代码
-Tasks carry a **billing code** so that token spend during execution can be attributed upstream to the requesting task/agent. When Agent A asks Agent B to do work, the cost of B's work is tracked against A's request. This enables cost attribution across the org.
+任务携带**计费代码**,以便执行期间的 token 花费可以归属到上游请求的任务/代理。当代理 A 要求代理 B 做工作时,B 的工作成本被跟踪到 A 的请求上。这实现了跨组织的成本归属。
-### Open Questions
+### 开放问题
-- Is this a strict tree or can agents report to multiple managers?
-- Can org structure change at runtime? (agents reassigned, teams restructured)
-- Do agents inherit any configuration from their manager?
-- Billing code format — simple string? Hierarchical?
+- 这是严格的树形结构还是代理可以向多个经理汇报?
+- 组织结构能在运行时改变吗?(代理重新分配、团队重组)
+- 代理是否从其经理继承任何配置?
+- 计费代码格式——简单字符串?层级式?
---
-## 4. Heartbeat System [DRAFT]
+## 4. 心跳系统 [草案]
-The heartbeat is a protocol, not a runtime. Paperclip defines how to initiate an agent's cycle. What the agent does with that cycle — how long it runs, whether it's task-scoped or continuous — is entirely up to the agent.
+心跳是一个协议,不是运行时。Paperclip 定义如何启动代理的周期。代理如何使用该周期——运行多长时间、是面向任务的还是持续的——完全由代理决定。
-### Execution Adapters
+### 执行适配器
-Agent configuration includes an **adapter** that defines how Paperclip invokes the agent. Built-in adapters include:
+代理配置包括一个**适配器**,定义 Paperclip 如何调用代理。内置适配器包括:
-| Adapter | Mechanism | Example |
+| 适配器 | 机制 | 示例 |
| ---------------- | -------------------------- | -------------------------------------------------- |
-| `process` | Execute a child process | `python run_agent.py --agent-id {id}` |
-| `http` | Send an HTTP request | `POST https://openclaw.example.com/hook/{id}` |
-| `claude_local` | Local Claude Code process | Claude Code heartbeat worker |
-| `codex_local` | Local Codex process | Codex CLI heartbeat worker |
-| `opencode_local` | Local OpenCode process | OpenCode heartbeat worker |
-| `pi_local` | Local Pi process | Pi CLI heartbeat worker |
-| `cursor` | Cursor API/CLI bridge | Cursor-integrated heartbeat worker |
-| `openclaw_gateway` | OpenClaw gateway API | Managed OpenClaw agent via gateway |
-| `hermes_local` | Local Hermes process | Hermes agent heartbeat worker |
+| `process` | 执行子进程 | `python run_agent.py --agent-id {id}` |
+| `http` | 发送 HTTP 请求 | `POST https://openclaw.example.com/hook/{id}` |
+| `claude_local` | 本地 Claude Code 进程 | Claude Code 心跳工作器 |
+| `codex_local` | 本地 Codex 进程 | Codex CLI 心跳工作器 |
+| `opencode_local` | 本地 OpenCode 进程 | OpenCode 心跳工作器 |
+| `pi_local` | 本地 Pi 进程 | Pi CLI 心跳工作器 |
+| `cursor` | Cursor API/CLI 桥接 | Cursor 集成心跳工作器 |
+| `openclaw_gateway` | OpenClaw 网关 API | 通过网关管理的 OpenClaw 代理 |
+| `hermes_local` | 本地 Hermes 进程 | Hermes 代理心跳工作器 |
-The `process` and `http` adapters ship as generic defaults. Additional built-in adapters cover common local coding runtimes (see list above), and new adapter types can be registered via the plugin system (see Plugin / Extension Architecture).
+`process` 和 `http` 适配器作为通用默认值附带。额外的内置适配器覆盖常见的本地编码运行时(见上表),新的适配器类型可以通过插件系统注册(见插件/扩展架构)。
-### Adapter Interface
+### 适配器接口
-Every adapter implements three methods:
+每个适配器实现三个方法:
```
invoke(agentConfig, context?) → void // Start the agent's cycle
@@ -212,320 +212,320 @@ status(agentConfig) → AgentStatus // Is it running? finished? errored?
cancel(agentConfig) → void // Graceful stop signal (for pause/resume)
```
-This is the full adapter contract. `invoke` starts the agent, `status` lets Paperclip check on it, `cancel` enables the board's pause functionality. Everything else (cost reporting, task updates) is optional and flows through the Paperclip REST API.
+这就是完整的适配器契约。`invoke` 启动代理,`status` 让 Paperclip 检查代理状态,`cancel` 启用董事会的暂停功能。其他一切(成本报告、任务更新)都是可选的,通过 Paperclip REST API 进行。
-### What Paperclip Controls
+### Paperclip 控制的内容
-- **When** to fire the heartbeat (schedule/frequency, per-agent)
-- **How** to fire it (adapter selection + config)
-- **What context** to include (thin ping vs. fat payload, per-agent)
+- **何时**触发心跳(调度/频率,每个代理)
+- **如何**触发(适配器选择 + 配置)
+- **包含什么上下文**(瘦 ping vs. 胖载荷,每个代理)
-### What Paperclip Does NOT Control
+### Paperclip 不控制的内容
-- How long the agent runs
-- What the agent does during its cycle
-- Whether the agent is task-scoped, time-windowed, or continuous
+- 代理运行多长时间
+- 代理在其周期内做什么
+- 代理是面向任务的、时间窗口的还是持续的
-### Pause Behavior
+### 暂停行为
-When the board (or system) pauses an agent:
+当董事会(或系统)暂停代理时:
-1. **Signal the current execution** — send a graceful termination signal to the running process/session
-2. **Grace period** — give the agent time to wrap up, save state, report final status
-3. **Force-kill after timeout** — if the agent doesn't stop within the grace period, terminate
-4. **Stop future heartbeats** — no new heartbeat cycles will fire until the agent is resumed
+1. **发送当前执行的信号** —— 向正在运行的进程/会话发送优雅终止信号
+2. **宽限期** —— 给代理时间收尾、保存状态、报告最终状态
+3. **超时后强制终止** —— 如果代理在宽限期内没有停止,则终止
+4. **停止未来心跳** —— 在代理恢复之前不会触发新的心跳周期
-This is "graceful signal + stop future heartbeats." The current run gets a chance to land cleanly.
+这是"优雅信号 + 停止未来心跳"。当前运行有机会干净地着陆。
-### Open Questions
+### 开放问题
-- Heartbeat frequency — who controls it? Fixed? Per-agent? Cron-like?
-- What happens when a heartbeat invocation fails? (process crashes, HTTP 500)
-- Health monitoring — how does Paperclip distinguish "stuck" from "working on a long task"?
-- Can agents self-trigger their next heartbeat? ("I'm done, wake me again in 5 min")
-- Grace period duration — fixed? configurable per agent?
+- 心跳频率——谁控制?固定的?每个代理?类 cron?
+- 心跳调用失败时会发生什么?(进程崩溃、HTTP 500)
+- 健康监控——Paperclip 如何区分"卡住"和"正在处理长任务"?
+- 代理能自触发下一次心跳吗?("我完成了,5 分钟后再叫醒我")
+- 宽限期时长——固定?每个代理可配置?
---
-## 5. Inter-Agent Communication [DRAFT]
+## 5. 代理间通信 [草案]
-All agent communication flows through the **task system**.
+所有代理通信都通过**任务系统**进行。
-### Model: Tasks + Comments
+### 模型:任务 + 评论
-- **Delegation** = creating a task and assigning it to another agent
-- **Coordination** = commenting on tasks
-- **Status updates** = updating task status and fields
+- **委托** = 创建任务并分配给另一个代理
+- **协调** = 在任务上评论
+- **状态更新** = 更新任务状态和字段
-There is no separate messaging or chat system. Tasks are the communication channel. This keeps all context attached to the work it relates to and creates a natural audit trail.
+没有单独的消息传递或聊天系统。任务是通信渠道。这将所有上下文附加到其相关的工作上,并创建自然的审计轨迹。
-### Implications
+### 含义
-- An agent's "inbox" is: tasks assigned to them + comments on tasks they're involved in
-- The CEO delegates by creating tasks assigned to the CTO
-- The CTO breaks those down into sub-tasks assigned to engineers
-- Discussion happens in task comments, not a side channel
-- If an agent needs to escalate, they comment on the parent task or reassign
+- 代理的"收件箱"是:分配给它们的任务 + 它们参与的任务上的评论
+- CEO 通过创建分配给 CTO 的任务来委托
+- CTO 将这些分解为分配给工程师的子任务
+- 讨论在任务评论中进行,而不是在侧信道中
+- 如果代理需要升级,它们在父任务上评论或重新分配
-### Task Hierarchy Mapping
+### 任务层级映射
-Full hierarchy: **Initiative** (company goal) → Projects → Milestones → Issues → Sub-issues. Everything traces back to an initiative, and the "company goal" is just the first/primary initiative.
+完整层级:**战略计划**(公司目标)→ 项目 → 里程碑 → 问题 → 子问题。一切都追溯到一个战略计划,"公司目标"只是第一个/主要的战略计划。
---
-## 6. Cost Tracking [DRAFT]
+## 6. 成本跟踪 [草案]
-Token/LLM cost budgeting is a core part of Paperclip. External revenue and expense tracking is a future plugin.
+Token/LLM 成本预算是 Paperclip 的核心部分。外部收入和支出跟踪是未来的插件。
-### Cost Reporting
+### 成本报告
-Fully-instrumented Agents report token/API usage back to Paperclip. Costs are tracked at every level:
+完全仪表化的代理向 Paperclip 报告 token/API 使用情况。成本在每个级别跟踪:
-- **Per Agent** — how much is this employee costing?
-- **Per task** — how much did this unit of work cost?
-- **Per project** — how much is this deliverable costing?
-- **Per Company** — total burn rate
+- **每个代理** —— 这个员工花费了多少?
+- **每个任务** —— 这个工作单元花费了多少?
+- **每个项目** —— 这个交付物花费了多少?
+- **每个公司** —— 总消耗率
-Costs should be denominated in both **tokens and dollars**.
+成本应以 **token 和美元**两种方式计价。
-Billing codes on tasks (see Org Structure) enable cost attribution across teams — when Agent A requests work from Agent B, B's costs roll up to A's request.
+任务上的计费代码(见组织结构)实现跨团队的成本归属——当代理 A 请求代理 B 做工作时,B 的成本汇总到 A 的请求上。
-### Budget Controls
+### 预算控制
-Three tiers:
+三个层级:
-1. **Visibility** — dashboards showing spend at every level (Agent, task, project, Company)
-2. **Soft alerts** — configurable thresholds (e.g. warn at 80% of budget)
-3. **Hard ceiling** — auto-pause the Agent when budget is hit. Board notified. Board can override/raise the limit.
+1. **可见性** —— 在每个级别(代理、任务、项目、公司)显示支出的仪表盘
+2. **软告警** —— 可配置的阈值(例如在预算的 80% 时警告)
+3. **硬上限** —— 当预算达到时自动暂停代理。通知董事会。董事会可以覆盖/提高限制。
-Budgets can be set to **unlimited** (no ceiling).
+预算可以设置为**无限制**(无上限)。
-### Open Questions
+### 开放问题
-- Cost reporting API — what's the schema for an agent to report costs?
-- Dashboard design — what metrics matter most at each level?
-- Budget period — per-day? per-week? per-month? rolling?
+- 成本报告 API——代理报告成本的模式是什么?
+- 仪表盘设计——每个级别最重要的指标是什么?
+- 预算周期——每天?每周?每月?滚动?
---
-## 7. Default Agents & Bootstrap Flow [DRAFT]
+## 7. 默认代理和引导流程 [草案]
-### Bootstrap Sequence
+### 引导序列
-How a Company goes from "created" to "running":
+公司如何从"已创建"到"运行中":
-1. Human creates a Company and its initial Initiatives
-2. Human defines initial top-level tasks
-3. Human creates the CEO Agent (using the default CEO template or custom)
-4. CEO's first heartbeat: reviews the Initiatives and tasks, proposes a strategic breakdown (org structure, sub-tasks, hiring plan)
-5. **Board approves** the CEO's strategic plan
-6. CEO begins execution — creating tasks, proposing hires (Board-approved), delegating
+1. 人类创建公司及其初始战略计划
+2. 人类定义初始顶层任务
+3. 人类创建 CEO 代理(使用默认 CEO 模板或自定义)
+4. CEO 的第一次心跳:审查战略计划和任务,提出战略分解(组织结构、子任务、招聘计划)
+5. **董事会批准** CEO 的战略计划
+6. CEO 开始执行——创建任务、提出招聘(需董事会批准)、委托
-### Default Agents
+### 默认代理
-Paperclip ships default Agent templates:
+Paperclip 附带默认代理模板:
-- **Default Agent** — a basic Claude Code or Codex loop. Knows the **Paperclip Skill** (SKILL.md) so it can interact with the task system, read Company context, report status.
-- **Default CEO** — extends the Default Agent with CEO-specific behavior: strategic planning, delegation to reports, progress review, Board communication.
+- **默认代理** —— 基本的 Claude Code 或 Codex 循环。了解 **Paperclip 技能**(SKILL.md),因此可以与任务系统交互、读取公司上下文、报告状态。
+- **默认 CEO** —— 扩展默认代理,具有 CEO 特定行为:战略规划、向下属委托、进度审查、与董事会沟通。
-These are starting points. Users can customize or replace them entirely.
+这些是起点。用户可以完全自定义或替换它们。
-### Default Agent Behavior
+### 默认代理行为
-The default agent's loop is **config-driven**. The adapter config contains the instructions that define what the agent does on each heartbeat cycle. There is no hardcoded standard loop — each agent's config determines its behavior.
+默认代理的循环是**配置驱动的**。适配器配置包含定义代理在每个心跳周期做什么的指令。没有硬编码的标准循环——每个代理的配置决定其行为。
-This means the default CEO config tells the CEO to review strategy, check on reports, etc. The default engineer config tells the engineer to check assigned tasks, pick the highest priority, and work it. But these are config choices, not protocol requirements.
+这意味着默认 CEO 配置告诉 CEO 审查战略、检查下属等。默认工程师配置告诉工程师检查分配的任务、选择最高优先级的任务并执行。但这些是配置选择,不是协议要求。
-### Paperclip Skill (SKILL.md)
+### Paperclip 技能(SKILL.md)
-A skill definition that teaches agents how to interact with Paperclip. Provides:
+教代理如何与 Paperclip 交互的技能定义。提供:
-- Task CRUD (create, read, update, complete tasks)
-- Status reporting (check in, report progress)
-- Company context (read goal, org chart, current state)
-- Cost reporting (log token/API usage)
-- Inter-agent communication rules
+- 任务 CRUD(创建、读取、更新、完成任务)
+- 状态报告(签到、报告进度)
+- 公司上下文(读取目标、组织图、当前状态)
+- 成本报告(记录 token/API 使用)
+- 代理间通信规则
-This skill is adapter-agnostic — it can be loaded into Claude Code, injected into prompts, or used as API documentation for custom agents.
+这个技能是适配器无关的——它可以加载到 Claude Code 中、注入到提示中,或用作自定义代理的 API 文档。
---
-## 8. Architecture & Deployment [DRAFT]
+## 8. 架构与部署 [草案]
-### Deployment Model
+### 部署模型
-**Single-tenant, self-hostable.** Not a SaaS. One instance = one operator's companies.
+**单租户、可自托管。** 不是 SaaS。一个实例 = 一个操作员的公司。
-#### Development Path (Progressive Deployment)
+#### 开发路径(渐进式部署)
-1. **Local dev** — One command to install and run. Embedded Postgres. Everything on your machine. Agents run locally.
-2. **Hosted** — Deploy to Vercel/Supabase/AWS/anywhere. Remote agents connect to your server with a shared database. The UI is accessible via the web.
-3. **Open company** — Optionally make parts public (e.g. a job board visible to the public for open companies).
+1. **本地开发** —— 一条命令安装和运行。嵌入式 Postgres。一切都在你的机器上。代理在本地运行。
+2. **托管** —— 部署到 Vercel/Supabase/AWS/任何地方。远程代理通过共享数据库连接到你的服务器。UI 可通过网络访问。
+3. **开放公司** —— 可选地公开部分内容(例如对开放公司可见的招聘板)。
-The key constraint: it must be trivial to go from "I'm trying this on my machine" to "my agents are running on remote servers talking to my Paperclip instance."
+关键约束:从"我在我的机器上试用"到"我的代理在远程服务器上运行并与我的 Paperclip 实例通信"必须是简单的。
-#### Agent Authentication
+#### 代理认证
-When a user creates an Agent, Paperclip generates a **connection string** containing: the server URL, an API key, and instructions for how to authenticate. The Agent is assumed to be capable of figuring out how to call the API with its token/key from there.
+当用户创建代理时,Paperclip 生成一个**连接字符串**,包含:服务器 URL、API 密钥和认证说明。假设代理能够从中弄清楚如何使用其 token/密钥调用 API。
-Flow:
+流程:
-1. Human creates an Agent in the UI
-2. Paperclip generates a connection string (URL + key + instructions)
-3. Human provides this string to the Agent (e.g. in its adapter config, environment, etc.)
-4. Agent uses the key to authenticate API calls to the control plane
+1. 人类在 UI 中创建代理
+2. Paperclip 生成连接字符串(URL + 密钥 + 说明)
+3. 人类将此字符串提供给代理(例如在其适配器配置、环境等中)
+4. 代理使用密钥对控制平面的 API 调用进行认证
-### Tech Stack
+### 技术栈
-| Layer | Technology |
-| -------- | ------------------------------------------------------------ |
-| Frontend | React + Vite |
-| Backend | TypeScript + Express (REST API, not tRPC — need non-TS clients) |
-| Database | PostgreSQL (see [doc/DATABASE.md](./doc/DATABASE.md) for details — PGlite embedded for dev, Docker or hosted Supabase for production) |
-| Auth | [Better Auth](https://www.better-auth.com/) |
+| 层 | 技术 |
+| ---------- | ------------------------------------------------------------ |
+| 前端 | React + Vite |
+| 后端 | TypeScript + Express(REST API,不是 tRPC——需要非 TS 客户端)|
+| 数据库 | PostgreSQL(详见 [doc/DATABASE.md](./doc/DATABASE.md)——开发用 PGlite 嵌入式,生产用 Docker 或托管 Supabase)|
+| 认证 | [Better Auth](https://www.better-auth.com/) |
-### Concurrency Model: Atomic Task Checkout
+### 并发模型:原子任务签出
-Tasks use **single assignment** (one agent per task) with **atomic checkout**:
+任务使用**单分配**(每个任务一个代理)和**原子签出**:
-1. Agent attempts to set a task to `in_progress` (claiming it)
-2. The API/database enforces this atomically — if another agent already claimed it, the request fails with an error identifying which agent has it
-3. If the task is already assigned to the requesting agent from a previous session, they can resume
+1. 代理尝试将任务设置为 `in_progress`(认领它)
+2. API/数据库以原子方式执行此操作——如果另一个代理已经认领了它,请求会失败并返回识别哪个代理持有它的错误
+3. 如果任务已经从先前的会话分配给请求的代理,他们可以恢复
-No optimistic locking or CRDTs needed. The single-assignment model + atomic checkout prevents conflicts at the design level.
+不需要乐观锁定或 CRDT。单分配模型 + 原子签出在设计层面防止冲突。
-### Human in the Loop
+### 人在回路中
-Agents can create tasks assigned to humans. The board member (or any human with access) can complete these tasks through the UI.
+代理可以创建分配给人类的任务。董事会成员(或任何有访问权的人类)可以通过 UI 完成这些任务。
-When a human completes a task, if the requesting agent's adapter supports **pingbacks** (e.g. OpenClaw hooks), Paperclip sends a notification to wake that agent. This keeps humans rare but possible participants in the workflow.
+当人类完成任务时,如果请求代理的适配器支持**回调 ping**(例如 OpenClaw 钩子),Paperclip 发送通知唤醒该代理。这使人类成为工作流中罕见但可能的参与者。
-The agents are discouraged from assigning tasks to humans in the Paperclip SKILL, but sometimes it's unavoidable.
+在 Paperclip SKILL 中不鼓励代理将任务分配给人类,但有时这是不可避免的。
-### API Design
+### API 设计
-**Single unified REST API.** The same API serves both the frontend UI and agents. Authentication determines permissions — board auth has full access, agent API keys have scoped access (their own tasks, cost reporting, company context).
+**单一统一 REST API。** 同一个 API 同时服务前端 UI 和代理。认证决定权限——董事会认证有完全访问权,代理 API 密钥有范围化访问权(他们自己的任务、成本报告、公司上下文)。
-No separate "agent API" vs. "board API." Same endpoints, different authorization levels.
+没有单独的"代理 API"与"董事会 API"。相同的端点,不同的授权级别。
-### Work Artifacts
+### 工作产物
-Paperclip manages task-linked work artifacts: issue documents (rich-text plans, specs, notes attached to issues) and file attachments. Agents read and write these through the API as part of normal task execution. Full delivery infrastructure (code repos, deployments, production runtime) remains the agent's domain — Paperclip orchestrates the work, not the build pipeline.
+Paperclip 管理与任务关联的工作产物:问题文档(附加到问题的富文本计划、规格、笔记)和文件附件。代理通过 API 作为正常任务执行的一部分读写这些。完整的交付基础设施(代码仓库、部署、生产运行时)仍然是代理的领域——Paperclip 编排工作,而不是构建管道。
-### Open Questions
+### 开放问题
-- Real-time updates to the UI — WebSocket? SSE? Polling?
-- Agent API key scoping — what exactly can an Agent access? Only their own tasks? Their team's? The whole Company?
+- UI 的实时更新——WebSocket?SSE?轮询?
+- 代理 API 密钥范围——代理到底可以访问什么?只有自己的任务?团队的?整个公司?
-### Crash Recovery: Manual, Not Automatic
+### 崩溃恢复:手动,而非自动
-When an agent crashes or disappears mid-task, Paperclip does **not** auto-reassign or auto-release the task. Instead:
+当代理在任务中途崩溃或消失时,Paperclip **不会**自动重新分配或自动释放任务。相反:
-- Paperclip surfaces stale tasks (tasks in `in_progress` with no recent activity) through dashboards and reporting
-- Paperclip does not fail silently — the auditing and visibility tools make problems obvious
-- Recovery is handled by humans or by emergent processes (e.g. a project manager agent whose job is to monitor for stale work and surface it)
+- Paperclip 通过仪表盘和报告展示过期任务(处于 `in_progress` 状态且没有最近活动的任务)
+- Paperclip 不会静默失败——审计和可见性工具使问题显而易见
+- 恢复由人类或涌现的流程处理(例如一个项目经理代理,其工作是监控过期工作并展示它)
-**Principle: Paperclip reports problems, it doesn't silently fix them.** Automatic recovery hides failures. Good visibility lets the right entity (human or agent) decide what to do.
+**原则:Paperclip 报告问题,不静默修复它们。** 自动恢复隐藏故障。良好的可见性让正确的实体(人类或代理)决定该怎么做。
-### Plugin / Extension Architecture
+### 插件/扩展架构
-The core Paperclip system must be extensible. Features like knowledge bases, external revenue tracking, and new Agent Adapters should be addable as **plugins** without modifying core. This means:
+核心 Paperclip 系统必须是可扩展的。知识库、外部收入跟踪和新代理适配器等功能应该可以作为**插件**添加而无需修改核心。这意味着:
-- Well-defined API boundaries that plugins can hook into
-- Event system or hooks for reacting to task/Agent lifecycle events
-- **Agent Adapter plugins** — new Adapter types can be registered via the plugin system
-- Plugin-registrable UI components (future)
+- 插件可以接入的明确定义的 API 边界
+- 用于响应任务/代理生命周期事件的事件系统或钩子
+- **代理适配器插件** —— 新的适配器类型可以通过插件系统注册
+- 插件可注册的 UI 组件(未来)
-The plugin framework has shipped. Plugins can register new adapter types, hook into lifecycle events, and contribute UI components (e.g. global toolbar buttons). A plugin SDK and CLI commands (`paperclipai plugin`) are available for authoring and installing plugins.
+插件框架已发布。插件可以注册新的适配器类型、接入生命周期事件,并贡献 UI 组件(例如全局工具栏按钮)。插件 SDK 和 CLI 命令(`paperclipai plugin`)可用于编写和安装插件。
---
-## 9. Frontend / UI [DRAFT]
+## 9. 前端 / UI [草案]
-### Primary Views
+### 主要视图
-Each is a distinct page/route:
+每个都是独立的页面/路由:
-1. **Org Chart** — the org tree with live status indicators (running/idle/paused/error) per agent. Real-time activity feed of what agents are doing.
-2. **Task Board** — Task management. Kanban and list views. Filter by team, agent, project, status.
-3. **Dashboard** — high-level metrics: agent count, active tasks, costs, goal progress, burn rate. The "glance" view from GOAL.md.
-4. **Agent Detail** — deep dive on a single agent: their tasks, activity, costs, configuration, status history.
-5. **Project/Initiative Views** — progress tracking against milestones and goals.
-6. **Cost Dashboard** — spend visualization at every level (agent, task, project, company).
+1. **组织图** —— 带有每个代理实时状态指示器(运行中/空闲/暂停/错误)的组织树。代理正在做什么的实时活动流。
+2. **任务看板** —— 任务管理。看板和列表视图。按团队、代理、项目、状态筛选。
+3. **仪表盘** —— 高级指标:代理数量、活跃任务、成本、目标进度、消耗率。来自 GOAL.md 的"一览"视图。
+4. **代理详情** —— 单个代理的深入查看:他们的任务、活动、成本、配置、状态历史。
+5. **项目/战略计划视图** —— 针对里程碑和目标的进度跟踪。
+6. **成本仪表盘** —— 在每个级别(代理、任务、项目、公司)的支出可视化。
-### Board Controls (Available Everywhere)
+### 董事会控制(随处可用)
-- Pause/resume agents (any view)
-- Pause/resume tasks/projects (any view)
-- Approve/reject pending actions (hiring, strategy proposals)
-- Direct task creation, editing, commenting
+- 暂停/恢复代理(任何视图)
+- 暂停/恢复任务/项目(任何视图)
+- 批准/拒绝待处理操作(招聘、战略提案)
+- 直接任务创建、编辑、评论
---
-## 10. V1 Scope (MVP) [DRAFT]
-
-**Full loop with one adapter.** V1 must demonstrate the complete Paperclip cycle end-to-end, even if narrow.
-
-### Must Have (V1)
-
-- [ ] **Company CRUD** — create a Company with Initiatives
-- [ ] **Agent CRUD** — create/edit/pause/resume Agents with Adapter config
-- [ ] **Org chart** — define reporting structure, visualize it
-- [ ] **Process adapter** — invoke(), status(), cancel() for local child processes
-- [ ] **Task management** — full lifecycle with hierarchy (tasks trace to company goal)
-- [ ] **Atomic task checkout** — single assignment, in_progress locking
-- [ ] **Board governance** — human approves hires, pauses Agents, sets budgets, full PM access
-- [ ] **Cost tracking** — Agents report token usage, per-Agent/task/Company visibility
-- [ ] **Budget controls** — soft alerts + hard ceiling with auto-pause
-- [ ] **Default agent** — basic Claude Code/Codex loop with Paperclip skill
-- [ ] **Default CEO** — strategic planning, delegation, board communication
-- [ ] **Paperclip skill (SKILL.md)** — teaches agents to interact with the API
-- [ ] **REST API** — full API for agent interaction (Express)
-- [ ] **Web UI** — React/Vite: org chart, task board, dashboard, cost views
-- [ ] **Agent auth** — connection string generation with URL + key + instructions
-- [ ] **One-command dev setup** — embedded PGlite, everything local
-- [ ] **Multiple Adapter types** (HTTP, OpenClaw gateway, and local coding adapters)
-
-### Not V1
-
-- Knowledge base - a future plugin
-- Advanced governance models (hiring budgets, multi-member boards)
-- Revenue/expense tracking beyond token costs - a future plugin
-- Public job board / open company features
+## 10. V1 范围(MVP)[草案]
+
+**使用一个适配器完成完整循环。** V1 必须端到端展示完整的 Paperclip 周期,即使是狭窄的。
+
+### 必须有(V1)
+
+- [ ] **公司 CRUD** —— 创建带有战略计划的公司
+- [ ] **代理 CRUD** —— 使用适配器配置创建/编辑/暂停/恢复代理
+- [ ] **组织图** —— 定义汇报结构,可视化它
+- [ ] **进程适配器** —— 用于本地子进程的 invoke()、status()、cancel()
+- [ ] **任务管理** —— 带层级的完整生命周期(任务追溯到公司目标)
+- [ ] **原子任务签出** —— 单分配,in_progress 锁定
+- [ ] **董事会治理** —— 人类批准招聘、暂停代理、设置预算、完全的项目管理访问
+- [ ] **成本跟踪** —— 代理报告 token 使用,每个代理/任务/公司的可见性
+- [ ] **预算控制** —— 软告警 + 带自动暂停的硬上限
+- [ ] **默认代理** —— 带 Paperclip 技能的基本 Claude Code/Codex 循环
+- [ ] **默认 CEO** —— 战略规划、委托、董事会沟通
+- [ ] **Paperclip 技能(SKILL.md)** —— 教代理与 API 交互
+- [ ] **REST API** —— 用于代理交互的完整 API(Express)
+- [ ] **Web UI** —— React/Vite:组织图、任务看板、仪表盘、成本视图
+- [ ] **代理认证** —— 带 URL + 密钥 + 说明的连接字符串生成
+- [ ] **一条命令的开发设置** —— 嵌入式 PGlite,一切在本地
+- [ ] **多种适配器类型**(HTTP、OpenClaw 网关和本地编码适配器)
+
+### 非 V1
+
+- 知识库 - 未来的插件
+- 高级治理模型(招聘预算、多成员董事会)
+- 超出 token 成本的收入/支出跟踪 - 未来的插件
+- 公共招聘板 / 开放公司功能
---
-## 11. Knowledge Base
+## 11. 知识库
-**Anti-goal for core.** The knowledge base is not part of the Paperclip core — it will be a plugin. The task system + comments + agent descriptions provide sufficient shared context.
+**核心的反目标。** 知识库不是 Paperclip 核心的一部分——它将是一个插件。任务系统 + 评论 + 代理描述提供了足够的共享上下文。
-The architecture must support adding a knowledge base plugin later (clean API boundaries, hookable lifecycle events) but the core system explicitly does not include one.
+架构必须支持以后添加知识库插件(干净的 API 边界、可接入的生命周期事件),但核心系统明确不包含知识库。
---
-## 12. Anti-Requirements
+## 12. 反需求
-Things Paperclip explicitly does **not** do:
+Paperclip 明确**不做**的事情:
-- **Not an Agent runtime** — Paperclip orchestrates, Agents run elsewhere
-- **Not a knowledge base** — core has no wiki/docs/vector-DB (plugin territory)
-- **Not a SaaS** — single-tenant, self-hosted
-- **Not opinionated about Agent implementation** — any language, any framework, any runtime
-- **Not automatically self-healing** — surfaces problems, doesn't silently fix them
-- **Does not manage delivery infrastructure** — no repo management, no deployment, no file systems (but does manage task-linked documents and attachments)
-- **Does not auto-reassign work** — stale tasks are surfaced, not silently redistributed
-- **Does not track external revenue/expenses** — that's a future plugin. Token/LLM cost budgeting is core.
+- **不是代理运行时** —— Paperclip 编排,代理在其他地方运行
+- **不是知识库** —— 核心没有 wiki/文档/向量数据库(插件领域)
+- **不是 SaaS** —— 单租户,自托管
+- **对代理实现不持固定观点** —— 任何语言、任何框架、任何运行时
+- **不自动自愈** —— 展示问题,不静默修复
+- **不管理交付基础设施** —— 不管理代码仓库、部署、文件系统(但管理与任务关联的文档和附件)
+- **不自动重新分配工作** —— 过期任务被展示,而非静默重新分配
+- **不跟踪外部收入/支出** —— 那是未来的插件。Token/LLM 成本预算是核心。
---
-## 13. Principles (Consolidated)
-
-1. **Unopinionated about how you run your Agents.** Any language, any framework, any runtime. Paperclip is the control plane, not the execution plane.
-2. **Company is the unit of organization.** Everything lives under a Company.
-3. **Tasks are the communication channel.** All Agent communication flows through tasks + comments. No side channels.
-4. **All work traces to the goal.** Hierarchical task management — nothing exists in isolation.
-5. **Board governs.** Humans retain control through the Board. Conservative defaults (human approval required).
-6. **Surface problems, don't hide them.** Good auditing and visibility. No silent auto-recovery.
-7. **Atomic ownership.** Single assignee per task. Atomic checkout prevents conflicts.
-8. **Progressive deployment.** Trivial to start local, straightforward to scale to hosted.
-9. **Extensible core.** Clean boundaries so plugins can add capabilities (Adapters, knowledge base, revenue tracking) without modifying core.
+## 13. 原则(汇总)
+
+1. **对如何运行代理不持固定观点。** 任何语言、任何框架、任何运行时。Paperclip 是控制平面,不是执行平面。
+2. **公司是组织单位。** 一切都在公司之下。
+3. **任务是通信渠道。** 所有代理通信通过任务 + 评论进行。没有侧信道。
+4. **所有工作追溯到目标。** 层级化任务管理——没有什么是孤立存在的。
+5. **董事会治理。** 人类通过董事会保持控制。保守的默认值(需要人类批准)。
+6. **展示问题,不隐藏它们。** 良好的审计和可见性。没有静默自动恢复。
+7. **原子所有权。** 每个任务单一分配者。原子签出防止冲突。
+8. **渐进式部署。** 本地启动简单,扩展到托管也很直接。
+9. **可扩展的核心。** 干净的边界,使插件可以添加功能(适配器、知识库、收入跟踪)而无需修改核心。
diff --git a/doc/TASKS-mcp.md b/doc/TASKS-mcp.md
index c70cf3e40d..8650655de3 100644
--- a/doc/TASKS-mcp.md
+++ b/doc/TASKS-mcp.md
@@ -1,37 +1,35 @@
-# Task Management MCP Interface
+# 任务管理 MCP 接口
-Function contracts for the Paperclip task management system. Defines the
-operations available to agents (and external tools) via MCP. Refer to
-[TASKS.md](./TASKS.md) for the underlying data model.
+Paperclip 任务管理系统的函数契约。定义了智能体(及外部工具)通过 MCP 可用的操作。底层数据模型请参阅
+[TASKS.md](./TASKS.md)。
-All operations return JSON. IDs are UUIDs. Timestamps are ISO 8601.
-Issue identifiers (e.g. `ENG-123`) are accepted anywhere an issue `id` is
-expected.
+所有操作均返回 JSON。ID 为 UUID,时间戳为 ISO 8601 格式。
+在任何需要 issue `id` 的地方,均可接受 issue 标识符(例如 `ENG-123`)。
---
-## Issues
+## Issues(问题)
### `list_issues`
-List and filter issues in the workspace.
+列出并筛选工作区中的 issue。
| Parameter | Type | Required | Notes |
| ----------------- | -------- | -------- | ----------------------------------------------------------------------------------------------- |
-| `query` | string | no | Free-text search across title and description |
-| `teamId` | string | no | Filter by team |
-| `status` | string | no | Filter by specific workflow state |
-| `stateType` | string | no | Filter by state category: `triage`, `backlog`, `unstarted`, `started`, `completed`, `cancelled` |
-| `assigneeId` | string | no | Filter by assignee (agent id) |
-| `projectId` | string | no | Filter by project |
-| `parentId` | string | no | Filter by parent issue (returns sub-issues) |
-| `labelIds` | string[] | no | Filter to issues with ALL of these labels |
-| `priority` | number | no | Filter by priority (0-4) |
-| `includeArchived` | boolean | no | Include archived issues. Default: false |
-| `orderBy` | string | no | `created`, `updated`, `priority`, `due_date`. Default: `created` |
-| `limit` | number | no | Max results. Default: 50 |
-| `after` | string | no | Cursor for forward pagination |
-| `before` | string | no | Cursor for backward pagination |
+| `query` | string | no | 对标题和描述进行全文搜索 |
+| `teamId` | string | no | 按团队筛选 |
+| `status` | string | no | 按特定工作流状态筛选 |
+| `stateType` | string | no | 按状态类别筛选:`triage`、`backlog`、`unstarted`、`started`、`completed`、`cancelled` |
+| `assigneeId` | string | no | 按负责人筛选(智能体 ID) |
+| `projectId` | string | no | 按项目筛选 |
+| `parentId` | string | no | 按父 issue 筛选(返回子 issue) |
+| `labelIds` | string[] | no | 筛选同时包含所有这些标签的 issue |
+| `priority` | number | no | 按优先级筛选(0-4) |
+| `includeArchived` | boolean | no | 是否包含已归档的 issue。默认:false |
+| `orderBy` | string | no | `created`、`updated`、`priority`、`due_date`。默认:`created` |
+| `limit` | number | no | 最大结果数。默认:50 |
+| `after` | string | no | 向后翻页游标 |
+| `before` | string | no | 向前翻页游标 |
**Returns:** `{ issues: Issue[], pageInfo: { hasNextPage, endCursor, hasPreviousPage, startCursor } }`
@@ -39,91 +37,91 @@ List and filter issues in the workspace.
### `get_issue`
-Retrieve a single issue by ID or identifier, with all relations expanded.
+通过 ID 或标识符检索单个 issue,并展开所有关联关系。
| Parameter | Type | Required | Notes |
| --------- | ------ | -------- | -------------------------------------------------- |
-| `id` | string | yes | UUID or human-readable identifier (e.g. `ENG-123`) |
+| `id` | string | yes | UUID 或人类可读标识符(例如 `ENG-123`) |
-**Returns:** Full `Issue` object including:
+**Returns:** 完整的 `Issue` 对象,包含:
-- `state` (expanded WorkflowState)
-- `assignee` (expanded Agent, if set)
-- `labels` (expanded Label[])
-- `relations` (IssueRelation[] with expanded related issues)
-- `children` (sub-issue summaries: id, identifier, title, state, assignee)
-- `parent` (summary, if this is a sub-issue)
-- `comments` (Comment[], most recent first)
+- `state`(展开的 WorkflowState)
+- `assignee`(展开的 Agent,若已设置)
+- `labels`(展开的 Label[])
+- `relations`(IssueRelation[],含展开的关联 issue)
+- `children`(子 issue 摘要:id、identifier、title、state、assignee)
+- `parent`(摘要,若本 issue 为子 issue)
+- `comments`(Comment[],最新优先)
---
### `create_issue`
-Create a new issue.
+创建一个新 issue。
| Parameter | Type | Required | Notes |
| ------------- | -------- | -------- | --------------------------------------------- |
| `title` | string | yes | |
-| `teamId` | string | yes | Team the issue belongs to |
-| `description` | string | no | Markdown |
-| `status` | string | no | Workflow state. Default: team's default state |
-| `priority` | number | no | 0-4. Default: 0 (none) |
-| `estimate` | number | no | Point estimate |
-| `dueDate` | string | no | ISO date |
-| `assigneeId` | string | no | Agent to assign |
-| `projectId` | string | no | Project to associate with |
-| `milestoneId` | string | no | Milestone within the project |
-| `parentId` | string | no | Parent issue (makes this a sub-issue) |
-| `goalId` | string | no | Linked goal/objective |
-| `labelIds` | string[] | no | Labels to apply |
-| `sortOrder` | number | no | Ordering within views |
-
-**Returns:** Created `Issue` object with computed fields (`identifier`, `createdAt`, etc.)
+| `teamId` | string | yes | issue 所属的团队 |
+| `description` | string | no | Markdown 格式 |
+| `status` | string | no | 工作流状态。默认:团队默认状态 |
+| `priority` | number | no | 0-4。默认:0(无) |
+| `estimate` | number | no | 点数估算 |
+| `dueDate` | string | no | ISO 日期 |
+| `assigneeId` | string | no | 指派的智能体 |
+| `projectId` | string | no | 关联的项目 |
+| `milestoneId` | string | no | 项目内的里程碑 |
+| `parentId` | string | no | 父 issue(使本 issue 成为子 issue) |
+| `goalId` | string | no | 关联的目标/目的 |
+| `labelIds` | string[] | no | 要应用的标签 |
+| `sortOrder` | number | no | 视图内的排序顺序 |
-**Side effects:**
+**Returns:** 创建的 `Issue` 对象,包含计算字段(`identifier`、`createdAt` 等)。
+
+**副作用:**
-- If `parentId` is set, inherits `projectId` from parent (unless explicitly provided)
-- `identifier` is auto-generated from team key + next sequence number
+- 若设置了 `parentId`,则从父 issue 继承 `projectId`(除非显式提供)
+- `identifier` 由团队 key 加下一个序列号自动生成
---
### `update_issue`
-Update an existing issue.
+更新已有 issue。
| Parameter | Type | Required | Notes |
| ------------- | -------- | -------- | -------------------------------------------- |
-| `id` | string | yes | UUID or identifier |
+| `id` | string | yes | UUID 或标识符 |
| `title` | string | no | |
| `description` | string | no | |
-| `status` | string | no | Transition to a new workflow state |
+| `status` | string | no | 切换到新的工作流状态 |
| `priority` | number | no | 0-4 |
| `estimate` | number | no | |
-| `dueDate` | string | no | ISO date, or `null` to clear |
-| `assigneeId` | string | no | Agent id, or `null` to unassign |
-| `projectId` | string | no | Project id, or `null` to remove from project |
-| `milestoneId` | string | no | Milestone id, or `null` to clear |
-| `parentId` | string | no | Reparent, or `null` to promote to standalone |
-| `goalId` | string | no | Goal id, or `null` to unlink |
-| `labelIds` | string[] | no | **Replaces** all labels (not additive) |
-| `teamId` | string | no | Move to a different team |
-| `sortOrder` | number | no | Ordering within views |
-
-**Returns:** Updated `Issue` object.
+| `dueDate` | string | no | ISO 日期,或 `null` 以清除 |
+| `assigneeId` | string | no | 智能体 ID,或 `null` 以取消指派 |
+| `projectId` | string | no | 项目 ID,或 `null` 以从项目中移除 |
+| `milestoneId` | string | no | 里程碑 ID,或 `null` 以清除 |
+| `parentId` | string | no | 重新指定父级,或 `null` 以升为独立 issue |
+| `goalId` | string | no | 目标 ID,或 `null` 以取消关联 |
+| `labelIds` | string[] | no | **替换**所有标签(非追加) |
+| `teamId` | string | no | 移动到其他团队 |
+| `sortOrder` | number | no | 视图内的排序顺序 |
-**Side effects:**
+**Returns:** 更新后的 `Issue` 对象。
+
+**副作用:**
-- Changing `status` to a state with category `started` sets `startedAt` (if not already set)
-- Changing `status` to `completed` sets `completedAt`
-- Changing `status` to `cancelled` sets `cancelledAt`
-- Moving to `completed`/`cancelled` with sub-issue auto-close enabled completes open sub-issues
-- Changing `teamId` re-assigns the identifier (e.g. `ENG-42` → `DES-18`); old identifier preserved in `previousIdentifiers`
+- 将 `status` 更改为类别为 `started` 的状态时,会设置 `startedAt`(若尚未设置)
+- 将 `status` 更改为 `completed` 时,会设置 `completedAt`
+- 将 `status` 更改为 `cancelled` 时,会设置 `cancelledAt`
+- 在启用子 issue 自动关闭的情况下,移动到 `completed`/`cancelled` 会完成所有未关闭的子 issue
+- 更改 `teamId` 会重新分配标识符(例如 `ENG-42` → `DES-18`);旧标识符保留在 `previousIdentifiers` 中
---
### `archive_issue`
-Soft-archive an issue. Sets `archivedAt`. Does not delete.
+软归档一个 issue。设置 `archivedAt`,不执行删除。
| Parameter | Type | Required |
| --------- | ------ | -------- |
@@ -135,44 +133,43 @@ Soft-archive an issue. Sets `archivedAt`. Does not delete.
### `list_my_issues`
-List issues assigned to a specific agent. Convenience wrapper around
-`list_issues` with `assigneeId` pre-filled.
+列出分配给特定智能体的 issue。是预填 `assigneeId` 的 `list_issues` 便捷封装。
| Parameter | Type | Required | Notes |
| ----------- | ------ | -------- | ------------------------------ |
-| `agentId` | string | yes | The agent whose issues to list |
-| `stateType` | string | no | Filter by state category |
-| `orderBy` | string | no | Default: `priority` |
-| `limit` | number | no | Default: 50 |
+| `agentId` | string | yes | 要列出 issue 的智能体 |
+| `stateType` | string | no | 按状态类别筛选 |
+| `orderBy` | string | no | 默认:`priority` |
+| `limit` | number | no | 默认:50 |
-**Returns:** Same shape as `list_issues`.
+**Returns:** 与 `list_issues` 返回结构相同。
---
-## Workflow States
+## Workflow States(工作流状态)
### `list_workflow_states`
-List workflow states for a team, grouped by category.
+列出团队的工作流状态,按类别分组。
| Parameter | Type | Required |
| --------- | ------ | -------- |
| `teamId` | string | yes |
-**Returns:** `{ states: WorkflowState[] }` -- ordered by category (triage, backlog, unstarted, started, completed, cancelled), then by `position` within each category.
+**Returns:** `{ states: WorkflowState[] }` -- 按类别排序(triage、backlog、unstarted、started、completed、cancelled),同类别内再按 `position` 排序。
---
### `get_workflow_state`
-Look up a workflow state by name or ID.
+通过名称或 ID 查找工作流状态。
| Parameter | Type | Required | Notes |
| --------- | ------ | -------- | ------------------ |
| `teamId` | string | yes | |
-| `query` | string | yes | State name or UUID |
+| `query` | string | yes | 状态名称或 UUID |
-**Returns:** Single `WorkflowState` object.
+**Returns:** 单个 `WorkflowState` 对象。
---
diff --git a/doc/TASKS.md b/doc/TASKS.md
index 8c9e72b343..abacd69afa 100644
--- a/doc/TASKS.md
+++ b/doc/TASKS.md
@@ -1,311 +1,292 @@
-# Task Management Data Model
+# 任务管理数据模型
-Reference for how task tracking works in Paperclip. Describes the entities, their
-relationships, and the rules governing task lifecycle. Written as a target model
--- some of this is already implemented, some is aspirational.
+本文是 Paperclip 任务跟踪机制的参考文档,描述了各实体、它们之间的关系以及任务生命周期的管理规则。本文作为目标模型编写——其中部分内容已实现,部分为规划中的目标。
---
-## Entity Hierarchy
+## 实体层级
```
Workspace
- Initiatives (roadmap-level objectives, span quarters)
- Projects (time-bound deliverables, can span teams)
- Milestones (stages within a project)
- Issues (units of work, the core entity)
- Sub-issues (broken-down work under a parent issue)
+ Initiatives (路线图级别的目标,跨季度)
+ Projects (有时间限制的可交付成果,可跨团队)
+ Milestones (项目内的阶段)
+ Issues (工作单元,核心实体)
+ Sub-issues (拆解自父 issue 的子工作)
```
-Everything flows down. An initiative contains projects; a project contains
-milestones and issues; an issue can have sub-issues. Each level adds
-granularity.
+所有内容自上而下流动。一个 initiative 包含多个 project;一个 project 包含 milestone 和 issue;一个 issue 可以有子 issue。每一层都增加粒度。
---
-## Issues (Core Entity)
-
-An issue is the fundamental unit of work.
-
-### Fields
-
-| Field | Type | Required | Notes |
-| ------------- | ---------------- | -------- | ----------------------------------------------------------------- |
-| `id` | uuid | yes | Primary key |
-| `identifier` | string | computed | Human-readable, e.g. `ENG-123` (team key + auto-increment number) |
-| `title` | string | yes | Short summary |
-| `description` | text/markdown | no | Full description, supports markdown |
-| `status` | WorkflowState FK | yes | Defaults to team's default state |
-| `priority` | enum (0-4) | no | Defaults to 0 (none). See Priority section. |
-| `estimate` | number | no | Complexity/size points |
-| `dueDate` | date | no | |
-| `teamId` | uuid FK | yes | Every issue belongs to exactly one team |
-| `projectId` | uuid FK | no | At most one project per issue |
-| `milestoneId` | uuid FK | no | At most one milestone per issue |
-| `assigneeId` | uuid FK | no | **Single assignee.** See Assignees section. |
-| `creatorId` | uuid FK | no | Who created it |
-| `parentId` | uuid FK (self) | no | Parent issue, for sub-issue relationships |
-| `goalId` | uuid FK | no | Linked objective/goal |
-| `sortOrder` | float | no | Ordering within views |
-| `createdAt` | timestamp | yes | |
-| `updatedAt` | timestamp | yes | |
-| `startedAt` | timestamp | computed | When issue entered a "started" state |
-| `completedAt` | timestamp | computed | When issue entered a "completed" state |
-| `cancelledAt` | timestamp | computed | When issue entered a "cancelled" state |
-| `archivedAt` | timestamp | no | Soft archive |
+## Issues(核心实体)
+
+Issue 是工作的基本单元。
+
+### 字段
+
+| 字段 | 类型 | 必填 | 说明 |
+| ------------- | ---------------- | ---- | ----------------------------------------------------------------- |
+| `id` | uuid | 是 | 主键 |
+| `identifier` | string | 计算 | 人类可读,例如 `ENG-123`(团队前缀 + 自增编号) |
+| `title` | string | 是 | 简短摘要 |
+| `description` | text/markdown | 否 | 完整描述,支持 markdown |
+| `status` | WorkflowState FK | 是 | 默认为团队的默认状态 |
+| `priority` | enum (0-4) | 否 | 默认为 0(无优先级),参见优先级章节 |
+| `estimate` | number | 否 | 复杂度/规模点数 |
+| `dueDate` | date | 否 | |
+| `teamId` | uuid FK | 是 | 每个 issue 必须属于且只属于一个团队 |
+| `projectId` | uuid FK | 否 | 每个 issue 最多关联一个 project |
+| `milestoneId` | uuid FK | 否 | 每个 issue 最多关联一个 milestone |
+| `assigneeId` | uuid FK | 否 | **单一负责人**,参见负责人章节 |
+| `creatorId` | uuid FK | 否 | 创建者 |
+| `parentId` | uuid FK (self) | 否 | 父 issue,用于子 issue 关系 |
+| `goalId` | uuid FK | 否 | 关联的目标/goal |
+| `sortOrder` | float | 否 | 视图内的排序顺序 |
+| `createdAt` | timestamp | 是 | |
+| `updatedAt` | timestamp | 是 | |
+| `startedAt` | timestamp | 计算 | issue 进入"已开始"状态的时间 |
+| `completedAt` | timestamp | 计算 | issue 进入"已完成"状态的时间 |
+| `cancelledAt` | timestamp | 计算 | issue 进入"已取消"状态的时间 |
+| `archivedAt` | timestamp | 否 | 软归档 |
---
-## Workflow States
+## 工作流状态
-Issue status is **not** a flat enum. It's a team-specific set of named states,
-each belonging to one of these fixed **categories**:
+Issue 的状态**不是**一个扁平的枚举,而是每个团队自定义的一组具名状态,每个状态归属于以下固定**类别**之一:
-| Category | Purpose | Example States |
+| 类别 | 用途 | 示例状态 |
| ------------- | ---------------------------- | ------------------------------- |
-| **Triage** | Incoming, needs review | Triage |
-| **Backlog** | Accepted, not ready for work | Backlog, Icebox |
-| **Unstarted** | Ready but not begun | Todo, Ready |
-| **Started** | Active work | In Progress, In Review, In QA |
-| **Completed** | Done | Done, Shipped |
-| **Cancelled** | Rejected or abandoned | Cancelled, Won't Fix, Duplicate |
-
-### Rules
-
-- Each team defines its own workflow states within these categories
-- Teams must have at least one state per category (Triage is optional)
-- Custom states can be added within any category (e.g. "In Review" under Started)
-- Categories are fixed and ordered -- you can reorder states _within_ a category
- but not the categories themselves
-- New issues default to the team's first Backlog state
-- Moving an issue to a Started state auto-sets `startedAt`; Completed sets
- `completedAt`; Cancelled sets `cancelledAt`
-- Marking an issue as a duplicate auto-moves it to a Cancelled state
-
-### WorkflowState Fields
-
-| Field | Type | Notes |
+| **Triage** | 新进,待审查 | Triage |
+| **Backlog** | 已接受,尚未准备好开工 | Backlog, Icebox |
+| **Unstarted** | 已就绪但尚未开始 | Todo, Ready |
+| **Started** | 积极推进中 | In Progress, In Review, In QA |
+| **Completed** | 已完成 | Done, Shipped |
+| **Cancelled** | 已拒绝或已放弃 | Cancelled, Won't Fix, Duplicate |
+
+### 规则
+
+- 每个团队在这些类别内定义自己的工作流状态
+- 每个团队每个类别至少需有一个状态(Triage 可选)
+- 可在任意类别内添加自定义状态(例如在 Started 下添加 "In Review")
+- 类别固定且有序——可在类别_内部_对状态排序,但不能调整类别本身的顺序
+- 新 issue 默认为团队的第一个 Backlog 状态
+- 将 issue 移至 Started 状态时自动设置 `startedAt`;移至 Completed 时设置 `completedAt`;移至 Cancelled 时设置 `cancelledAt`
+- 将 issue 标记为重复时自动移入 Cancelled 状态
+
+### WorkflowState 字段
+
+| 字段 | 类型 | 说明 |
| ------------- | ------- | ----------------------------------------------------------------------------- |
| `id` | uuid | |
-| `name` | string | Display name, e.g. "In Review" |
-| `type` | enum | One of: `triage`, `backlog`, `unstarted`, `started`, `completed`, `cancelled` |
-| `color` | string | Hex color |
-| `description` | string | Optional guidance text |
-| `position` | float | Ordering within the category |
-| `teamId` | uuid FK | Each state belongs to one team |
+| `name` | string | 显示名称,例如 "In Review" |
+| `type` | enum | 取值之一:`triage`, `backlog`, `unstarted`, `started`, `completed`, `cancelled` |
+| `color` | string | 十六进制颜色值 |
+| `description` | string | 可选的指导说明文字 |
+| `position` | float | 类别内的排序顺序 |
+| `teamId` | uuid FK | 每个状态属于一个团队 |
---
-## Priority
+## 优先级
-A fixed, non-customizable numeric scale:
+固定的、不可自定义的数值量表:
-| Value | Label | Notes |
-| ----- | ----------- | -------------------------------------- |
-| 0 | No priority | Default. Sorts last in priority views. |
-| 1 | Urgent | Could trigger immediate notification |
-| 2 | High | |
-| 3 | Medium | |
-| 4 | Low | |
+| 值 | 标签 | 说明 |
+| -- | ----------- | -------------------------------------- |
+| 0 | No priority | 默认值。在优先级视图中排在最后 |
+| 1 | Urgent | 可能触发即时通知 |
+| 2 | High | |
+| 3 | Medium | |
+| 4 | Low | |
-The scale is intentionally small and fixed. Use labels for additional
-categorization rather than adding more priority levels.
+该量表有意保持简小且固定。如需进一步分类,请使用标签,而非增加更多优先级层级。
---
-## Teams
+## 团队
-Teams are the primary organizational unit. Almost everything is scoped to a
-team.
+团队是主要的组织单位,几乎所有内容都在团队范围内进行管理。
-| Field | Type | Notes |
+| 字段 | 类型 | 说明 |
| ------------- | ------ | -------------------------------------------------------------- |
| `id` | uuid | |
-| `name` | string | e.g. "Engineering" |
-| `key` | string | Short uppercase prefix, e.g. "ENG". Used in issue identifiers. |
+| `name` | string | 例如 "Engineering" |
+| `key` | string | 简短的大写前缀,例如 "ENG",用于 issue 标识符 |
| `description` | string | |
-### Team Scoping
+### 团队范围
-- Each issue belongs to exactly one team
-- Workflow states are per-team
-- Labels can be team-scoped or workspace-wide
-- Projects can span multiple teams
+- 每个 issue 必须属于且只属于一个团队
+- 工作流状态按团队配置
+- 标签可以是团队范围或工作区范围
+- Project 可跨多个团队
-In our context (AI company), teams map to functional areas. Each agent reports
-to a team based on role.
+在我们的场景(AI 公司)中,团队对应各职能领域,每个 agent 根据角色归属于相应团队。
---
## Projects
-Projects group issues toward a specific, time-bound deliverable. They can span
-multiple teams.
+Project 将 issue 归组到一个具体的、有时限的可交付成果中,可跨多个团队。
-| Field | Type | Notes |
+| 字段 | 类型 | 说明 |
| ------------- | --------- | ------------------------------------------------------------- |
| `id` | uuid | |
| `name` | string | |
| `description` | text | |
-| `summary` | string | Short blurb |
+| `summary` | string | 简短概述 |
| `status` | enum | `backlog`, `planned`, `in_progress`, `completed`, `cancelled` |
-| `leadId` | uuid FK | Single owner for accountability |
+| `leadId` | uuid FK | 单一负责人,以便明确问责 |
| `startDate` | date | |
| `targetDate` | date | |
| `createdAt` | timestamp | |
| `updatedAt` | timestamp | |
-### Rules
+### 规则
-- An issue belongs to at most one project
-- Project status is **manually** updated (not auto-derived from issue states)
-- Projects can contain documents (specs, briefs) as linked entities
+- 每个 issue 最多属于一个 project
+- Project 状态**手动**更新(不自动推导自 issue 状态)
+- Project 可包含文档(规格说明、简报)作为关联实体
---
## Milestones
-Milestones subdivide a project into meaningful stages.
+Milestone 将 project 细分为有意义的阶段。
-| Field | Type | Notes |
+| 字段 | 类型 | 说明 |
| ------------- | ------- | ------------------------------ |
| `id` | uuid | |
| `name` | string | |
| `description` | text | |
| `targetDate` | date | |
-| `projectId` | uuid FK | Belongs to exactly one project |
+| `projectId` | uuid FK | 归属于且只属于一个 project |
| `sortOrder` | float | |
-Issues within a project can optionally be assigned to a milestone.
+Project 内的 issue 可选择性地分配到某个 milestone。
---
-## Labels / Tags
+## 标签
-Labels provide categorical tagging. They exist at two scopes:
+标签提供分类打标功能,存在于两个范围:
-- **Workspace labels** -- available across all teams
-- **Team labels** -- restricted to a specific team
+- **工作区标签** -- 在所有团队中可用
+- **团队标签** -- 仅限于特定团队
-| Field | Type | Notes |
+| 字段 | 类型 | 说明 |
| ------------- | -------------- | ------------------------------- |
| `id` | uuid | |
| `name` | string | |
-| `color` | string | Hex color |
-| `description` | string | Contextual guidance |
-| `teamId` | uuid FK | Null for workspace-level labels |
-| `groupId` | uuid FK (self) | Parent label for grouping |
+| `color` | string | 十六进制颜色值 |
+| `description` | string | 上下文说明 |
+| `teamId` | uuid FK | 工作区级标签时为 null |
+| `groupId` | uuid FK (self) | 用于分组的父标签 |
-### Label Groups
+### 标签组
-Labels can be organized into one level of nesting (group -> labels):
+标签可组织成一级嵌套结构(组 -> 标签):
-- Labels within a group are **mutually exclusive** on an issue (only one can be
- applied from each group)
-- Groups cannot contain other groups (single nesting level only)
-- Example: group "Type" contains labels "Bug", "Feature", "Chore" -- an issue
- gets at most one
+- 同一组内的标签在一个 issue 上**互斥**(每组只能应用一个)
+- 组不能包含其他组(仅支持单层嵌套)
+- 示例:组 "Type" 包含标签 "Bug"、"Feature"、"Chore"——一个 issue 最多获得其中一个
-### Issue-Label Junction
+### Issue-标签关联
-Many-to-many via `issue_labels` join table:
+通过 `issue_labels` 关联表实现多对多关系:
-| Field | Type |
+| 字段 | 类型 |
| --------- | ------- |
| `issueId` | uuid FK |
| `labelId` | uuid FK |
---
-## Issue Relations / Dependencies
+## Issue 关系 / 依赖
-Four relation types between issues:
+Issue 之间有四种关系类型:
-| Type | Meaning | Behavior |
+| 类型 | 含义 | 行为 |
| ------------ | -------------------------------- | --------------------------------------------- |
-| `related` | General connection | Informational link |
-| `blocks` | This issue blocks another | Blocked issue shown with flag |
-| `blocked_by` | This issue is blocked by another | Inverse of blocks |
-| `duplicate` | This issue duplicates another | Auto-moves the duplicate to a Cancelled state |
+| `related` | 一般关联 | 信息性链接 |
+| `blocks` | 此 issue 阻塞另一个 | 被阻塞的 issue 显示标记 |
+| `blocked_by` | 此 issue 被另一个阻塞 | blocks 的反向关系 |
+| `duplicate` | 此 issue 与另一个重复 | 自动将重复 issue 移入 Cancelled 状态 |
-### IssueRelation Fields
+### IssueRelation 字段
-| Field | Type | Notes |
+| 字段 | 类型 | 说明 |
| ---------------- | ------- | ---------------------------------------------- |
| `id` | uuid | |
| `type` | enum | `related`, `blocks`, `blocked_by`, `duplicate` |
-| `issueId` | uuid FK | Source issue |
-| `relatedIssueId` | uuid FK | Target issue |
+| `issueId` | uuid FK | 源 issue |
+| `relatedIssueId` | uuid FK | 目标 issue |
-### Rules
+### 规则
-- When a blocking issue is resolved, the relation becomes informational (flag
- turns green)
-- Duplicate is one-directional (you mark the duplicate, not the canonical)
-- Blocking is **not transitive** at the system level (A blocks B, B blocks C
- does not auto-block A->C)
+- 当阻塞 issue 被解决后,该关系变为信息性关系(标记变为绿色)
+- 重复关系是单向的(你标记重复方,而非原始方)
+- 阻塞关系在系统层面**不具有传递性**(A 阻塞 B,B 阻塞 C,不代表 A 自动阻塞 C)
---
-## Assignees
+## 负责人
-**Single-assignee model** by design.
+设计上采用**单一负责人模型**。
-- Each issue has at most one assignee at a time
-- This is deliberate: clear ownership prevents diffusion of responsibility
-- For collaborative work involving multiple people, use **sub-issues** with
- different assignees
+- 每个 issue 同时最多只有一个负责人
+- 这是刻意为之:清晰的所有权可防止责任扩散
+- 对于涉及多人的协作工作,请使用分配给不同负责人的**子 issue**
-In our context, agents are the assignees. The `assigneeId` FK on issues
-points to the `agents` table.
+在我们的场景中,agent 就是负责人。issue 上的 `assigneeId` 外键指向 `agents` 表。
---
-## Sub-issues (Parent/Child)
+## 子 Issue(父子关系)
-Issues support parent/child nesting.
+Issue 支持父子嵌套。
-- Setting `parentId` on an issue makes it a sub-issue
-- Sub-issues can themselves have sub-issues (multi-level nesting)
-- Sub-issues inherit **project** from their parent at creation
- time (not retroactively), but NOT team, labels, or assignee
+- 在 issue 上设置 `parentId` 即可将其设为子 issue
+- 子 issue 本身也可以有子 issue(支持多层嵌套)
+- 子 issue 在创建时从父 issue 继承 **project**(非追溯性),但不继承团队、标签或负责人
-### Auto-close
+### 自动关闭
-- **Sub-issue auto-close**: when parent completes, remaining sub-issues
- auto-complete
+- **子 issue 自动关闭**:当父 issue 完成时,剩余的子 issue 自动完成
-### Conversions
+### 转换
-- Existing issues can be reparented (add or remove `parentId`)
-- A parent issue with many sub-issues can be "promoted" to a project
+- 现有 issue 可以重新设置父级(添加或移除 `parentId`)
+- 拥有大量子 issue 的父 issue 可以"晋升"为 project
---
-## Estimates
+## 估算
-Point-based estimation, configured per-team.
+基于点数的估算,按团队配置。
-### Available Scales
+### 可用量表
-| Scale | Values |
-| ----------- | ------------------------ |
+| 量表 | 取值 |
+| -------- | ------------------------ |
| Exponential | 1, 2, 4, 8, 16 (+32, 64) |
-Unestimated issues default to 1 point for progress/velocity calculations.
+未估算的 issue 在进度/速度计算时默认为 1 点。
---
-## Comments
+## 评论
-| Field | Type | Notes |
+| 字段 | 类型 | 说明 |
| ------------ | -------------- | -------------------------- |
| `id` | uuid | |
| `body` | text/markdown | |
| `issueId` | uuid FK | |
-| `authorId` | uuid FK | Can be a user or agent |
-| `parentId` | uuid FK (self) | For threaded replies |
-| `resolvedAt` | timestamp | If the thread was resolved |
+| `authorId` | uuid FK | 可以是用户或 agent |
+| `parentId` | uuid FK (self) | 用于线程式回复 |
+| `resolvedAt` | timestamp | 若线程已解决则设置此时间 |
| `createdAt` | timestamp | |
| `updatedAt` | timestamp | |
@@ -313,44 +294,40 @@ Unestimated issues default to 1 point for progress/velocity calculations.
## Initiatives
-The highest-level planning construct. Groups projects toward a strategic
-objective. Initiatives have strategic owners, and are typically measured by outcomes/OKRs, not “done/not done.”
+最高层级的规划结构。将多个 project 归组到一个战略目标中。Initiative 有战略负责人,通常以结果/OKR 衡量,而非”完成/未完成”。
-| Field | Type | Notes |
+| 字段 | 类型 | 说明 |
| ------------- | ------- | -------------------------------- |
| `id` | uuid | |
| `name` | string | |
| `description` | text | |
-| `ownerId` | uuid FK | Single owner |
+| `ownerId` | uuid FK | 单一负责人 |
| `status` | enum | `planned`, `active`, `completed` |
| `targetDate` | date | |
-Initiatives contain projects (many-to-many) and provide a rollup view of
-progress across all contained projects.
+Initiative 包含多个 project(多对多),并提供所有关联 project 进度的汇总视图。
---
-## Identifiers
+## 标识符
-Issues use human-readable identifiers: `{TEAM_KEY}-{NUMBER}`
+Issue 使用人类可读的标识符:`{TEAM_KEY}-{NUMBER}`
-- Team key: short uppercase string set per team (e.g. "ENG", "DES")
-- Number: auto-incrementing integer per team
-- Examples: `ENG-123`, `DES-45`, `OPS-7`
-- If an issue moves between teams, it gets a new identifier and the old one is
- preserved in `previousIdentifiers`
+- 团队前缀:每个团队设定的简短大写字符串(例如 "ENG"、"DES")
+- 编号:每个团队内自增的整数
+- 示例:`ENG-123`、`DES-45`、`OPS-7`
+- 若 issue 在团队间移动,将获得新标识符,旧标识符保留在 `previousIdentifiers` 中
-This is far better for human communication than UUIDs. People say "grab ENG-42"
-not "grab 7f3a...".
+这比 UUID 更适合人类交流。人们会说"去处理 ENG-42",而不是"去处理 7f3a..."。
---
-## Entity Relationships
+## 实体关系
```
Team (1) ----< (many) Issue
Team (1) ----< (many) WorkflowState
-Team (1) ----< (many) Label (team-scoped)
+Team (1) ----< (many) Label (团队范围)
Issue (many) >---- (1) WorkflowState
Issue (many) >---- (0..1) Assignee (Agent)
@@ -372,36 +349,25 @@ Initiative (many) >---- (1) Owner (Agent)
---
-## Implementation Priority
+## 实现优先级
-Recommended build order, highest value first:
+建议的构建顺序,价值最高者优先:
-### High Value
+### 高价值
-1. **Teams** -- `teams` table + `teamId` FK on issues. Foundation for
- human-readable identifiers (`ENG-123`) and per-team workflow states. Most
- other features depend on team scoping, so build this first.
-2. **Workflow states** -- `workflow_states` table + `stateId` FK on issues.
- Per-team custom workflows with category-based state transitions.
-3. **Labels** -- `labels` + `issue_labels` tables. Categorization
- (bug/feature/chore, area tags, etc.) without polluting the status field.
-4. **Issue Relations** -- `issue_relations` table. Blocking/blocked-by is
- essential for agent coordination (agent A can't start until agent B finishes).
-5. **Sub-issues** -- `parentId` self-FK on `issues`. Lets agents break down
- large tasks.
-6. **Comments** -- `comments` table. Agents need to communicate about issues
- without overwriting the description.
+1. **Teams** -- `teams` 表 + issues 上的 `teamId` 外键。是人类可读标识符(`ENG-123`)和按团队配置工作流状态的基础。大多数其他功能依赖团队范围,因此应首先构建。
+2. **Workflow states** -- `workflow_states` 表 + issues 上的 `stateId` 外键。基于类别的状态流转,支持每团队自定义工作流。
+3. **Labels** -- `labels` + `issue_labels` 表。提供分类能力(bug/feature/chore、领域标签等),而不污染状态字段。
+4. **Issue Relations** -- `issue_relations` 表。阻塞/被阻塞关系对于 agent 协调至关重要(agent A 无法在 agent B 完成前开始)。
+5. **Sub-issues** -- `issues` 上的 `parentId` 自引用外键。让 agent 能够分解大型任务。
+6. **Comments** -- `comments` 表。Agent 需要就 issue 进行沟通,而不是覆盖描述内容。
-### Medium Value
+### 中等价值
-7. **Transition timestamps** -- `startedAt`, `completedAt`, `cancelledAt` on
- issues, auto-set by workflow state changes. Enables velocity tracking and SLA
- measurement.
+7. **Transition timestamps** -- issues 上的 `startedAt`、`completedAt`、`cancelledAt`,由工作流状态变更自动设置。支持速度跟踪和 SLA 测量。
-### Lower Priority (For Later)
+### 较低优先级(留待后期)
-8. **Milestones** -- Useful once projects get complex enough to need stages.
-9. **Initiatives** -- Useful once we have multiple projects that serve a common
- strategic goal.
-10. **Estimates** -- Useful once we want to measure throughput and predict
- capacity.
+8. **Milestones** -- 当 project 复杂到需要划分阶段时有用。
+9. **Initiatives** -- 当有多个 project 服务于同一战略目标时有用。
+10. **Estimates** -- 当需要衡量吞吐量并预测产能时有用。
diff --git a/doc/UNTRUSTED-PR-REVIEW.md b/doc/UNTRUSTED-PR-REVIEW.md
index 0061a58135..77850f1b65 100644
--- a/doc/UNTRUSTED-PR-REVIEW.md
+++ b/doc/UNTRUSTED-PR-REVIEW.md
@@ -1,42 +1,42 @@
-# Untrusted PR Review In Docker
+# 在 Docker 中审查不可信 PR
-Use this workflow when you want Codex or Claude to inspect a pull request that you do not want touching your host machine directly.
+当你想让 Codex 或 Claude 检查一个不希望直接接触主机的拉取请求时,使用此工作流。
-This is intentionally separate from the normal Paperclip dev image.
+这与正常的 Paperclip 开发镜像是有意分开的。
-## What this container isolates
+## 此容器隔离的内容
-- `codex` auth/session state in a Docker volume, not your host `~/.codex`
-- `claude` auth/session state in a Docker volume, not your host `~/.claude`
-- `gh` auth state in the same container-local home volume
-- review clones, worktrees, dependency installs, and local databases in a writable scratch volume under `/work`
+- `codex` 认证/会话状态在 Docker 卷中,而非你的主机 `~/.codex`
+- `claude` 认证/会话状态在 Docker 卷中,而非你的主机 `~/.claude`
+- `gh` 认证状态在同一个容器本地 home 卷中
+- 审查克隆、worktree、依赖安装和本地数据库在 `/work` 下的可写临时卷中
-By default this workflow does **not** mount your host repo checkout, your host home directory, or your SSH agent.
+默认情况下,此工作流**不会**挂载你的主机仓库检出、主机 home 目录或 SSH 代理。
-## Files
+## 文件
- `docker/untrusted-review/Dockerfile`
- `docker-compose.untrusted-review.yml`
-- `review-checkout-pr` inside the container
+- 容器内的 `review-checkout-pr`
-## Build and start a shell
+## 构建并启动 shell
```sh
docker compose -f docker-compose.untrusted-review.yml build
docker compose -f docker-compose.untrusted-review.yml run --rm --service-ports review
```
-That opens an interactive shell in the review container with:
+这会在审查容器中打开一个交互式 shell,包含:
- Node + Corepack/pnpm
- `codex`
- `claude`
- `gh`
-- `git`, `rg`, `fd`, `jq`
+- `git`、`rg`、`fd`、`jq`
-## First-time login inside the container
+## 容器内首次登录
-Run these once. The resulting login state persists in the `review-home` Docker volume.
+运行一次即可。生成的登录状态会持久化在 `review-home` Docker 卷中。
```sh
gh auth login
@@ -44,92 +44,92 @@ codex login
claude login
```
-If you prefer API-key auth instead of CLI login, pass keys through Compose env:
+如果你更喜欢使用 API 密钥认证而非 CLI 登录,通过 Compose 环境变量传递密钥:
```sh
OPENAI_API_KEY=... ANTHROPIC_API_KEY=... docker compose -f docker-compose.untrusted-review.yml run --rm review
```
-## Check out a PR safely
+## 安全地检出 PR
-Inside the container:
+在容器内:
```sh
review-checkout-pr paperclipai/paperclip 432
cd /work/checkouts/paperclipai-paperclip/pr-432
```
-What this does:
+这会执行以下操作:
-1. Creates or reuses a repo clone under `/work/repos/...`
-2. Fetches `pull//head` from GitHub
-3. Creates a detached git worktree under `/work/checkouts/...`
+1. 在 `/work/repos/...` 下创建或复用仓库克隆
+2. 从 GitHub 获取 `pull//head`
+3. 在 `/work/checkouts/...` 下创建分离的 git worktree
-The checkout lives entirely inside the container volume.
+检出内容完全存在于容器卷内。
-## Ask Codex or Claude to review it
+## 让 Codex 或 Claude 审查
-Inside the PR checkout:
+在 PR 检出目录内:
```sh
codex
```
-Then give it a prompt like:
+然后给出类似这样的提示:
```text
Review this PR as hostile input. Focus on security issues, data exfiltration paths, sandbox escapes, dangerous install/runtime scripts, auth changes, and subtle behavioral regressions. Do not modify files. Produce findings ordered by severity with file references.
```
-Or with Claude:
+或者使用 Claude:
```sh
claude
```
-## Preview the Paperclip app from the PR
+## 从 PR 预览 Paperclip 应用
-Only do this when you intentionally want to execute the PR's code inside the container.
+只有当你有意要在容器内执行 PR 的代码时才这样做。
-Inside the PR checkout:
+在 PR 检出目录内:
```sh
pnpm install
HOST=0.0.0.0 pnpm dev
```
-Open from the host:
+从主机打开:
- `http://localhost:3100`
-The Compose file also exposes Vite's default port:
+Compose 文件还暴露了 Vite 的默认端口:
- `http://localhost:5173`
-Notes:
+注意:
-- `pnpm install` can run untrusted lifecycle scripts from the PR. That is why this happens inside the isolated container instead of on your host.
-- If you only want static inspection, do not run install/dev commands.
-- Paperclip's embedded PostgreSQL and local storage stay inside the container home volume via `PAPERCLIP_HOME=/home/reviewer/.paperclip-review`.
+- `pnpm install` 可能会运行 PR 中的不可信生命周期脚本。这就是为什么这在隔离容器内进行,而不是在你的主机上。
+- 如果你只想进行静态检查,不要运行 install/dev 命令。
+- Paperclip 的内嵌 PostgreSQL 和本地存储通过 `PAPERCLIP_HOME=/home/reviewer/.paperclip-review` 保留在容器 home 卷内。
-## Reset state
+## 重置状态
-Remove the review container volumes when you want a clean environment:
+当你需要干净环境时,删除审查容器卷:
```sh
docker compose -f docker-compose.untrusted-review.yml down -v
```
-That deletes:
+这会删除:
-- Codex/Claude/GitHub login state stored in `review-home`
-- cloned repos, worktrees, installs, and scratch data stored in `review-work`
+- 存储在 `review-home` 中的 Codex/Claude/GitHub 登录状态
+- 存储在 `review-work` 中的克隆仓库、worktree、安装和临时数据
-## Security limits
+## 安全限制
-This is a useful isolation boundary, but it is still Docker, not a full VM.
+这是一个有用的隔离边界,但它仍然是 Docker,而非完整的虚拟机。
-- A reviewed PR can still access the container's network unless you disable it.
-- Any secrets you pass into the container are available to code you execute inside it.
-- Do not mount your host repo, host home, `.ssh`, or Docker socket unless you are intentionally weakening the boundary.
-- If you need a stronger boundary than this, use a disposable VM instead of Docker.
+- 被审查的 PR 仍然可以访问容器的网络,除非你禁用它。
+- 你传入容器的任何密钥对在容器内执行的代码都是可用的。
+- 不要挂载你的主机仓库、主机 home、`.ssh` 或 Docker socket,除非你有意削弱隔离边界。
+- 如果你需要比此更强的隔离边界,请使用一次性虚拟机而非 Docker。
diff --git a/doc/experimental/issue-worktree-support.md b/doc/experimental/issue-worktree-support.md
index 8f05ff199d..1e33d32148 100644
--- a/doc/experimental/issue-worktree-support.md
+++ b/doc/experimental/issue-worktree-support.md
@@ -1,62 +1,62 @@
-# Issue worktree support
+# Issue worktree 支持
-Status: experimental, runtime-only, not shipping as a user-facing feature yet.
+状态:实验性功能,仅限运行时,尚未作为面向用户的功能发布。
-This branch contains the runtime and seeding work needed for issue-scoped worktrees:
+此分支包含 issue 级别 worktree 所需的运行时和初始化工作:
-- project execution workspace policy support
-- issue-level execution workspace settings
-- git worktree realization for isolated issue execution
-- optional command-based worktree provisioning
-- seeded worktree fixes for secrets key compatibility
-- seeded project workspace rebinding to the current git worktree
+- 项目执行工作区策略支持
+- issue 级别的执行工作区设置
+- 用于隔离 issue 执行的 git worktree 实现
+- 可选的基于命令的 worktree 配置
+- 针对密钥兼容性的种子 worktree 修复
+- 种子项目工作区重新绑定到当前 git worktree
-We are intentionally not shipping the UI for this yet. The runtime code remains in place, but the main UI entrypoints are hard-gated off for now.
+我们有意暂不发布此功能的 UI。运行时代码保留,但主要 UI 入口目前被硬性关闭。
-## What works today
+## 当前可用功能
-- projects can carry execution workspace policy in the backend
-- issues can carry execution workspace settings in the backend
-- heartbeat execution can realize isolated git worktrees
-- runtime can run a project-defined provision command inside the derived worktree
-- seeded worktree instances can keep local-encrypted secrets working
-- seeded worktree instances can rebind same-repo project workspace paths onto the current git worktree
+- 项目可以在后端携带执行工作区策略
+- issue 可以在后端携带执行工作区设置
+- 心跳执行可以实现隔离的 git worktree
+- 运行时可以在派生的 worktree 内运行项目定义的配置命令
+- 种子 worktree 实例可以保持本地加密密钥正常工作
+- 种子 worktree 实例可以将同仓库项目工作区路径重新绑定到当前 git worktree
-## Hidden UI entrypoints
+## 隐藏的 UI 入口
-These are the current user-facing UI surfaces for the feature, now intentionally disabled:
+以下是该功能当前面向用户的 UI 界面,现已有意禁用:
-- project settings:
+- 项目设置:
- `ui/src/components/ProjectProperties.tsx`
- - execution workspace policy controls
- - git worktree base ref / branch template / parent dir
- - provision / teardown command inputs
+ - 执行工作区策略控制
+ - git worktree 基础引用 / 分支模板 / 父目录
+ - 配置 / 清理命令输入
-- issue creation:
+- issue 创建:
- `ui/src/components/NewIssueDialog.tsx`
- - isolated issue checkout toggle
- - defaulting issue execution workspace settings from project policy
+ - 隔离 issue 检出切换
+ - 从项目策略默认 issue 执行工作区设置
-- issue editing:
+- issue 编辑:
- `ui/src/components/IssueProperties.tsx`
- - issue-level workspace mode toggle
- - defaulting issue execution workspace settings when project changes
+ - issue 级别工作区模式切换
+ - 当项目变更时默认 issue 执行工作区设置
-- agent/runtime settings:
+- 代理/运行时设置:
- `ui/src/adapters/runtime-json-fields.tsx`
- - runtime services JSON field, which is part of the broader workspace-runtime support surface
+ - 运行时服务 JSON 字段,这是更广泛的工作区-运行时支持界面的一部分
-## Why the UI is hidden
+## UI 隐藏的原因
-- the runtime behavior is still being validated
-- the workflow and operator ergonomics are not final
-- we do not want to expose a partially-baked user-facing feature in issues, projects, or settings
+- 运行时行为仍在验证中
+- 工作流和操作人员的使用体验尚未最终确定
+- 我们不希望在 issue、项目或设置中暴露一个尚未完善的面向用户的功能
-## Re-enable plan
+## 重新启用计划
-When this is ready to ship:
+当此功能准备发布时:
-- re-enable the gated UI sections in the files above
-- review wording and defaults for project and issue controls
-- decide which agent/runtime settings should remain advanced-only
-- add end-to-end product-level verification for the full UI workflow
+- 重新启用上述文件中被关闭的 UI 部分
+- 审查项目和 issue 控制的措辞和默认值
+- 决定哪些代理/运行时设置应保持为高级选项
+- 为完整 UI 工作流添加端到端产品级验证
diff --git a/doc/memory-landscape.md b/doc/memory-landscape.md
index 9648828c45..8238c6747e 100644
--- a/doc/memory-landscape.md
+++ b/doc/memory-landscape.md
@@ -1,172 +1,172 @@
-# Memory Landscape
+# 记忆系统全景
-Date: 2026-03-17
+日期:2026-03-17
-This document summarizes the memory systems referenced in task `PAP-530` and extracts the design patterns that matter for Paperclip.
+本文档总结了任务 `PAP-530` 中引用的记忆系统,并提取了对 Paperclip 重要的设计模式。
-## What Paperclip Needs From This Survey
+## Paperclip 需要从这项调研中获得什么
-Paperclip is not trying to become a single opinionated memory engine. The more useful target is a control-plane memory surface that:
+Paperclip 并非试图成为一个单一的、有主见的记忆引擎。更有用的目标是一个控制平面记忆层,它:
-- stays company-scoped
-- lets each company choose a default memory provider
-- lets specific agents override that default
-- keeps provenance back to Paperclip runs, issues, comments, and documents
-- records memory-related cost and latency the same way the rest of the control plane records work
-- works with plugin-provided providers, not only built-ins
+- 保持公司范围
+- 让每家公司选择默认的记忆提供者
+- 让特定代理覆盖该默认值
+- 保持对 Paperclip 运行、议题、评论和文档的来源追溯
+- 像控制平面记录工作的其他部分一样记录记忆相关的成本和延迟
+- 与插件提供的提供者配合工作,而不仅是内置的
-The question is not "which memory project wins?" The question is "what is the smallest Paperclip contract that can sit above several very different memory systems without flattening away the useful differences?"
+问题不是"哪个记忆项目胜出?"而是"Paperclip 的最小契约是什么,能够位于几个非常不同的记忆系统之上,而不会抹平有用的差异?"
-## Quick Grouping
+## 快速分类
-### Hosted memory APIs
+### 托管记忆 API
- `mem0`
- `supermemory`
- `Memori`
-These optimize for a simple application integration story: send conversation/content plus an identity, then query for relevant memory or user context later.
+这些优化了简单的应用集成方式:发送对话/内容加上身份标识,然后稍后查询相关记忆或用户上下文。
-### Agent-centric memory frameworks / memory OSes
+### 以代理为中心的记忆框架/记忆操作系统
- `MemOS`
- `memU`
- `EverMemOS`
- `OpenViking`
-These treat memory as an agent runtime subsystem, not only as a search index. They usually add task memory, profiles, filesystem-style organization, async ingestion, or skill/resource management.
+这些将记忆视为代理运行时子系统,而不仅仅是搜索索引。它们通常添加任务记忆、用户画像、文件系统风格的组织、异步摄入或技能/资源管理。
-### Local-first memory stores / indexes
+### 本地优先的记忆存储/索引
- `nuggets`
- `memsearch`
-These emphasize local persistence, inspectability, and low operational overhead. They are useful because Paperclip is local-first today and needs at least one zero-config path.
+这些强调本地持久化、可检查性和低运维开销。它们很有用,因为 Paperclip 目前是本地优先的,需要至少一条零配置路径。
-## Per-Project Notes
+## 各项目笔记
-| Project | Shape | Notable API / model | Strong fit for Paperclip | Main mismatch |
+| 项目 | 形态 | 主要 API / 模型 | 与 Paperclip 的契合度 | 主要不匹配 |
|---|---|---|---|---|
-| [nuggets](https://github.com/NeoVertex1/nuggets) | local memory engine + messaging gateway | topic-scoped HRR memory with `remember`, `recall`, `forget`, fact promotion into `MEMORY.md` | good example of lightweight local memory and automatic promotion | very specific architecture; not a general multi-tenant service |
-| [mem0](https://github.com/mem0ai/mem0) | hosted + OSS SDK | `add`, `search`, `getAll`, `get`, `update`, `delete`, `deleteAll`; entity partitioning via `user_id`, `agent_id`, `run_id`, `app_id` | closest to a clean provider API with identities and metadata filters | provider owns extraction heavily; Paperclip should not assume every backend behaves like mem0 |
-| [MemOS](https://github.com/MemTensor/MemOS) | memory OS / framework | unified add-retrieve-edit-delete, memory cubes, multimodal memory, tool memory, async scheduler, feedback/correction | strong source for optional capabilities beyond plain search | much broader than the minimal contract Paperclip should standardize first |
-| [supermemory](https://github.com/supermemoryai/supermemory) | hosted memory + context API | `add`, `profile`, `search.memories`, `search.documents`, document upload, settings; automatic profile building and forgetting | strong example of "context bundle" rather than raw search results | heavily productized around its own ontology and hosted flow |
-| [memU](https://github.com/NevaMind-AI/memU) | proactive agent memory framework | file-system metaphor, proactive loop, intent prediction, always-on companion model | good source for when memory should trigger agent behavior, not just retrieval | proactive assistant framing is broader than Paperclip's task-centric control plane |
-| [Memori](https://github.com/MemoriLabs/Memori) | hosted memory fabric + SDK wrappers | registers against LLM SDKs, attribution via `entity_id` + `process_id`, sessions, cloud + BYODB | strong example of automatic capture around model clients | wrapper-centric design does not map 1:1 to Paperclip's run / issue / comment lifecycle |
-| [EverMemOS](https://github.com/EverMind-AI/EverMemOS) | conversational long-term memory system | MemCell extraction, structured narratives, user profiles, hybrid retrieval / reranking | useful model for provenance-rich structured memories and evolving profiles | focused on conversational memory rather than generalized control-plane events |
-| [memsearch](https://github.com/zilliztech/memsearch) | markdown-first local memory index | markdown as source of truth, `index`, `search`, `watch`, transcript parsing, plugin hooks | excellent baseline for a local built-in provider and inspectable provenance | intentionally simple; no hosted service semantics or rich correction workflow |
-| [OpenViking](https://github.com/volcengine/OpenViking) | context database | filesystem-style organization of memories/resources/skills, tiered loading, visualized retrieval trajectories | strong source for browse/inspect UX and context provenance | treats "context database" as a larger product surface than Paperclip should own |
+| [nuggets](https://github.com/NeoVertex1/nuggets) | 本地记忆引擎 + 消息网关 | 基于主题的 HRR 记忆,具有 `remember`、`recall`、`forget`,事实提升至 `MEMORY.md` | 轻量级本地记忆和自动提升的好例子 | 架构非常特定;不是通用的多租户服务 |
+| [mem0](https://github.com/mem0ai/mem0) | 托管 + 开源 SDK | `add`、`search`、`getAll`、`get`、`update`、`delete`、`deleteAll`;通过 `user_id`、`agent_id`、`run_id`、`app_id` 进行实体分区 | 最接近带身份标识和元数据过滤的干净提供者 API | 提供者大量控制提取;Paperclip 不应假设每个后端都像 mem0 一样运作 |
+| [MemOS](https://github.com/MemTensor/MemOS) | 记忆操作系统/框架 | 统一的增删改查、记忆立方体、多模态记忆、工具记忆、异步调度器、反馈/纠正 | 超越简单搜索的可选能力的有力来源 | 比 Paperclip 应该首先标准化的最小契约广泛得多 |
+| [supermemory](https://github.com/supermemoryai/supermemory) | 托管记忆 + 上下文 API | `add`、`profile`、`search.memories`、`search.documents`、文档上传、设置;自动构建用户画像和遗忘 | "上下文包"而非原始搜索结果的好例子 | 高度围绕自身本体论和托管流程产品化 |
+| [memU](https://github.com/NevaMind-AI/memU) | 主动式代理记忆框架 | 文件系统隐喻、主动循环、意图预测、始终在线的伴随模型 | 记忆应触发代理行为而非仅检索的好来源 | 主动助手框架比 Paperclip 以任务为中心的控制平面更广泛 |
+| [Memori](https://github.com/MemoriLabs/Memori) | 托管记忆网络 + SDK 封装 | 针对 LLM SDK 注册,通过 `entity_id` + `process_id` 归因,会话,云 + BYODB | 围绕模型客户端自动捕获的好例子 | 封装为中心的设计不能 1:1 映射到 Paperclip 的运行/议题/评论生命周期 |
+| [EverMemOS](https://github.com/EverMind-AI/EverMemOS) | 对话式长期记忆系统 | MemCell 提取、结构化叙事、用户画像、混合检索/重排序 | 来源丰富的结构化记忆和不断演进的用户画像的有用模型 | 专注于对话记忆而非通用控制平面事件 |
+| [memsearch](https://github.com/zilliztech/memsearch) | 以 markdown 为核心的本地记忆索引 | markdown 作为真实来源,`index`、`search`、`watch`、转录解析、插件钩子 | 本地内置提供者和可检查来源的极佳基线 | 有意简单;没有托管服务语义或丰富的纠正工作流 |
+| [OpenViking](https://github.com/volcengine/OpenViking) | 上下文数据库 | 记忆/资源/技能的文件系统风格组织、分层加载、可视化检索轨迹 | 浏览/检查 UX 和上下文来源的有力参考 | 将"上下文数据库"视为比 Paperclip 应该拥有的更大的产品面 |
-## Common Primitives Across The Landscape
+## 跨系统的共同原语
-Even though the systems disagree on architecture, they converge on a few primitives:
+尽管这些系统在架构上不一致,但它们在几个原语上趋于一致:
-- `ingest`: add memory from text, messages, documents, or transcripts
-- `query`: search or retrieve memory given a task, question, or scope
-- `scope`: partition memory by user, agent, project, process, or session
-- `provenance`: carry enough metadata to explain where a memory came from
-- `maintenance`: update, forget, dedupe, compact, or correct memories over time
-- `context assembly`: turn raw memories into a prompt-ready bundle for the agent
+- `ingest`:从文本、消息、文档或转录中添加记忆
+- `query`:根据任务、问题或范围搜索或检索记忆
+- `scope`:按用户、代理、项目、流程或会话对记忆进行分区
+- `provenance`:携带足够的元数据来解释记忆来自何处
+- `maintenance`:随时间更新、遗忘、去重、压缩或纠正记忆
+- `context assembly`:将原始记忆转化为代理可用的提示包
-If Paperclip does not expose these, it will not adapt well to the systems above.
+如果 Paperclip 不暴露这些,它将无法很好地适配上述系统。
-## Where The Systems Differ
+## 系统差异之处
-These differences are exactly why Paperclip needs a layered contract instead of a single hard-coded engine.
+这些差异正是 Paperclip 需要分层契约而非单一硬编码引擎的原因。
-### 1. Who owns extraction?
+### 1. 谁拥有提取权?
-- `mem0`, `supermemory`, and `Memori` expect the provider to infer memories from conversations.
-- `memsearch` expects the host to decide what markdown to write, then indexes it.
-- `MemOS`, `memU`, `EverMemOS`, and `OpenViking` sit somewhere in between and often expose richer memory construction pipelines.
+- `mem0`、`supermemory` 和 `Memori` 期望提供者从对话中推断记忆。
+- `memsearch` 期望宿主决定写什么 markdown,然后对其建立索引。
+- `MemOS`、`memU`、`EverMemOS` 和 `OpenViking` 介于两者之间,通常暴露更丰富的记忆构建管道。
-Paperclip should support both:
+Paperclip 应该支持两者:
-- provider-managed extraction
-- Paperclip-managed extraction with provider-managed storage / retrieval
+- 提供者管理的提取
+- Paperclip 管理的提取 + 提供者管理的存储/检索
-### 2. What is the source of truth?
+### 2. 什么是真实来源?
-- `memsearch` and `nuggets` make the source inspectable on disk.
-- hosted APIs often make the provider store canonical.
-- filesystem-style systems like `OpenViking` and `memU` treat hierarchy itself as part of the memory model.
+- `memsearch` 和 `nuggets` 使来源在磁盘上可检查。
+- 托管 API 通常使提供者存储为规范。
+- 文件系统风格的系统如 `OpenViking` 和 `memU` 将层级本身视为记忆模型的一部分。
-Paperclip should not require a single storage shape. It should require normalized references back to Paperclip entities.
+Paperclip 不应要求单一的存储形状。它应该要求归一化的引用回到 Paperclip 实体。
-### 3. Is memory just search, or also profile and planning state?
+### 3. 记忆仅仅是搜索,还是也包括画像和计划状态?
-- `mem0` and `memsearch` center search and CRUD.
-- `supermemory` adds user profiles as a first-class output.
-- `MemOS`, `memU`, `EverMemOS`, and `OpenViking` expand into tool traces, task memory, resources, and skills.
+- `mem0` 和 `memsearch` 以搜索和 CRUD 为中心。
+- `supermemory` 将用户画像添加为一等输出。
+- `MemOS`、`memU`、`EverMemOS` 和 `OpenViking` 扩展到工具轨迹、任务记忆、资源和技能。
-Paperclip should make plain search the minimum contract and richer outputs optional capabilities.
+Paperclip 应该将简单搜索作为最低契约,将更丰富的输出作为可选能力。
-### 4. Is memory synchronous or asynchronous?
+### 4. 记忆是同步的还是异步的?
-- local tools often work synchronously in-process.
-- larger systems add schedulers, background indexing, compaction, or sync jobs.
+- 本地工具通常在进程内同步工作。
+- 更大的系统添加调度器、后台索引、压缩或同步作业。
-Paperclip needs both direct request/response operations and background maintenance hooks.
+Paperclip 需要直接的请求/响应操作和后台维护钩子。
-## Paperclip-Specific Takeaways
+## Paperclip 特定的结论
-### Paperclip should own these concerns
+### Paperclip 应该拥有这些关注点
-- binding a provider to a company and optionally overriding it per agent
-- mapping Paperclip entities into provider scopes
-- provenance back to issue comments, documents, runs, and activity
-- cost / token / latency reporting for memory work
-- browse and inspect surfaces in the Paperclip UI
-- governance on destructive operations
+- 将提供者绑定到公司,并可选地按代理覆盖
+- 将 Paperclip 实体映射到提供者范围
+- 对议题评论、文档、运行和活动的来源追溯
+- 记忆工作的成本/token/延迟报告
+- Paperclip UI 中的浏览和检查界面
+- 破坏性操作的治理
-### Providers should own these concerns
+### 提供者应该拥有这些关注点
-- extraction heuristics
-- embedding / indexing strategy
-- ranking and reranking
-- profile synthesis
-- contradiction resolution and forgetting logic
-- storage engine details
+- 提取启发式算法
+- 嵌入/索引策略
+- 排名和重排序
+- 用户画像合成
+- 矛盾解决和遗忘逻辑
+- 存储引擎细节
-### The control-plane contract should stay small
+### 控制平面契约应该保持精简
-Paperclip does not need to standardize every feature from every provider. It needs:
+Paperclip 不需要标准化每个提供者的每个功能。它需要:
-- a required portable core
-- optional capability flags for richer providers
-- a way to record provider-native ids and metadata without pretending all providers are equivalent internally
+- 一个必须的可移植核心
+- 为更丰富的提供者提供的可选能力标志
+- 一种记录提供者原生 ID 和元数据的方式,而不假装所有提供者在内部是等价的
-## Recommended Direction
+## 推荐方向
-Paperclip should adopt a two-layer memory model:
+Paperclip 应该采用两层记忆模型:
-1. `Memory binding + control plane layer`
- Paperclip decides which provider key is in effect for a company, agent, or project, and it logs every memory operation with provenance and usage.
+1. `记忆绑定 + 控制平面层`
+ Paperclip 决定哪个提供者密钥对公司、代理或项目有效,并记录每个记忆操作的来源和使用情况。
-2. `Provider adapter layer`
- A built-in or plugin-supplied adapter turns Paperclip memory requests into provider-specific calls.
+2. `提供者适配器层`
+ 内置或插件提供的适配器将 Paperclip 记忆请求转换为提供者特定的调用。
-The portable core should cover:
+可移植核心应该覆盖:
-- ingest / write
-- search / recall
-- browse / inspect
-- get by provider record handle
-- forget / correction
-- usage reporting
+- 摄入/写入
+- 搜索/回忆
+- 浏览/检查
+- 按提供者记录句柄获取
+- 遗忘/纠正
+- 使用量报告
-Optional capabilities can cover:
+可选能力可以覆盖:
-- profile synthesis
-- async ingestion
-- multimodal content
-- tool / resource / skill memory
-- provider-native graph browsing
+- 用户画像合成
+- 异步摄入
+- 多模态内容
+- 工具/资源/技能记忆
+- 提供者原生图浏览
-That is enough to support:
+这足以支持:
-- a local markdown-first baseline similar to `memsearch`
-- hosted services similar to `mem0`, `supermemory`, or `Memori`
-- richer agent-memory systems like `MemOS` or `OpenViking`
+- 类似 `memsearch` 的本地 markdown 优先基线
+- 类似 `mem0`、`supermemory` 或 `Memori` 的托管服务
+- 类似 `MemOS` 或 `OpenViking` 的更丰富的代理记忆系统
-without forcing Paperclip itself to become a monolithic memory engine.
+而不会迫使 Paperclip 本身成为一个单体记忆引擎。
diff --git a/doc/plans/2026-02-16-module-system.md b/doc/plans/2026-02-16-module-system.md
index e804218960..bfe82e3dea 100644
--- a/doc/plans/2026-02-16-module-system.md
+++ b/doc/plans/2026-02-16-module-system.md
@@ -1,32 +1,32 @@
-# Paperclip Module System
+# Paperclip 模块系统
-> Supersession note: the company-template/package-format direction in this document is no longer current. For the current markdown-first company import/export plan, see `doc/plans/2026-03-13-company-import-export-v2.md` and `docs/companies/companies-spec.md`.
+> 取代说明:本文档中关于公司模板/包格式的方向已不再适用。当前以 Markdown 优先的公司导入/导出方案,请参阅 `doc/plans/2026-03-13-company-import-export-v2.md` 和 `docs/companies/companies-spec.md`。
-## Overview
+## 概述
-Paperclip's module system lets you extend the control plane with new capabilities — revenue tracking, observability, notifications, dashboards — without forking core. Modules are self-contained packages that register routes, UI pages, database tables, and lifecycle hooks.
+Paperclip 的模块系统让你可以在不分叉核心代码的情况下,为控制平面扩展新能力——收入追踪、可观测性、通知、仪表盘等。模块是自包含的包,可注册路由、UI 页面、数据库表和生命周期钩子。
-Separately, **Company Templates** are code-free data packages (agent teams, org charts, goal hierarchies) that you can import to bootstrap a new company.
+另外,**公司模板**是无代码的数据包(智能体团队、组织结构图、目标层级),可导入以快速初始化一家新公司。
-Both are discoverable through the **Company Store**.
+两者都可通过**公司商店**发现。
---
-## Concepts
+## 概念
-| Concept | What it is | Contains code? |
+| 概念 | 含义 | 包含代码? |
|---------|-----------|----------------|
-| **Module** | A package that extends Paperclip's API, UI, and data model | Yes |
-| **Company Template** | A data snapshot — agents, projects, goals, org structure | No (JSON only) |
-| **Company Store** | Registry for browsing/installing modules and templates | — |
-| **Hook** | A named event in the core that modules can subscribe to | — |
-| **Slot** | An exclusive category where only one module can be active (e.g., `observability`) | — |
+| **模块(Module)** | 扩展 Paperclip API、UI 和数据模型的包 | 是 |
+| **公司模板(Company Template)** | 数据快照——智能体、项目、目标、组织结构 | 否(仅 JSON) |
+| **公司商店(Company Store)** | 用于浏览/安装模块和模板的注册表 | — |
+| **钩子(Hook)** | 核心中已命名的事件,模块可订阅 | — |
+| **插槽(Slot)** | 独占类别,同一时间只能有一个模块处于活跃状态(如 `observability`) | — |
---
-## Module Architecture
+## 模块架构
-### File Structure
+### 文件结构
```
modules/
@@ -43,9 +43,9 @@ modules/
TokenDashboard.tsx
```
-Modules live in a top-level `modules/` directory. Each module is a pnpm workspace package.
+模块位于顶层 `modules/` 目录中。每个模块都是一个 pnpm 工作区包。
-### Manifest (`paperclip.module.json`)
+### 清单文件(`paperclip.module.json`)
```json
{
@@ -104,20 +104,20 @@ Modules live in a top-level `modules/` directory. Each module is a pnpm workspac
}
```
-Key fields:
+关键字段:
-- **`id`**: Unique identifier, used as the npm package name suffix (`@paperclipai/mod-observability`)
-- **`slot`**: Optional exclusive category. If set, only one module with this slot can be active. Omit for modules that can coexist freely.
-- **`hooks`**: Which core events this module subscribes to. Declared upfront so the core knows what to emit.
-- **`routes.prefix`**: Mounted under `/api/modules/`. The module owns this namespace.
-- **`ui.pages`**: Adds entries to the sidebar. Lazy-loaded React components.
-- **`ui.widgets`**: Injects components into existing pages (e.g., dashboard cards).
-- **`schema`**: Drizzle table definitions for module-owned tables. Prefixed with `mod__` to avoid collisions.
-- **`configSchema`**: JSON Schema for module configuration. Validated before the module loads.
+- **`id`**:唯一标识符,用作 npm 包名后缀(`@paperclipai/mod-observability`)
+- **`slot`**:可选的独占类别。设置后,同一插槽只能有一个模块处于活跃状态。可自由共存的模块可省略此字段。
+- **`hooks`**:该模块订阅的核心事件。提前声明以便核心知道需要触发哪些事件。
+- **`routes.prefix`**:挂载在 `/api/modules/` 下。模块拥有该命名空间。
+- **`ui.pages`**:向侧边栏添加条目,为懒加载的 React 组件。
+- **`ui.widgets`**:向现有页面注入组件(如仪表盘卡片)。
+- **`schema`**:模块自有表的 Drizzle 表定义。以 `mod__` 为前缀以避免冲突。
+- **`configSchema`**:模块配置的 JSON Schema,在模块加载前验证。
-### Entry Point
+### 入口点
-The module's `src/index.ts` exports a `register` function that receives the module API:
+模块的 `src/index.ts` 导出一个 `register` 函数,该函数接收模块 API:
```typescript
import type { ModuleAPI } from "@paperclipai/core";
@@ -143,7 +143,7 @@ export default function register(api: ModuleAPI) {
}
```
-### Module API Surface
+### 模块 API 接口
```typescript
interface ModuleAPI {
@@ -177,33 +177,33 @@ interface ModuleAPI {
}
```
-Modules get a scoped logger, access to the shared database, and read access to core services. They register their own routes and hook handlers. They do NOT monkey-patch core — they extend through defined interfaces.
+模块拥有作用域隔离的日志记录器、共享数据库访问权限以及对核心服务的只读访问。模块注册自己的路由和钩子处理器,不允许对核心进行猴子补丁——它们通过定义的接口进行扩展。
---
-## Hook System
+## 钩子系统
-### Core Hook Points
+### 核心钩子点
-Hooks are the primary integration point. The core emits events at well-defined moments. Modules subscribe in their `register` function.
+钩子是主要的集成点。核心在明确定义的时机触发事件,模块在其 `register` 函数中订阅。
-| Hook | Payload | When |
+| 钩子 | 载荷 | 触发时机 |
|------|---------|------|
-| `server:started` | `{ port }` | After the Express server begins listening |
-| `agent:created` | `{ agent }` | After a new agent is inserted |
-| `agent:updated` | `{ agent, changes }` | After an agent record is modified |
-| `agent:deleted` | `{ agent }` | After an agent is removed |
-| `agent:heartbeat` | `{ agentId, timestamp, meta }` | When an agent checks in. `meta` carries tokens_used, cost, latency, etc. |
-| `agent:status_changed` | `{ agent, from, to }` | When agent status transitions (idle→active, active→error, etc.) |
-| `issue:created` | `{ issue }` | After a new issue is inserted |
-| `issue:status_changed` | `{ issue, from, to }` | When issue moves between statuses |
-| `issue:assigned` | `{ issue, agent }` | When an issue is assigned to an agent |
-| `goal:created` | `{ goal }` | After a new goal is inserted |
-| `goal:completed` | `{ goal }` | When a goal's status becomes complete |
-| `budget:spend_recorded` | `{ agentId, amount, total }` | After spend is incremented |
-| `budget:threshold_crossed` | `{ agentId, budget, spent, percent }` | When an agent crosses 80%, 90%, or 100% of budget |
-
-### Hook Execution Model
+| `server:started` | `{ port }` | Express 服务器开始监听之后 |
+| `agent:created` | `{ agent }` | 新智能体插入之后 |
+| `agent:updated` | `{ agent, changes }` | 智能体记录修改之后 |
+| `agent:deleted` | `{ agent }` | 智能体删除之后 |
+| `agent:heartbeat` | `{ agentId, timestamp, meta }` | 智能体签到时。`meta` 携带 tokens_used、cost、latency 等信息 |
+| `agent:status_changed` | `{ agent, from, to }` | 智能体状态发生转换时(idle→active、active→error 等) |
+| `issue:created` | `{ issue }` | 新 issue 插入之后 |
+| `issue:status_changed` | `{ issue, from, to }` | issue 在状态间流转时 |
+| `issue:assigned` | `{ issue, agent }` | issue 被分配给智能体时 |
+| `goal:created` | `{ goal }` | 新目标插入之后 |
+| `goal:completed` | `{ goal }` | 目标状态变为完成时 |
+| `budget:spend_recorded` | `{ agentId, amount, total }` | 支出递增之后 |
+| `budget:threshold_crossed` | `{ agentId, budget, spent, percent }` | 智能体达到预算的 80%、90% 或 100% 时 |
+
+### 钩子执行模型
```typescript
// In the core — hook emitter
@@ -226,15 +226,15 @@ class HookBus {
}
```
-Design rules:
-- **Hooks are fire-and-forget.** A failing hook handler never crashes or blocks the core operation.
-- **Hooks are concurrent.** All handlers for an event run in parallel via `Promise.allSettled`.
-- **Hooks are post-commit.** They fire after the database write succeeds, not before. No vetoing.
-- **Hooks receive immutable snapshots.** Handlers get a copy of the data, not a mutable reference.
+设计规则:
+- **钩子是即发即忘的。** 失败的钩子处理器绝不会导致核心操作崩溃或阻塞。
+- **钩子是并发的。** 同一事件的所有处理器通过 `Promise.allSettled` 并行运行。
+- **钩子在提交后触发。** 在数据库写入成功之后触发,而非之前。不支持否决。
+- **钩子接收不可变快照。** 处理器获得数据的副本,而非可变引用。
-This keeps the core fast and resilient. If you need pre-commit validation (e.g., "reject this budget change"), that's a different mechanism (middleware/interceptor) we can add later if needed.
+这使核心保持快速且健壮。如果需要提交前验证(如"拒绝此预算变更"),那是另一种机制(中间件/拦截器),可在需要时再添加。
-### Observability Hook Example
+### 可观测性钩子示例
```typescript
// modules/observability/src/hooks.ts
@@ -262,15 +262,15 @@ export function createHeartbeatHandler(db: Db) {
}
```
-Every heartbeat, the observability module records token usage into its own `mod_observability_token_metrics` table. The core doesn't know or care about this table — it just emits the hook.
+每次心跳时,可观测性模块将 token 使用情况记录到其自有的 `mod_observability_token_metrics` 表中。核心并不知道也不关心这张表——它只是触发钩子。
---
-## Database Strategy for Modules
+## 模块数据库策略
-### Table Namespacing
+### 表命名空间
-Module tables are prefixed with `mod__` to avoid collisions with core tables and other modules:
+模块表以 `mod__` 为前缀,以避免与核心表和其他模块发生冲突:
```typescript
// modules/observability/src/schema.ts
@@ -295,45 +295,45 @@ export const alertRules = pgTable("mod_observability_alert_rules", {
});
```
-### Migration Strategy
+### 迁移策略
-Each module manages its own migrations in `src/migrations/`. The core migration runner discovers and applies them:
+每个模块在 `src/migrations/` 中管理自己的迁移。核心迁移运行器负责发现并应用它们:
-1. Core migrations run first (always)
-2. Module migrations run in dependency order
-3. Each module's migrations are tracked in a `mod_migrations` table with the module ID
-4. `pnpm db:migrate` runs everything. `pnpm db:migrate --module observability` runs one.
+1. 核心迁移优先运行(始终如此)
+2. 模块迁移按依赖顺序运行
+3. 每个模块的迁移以模块 ID 为键记录在 `mod_migrations` 表中
+4. `pnpm db:migrate` 运行所有迁移。`pnpm db:migrate --module observability` 只运行指定模块的迁移。
-Modules can reference core tables via foreign keys (e.g., `agent_id → agents.id`) but core tables never reference module tables. This is a strict one-way dependency.
+模块可以通过外键引用核心表(如 `agent_id → agents.id`),但核心表绝不引用模块表。这是严格的单向依赖关系。
---
-## Module Loading & Lifecycle
+## 模块加载与生命周期
-### Discovery
+### 发现
-On server startup:
+服务器启动时:
```
-1. Scan modules/ directory for paperclip.module.json manifests
-2. Validate each manifest (JSON Schema check on configSchema, required fields)
-3. Check slot conflicts (error if two active modules claim the same slot)
-4. Topological sort by dependencies (if module A requires module B)
-5. For each module in order:
- a. Validate module config against configSchema
- b. Run pending migrations
- c. Import entry point and call register(api)
- d. Mount routes at /api/modules/
- e. Start background services
-6. Emit server:started hook
+1. 扫描 modules/ 目录中的 paperclip.module.json 清单
+2. 验证每个清单(对 configSchema 和必填字段进行 JSON Schema 检查)
+3. 检查插槽冲突(若两个活跃模块声明同一插槽则报错)
+4. 按依赖关系拓扑排序(若模块 A 依赖模块 B)
+5. 按顺序处理每个模块:
+ a. 根据 configSchema 验证模块配置
+ b. 运行待执行的迁移
+ c. 导入入口点并调用 register(api)
+ d. 在 /api/modules/ 挂载路由
+ e. 启动后台服务
+6. 触发 server:started 钩子
```
-### Configuration
+### 配置
-Module config lives in the server's environment or a config file:
+模块配置存储在服务器环境变量或配置文件中:
```jsonc
-// paperclip.config.json (or env vars)
+// paperclip.config.json(或环境变量)
{
"modules": {
"enabled": ["observability", "revenue", "notifications"],
@@ -350,28 +350,28 @@ Module config lives in the server's environment or a config file:
}
```
-`$ENV_VAR` references are resolved at load time. Secrets never go in the config file directly.
+`$ENV_VAR` 引用在加载时解析。密钥不应直接写入配置文件。
-### Disabling a Module
+### 禁用模块
-Setting a module's enabled state to false:
-1. Stops its background services
-2. Unmounts its routes (returns 404)
-3. Unsubscribes its hook handlers
-4. Does NOT drop its database tables (data is preserved)
+将模块的启用状态设为 false 时:
+1. 停止其后台服务
+2. 卸载其路由(返回 404)
+3. 取消订阅其钩子处理器
+4. 不会删除其数据库表(数据得以保留)
---
-## UI Integration
+## UI 集成
-### How Module UI Works
+### 模块 UI 的工作方式
-The core UI shell provides:
-- A sidebar with slots for module-contributed nav items
-- A dashboard with widget mount points
-- A module settings page
+核心 UI 外壳提供:
+- 带有模块贡献导航条目插槽的侧边栏
+- 带有 widget 挂载点的仪表盘
+- 模块设置页面
-Modules declare pages and widgets in the manifest. The shell lazy-loads them:
+模块在清单中声明页面和 widget,外壳进行懒加载:
```typescript
// ui/src/modules/loader.ts
@@ -398,9 +398,9 @@ export const dashboardWidgets = [
];
```
-### Module UI Contract
+### 模块 UI 契约
-A module's UI entry exports named components:
+模块的 UI 入口导出具名组件:
```typescript
// modules/observability/src/ui/index.ts
@@ -408,7 +408,7 @@ export { default } from "./ObservabilityPage";
export { TokenBurnRateWidget } from "./TokenBurnRateWidget";
```
-Module UI components receive a standard props interface:
+模块 UI 组件接收标准的 props 接口:
```typescript
interface ModulePageProps {
@@ -423,15 +423,15 @@ interface ModuleWidgetProps {
}
```
-Module UI hits the module's own API routes (`/api/modules/observability/*`) for data.
+模块 UI 通过模块自有 API 路由(`/api/modules/observability/*`)获取数据。
---
-## Company Templates
+## 公司模板
-### Format
+### 格式
-A company template is a JSON file describing a full company structure:
+公司模板是描述完整公司结构的 JSON 文件:
```json
{
@@ -530,37 +530,37 @@ A company template is a JSON file describing a full company structure:
}
```
-Templates use `ref` strings (not UUIDs) for internal cross-references. On import, the system maps refs to generated UUIDs.
+模板使用 `ref` 字符串(非 UUID)进行内部交叉引用。导入时,系统将 ref 映射为生成的 UUID。
-### Import Flow
+### 导入流程
```
-1. Parse and validate the template JSON
-2. Check for ref uniqueness and dangling references
-3. Insert agents (topological sort by reportsTo)
-4. Insert goals (topological sort by parentRef)
-5. Insert projects
-6. Insert issues (resolve projectRef, assigneeRef, goalRef to real IDs)
-7. Log activity events for everything created
+1. 解析并验证模板 JSON
+2. 检查 ref 唯一性和悬空引用
+3. 插入智能体(按 reportsTo 拓扑排序)
+4. 插入目标(按 parentRef 拓扑排序)
+5. 插入项目
+6. 插入 issue(将 projectRef、assigneeRef、goalRef 解析为真实 ID)
+7. 为所有创建的内容记录活动事件
```
-### Export Flow
+### 导出流程
-You can also export a running company as a template:
+你也可以将运行中的公司导出为模板:
```
-GET /api/templates/export → downloads the current company as a template JSON
+GET /api/templates/export → 以模板 JSON 形式下载当前公司
```
-This makes companies shareable and clonable.
+这使公司可以分享和克隆。
---
-## Company Store
+## 公司商店
-The Company Store is a registry for discovering and installing modules and templates. For v1, it's a curated GitHub repo with a JSON index. Later it could become a hosted service.
+公司商店是用于发现和安装模块与模板的注册表。v1 版本是一个带有 JSON 索引的精选 GitHub 仓库,后续可演变为托管服务。
-### Index Format
+### 索引格式
```json
{
@@ -586,7 +586,7 @@ The Company Store is a registry for discovering and installing modules and templ
}
```
-### CLI Commands
+### CLI 命令
```bash
pnpm paperclipai store list # browse available modules and templates
@@ -597,76 +597,76 @@ pnpm paperclipai store export # export current company as templ
---
-## Module Candidates
+## 模块候选
-### Tier 1 — Build first (core extensions)
+### 第一层——优先构建(核心扩展)
-| Module | What it does | Key hooks |
+| 模块 | 功能 | 关键钩子 |
|--------|-------------|-----------|
-| **Observability** | Token usage tracking, cost metrics, agent performance dashboards, Prometheus export | `agent:heartbeat`, `budget:spend_recorded` |
-| **Revenue Tracking** | Connect Stripe/crypto wallets, track income, show P&L against agent costs | `budget:spend_recorded` |
-| **Notifications** | Slack/Discord/email alerts on configurable triggers | All hooks (configurable) |
+| **可观测性(Observability)** | Token 使用追踪、成本指标、智能体性能仪表盘、Prometheus 导出 | `agent:heartbeat`、`budget:spend_recorded` |
+| **收入追踪(Revenue Tracking)** | 连接 Stripe/加密钱包、追踪收入、对比智能体成本显示损益 | `budget:spend_recorded` |
+| **通知(Notifications)** | 基于可配置触发器的 Slack/Discord/邮件提醒 | 所有钩子(可配置) |
-### Tier 2 — High value
+### 第二层——高价值
-| Module | What it does | Key hooks |
+| 模块 | 功能 | 关键钩子 |
|--------|-------------|-----------|
-| **Analytics Dashboard** | Burn rate trends, agent utilization over time, goal velocity charts | `agent:heartbeat`, `issue:status_changed`, `goal:completed` |
-| **Workflow Automation** | If/then rules: "when issue is done, create follow-up", "when budget at 90%, pause agent" | `issue:status_changed`, `budget:threshold_crossed` |
-| **Knowledge Base** | Shared document store, vector search, agents read/write organizational knowledge | `agent:heartbeat` (for context injection) |
+| **分析仪表盘(Analytics Dashboard)** | 消耗率趋势、智能体利用率随时间变化、目标进度图表 | `agent:heartbeat`、`issue:status_changed`、`goal:completed` |
+| **工作流自动化(Workflow Automation)** | 条件规则:"issue 完成时创建跟进"、"预算达 90% 时暂停智能体" | `issue:status_changed`、`budget:threshold_crossed` |
+| **知识库(Knowledge Base)** | 共享文档存储、向量检索、智能体读写组织知识 | `agent:heartbeat`(用于上下文注入) |
-### Tier 3 — Nice to have
+### 第三层——锦上添花
-| Module | What it does | Key hooks |
+| 模块 | 功能 | 关键钩子 |
|--------|-------------|-----------|
-| **Audit & Compliance** | Immutable audit trail, approval workflows, spend authorization | All write hooks |
-| **Agent Logs / Replay** | Full execution traces per agent, token-by-token replay | `agent:heartbeat` |
-| **Multi-tenant** | Separate companies/orgs within one Paperclip instance | `server:started` |
+| **审计与合规(Audit & Compliance)** | 不可篡改的审计追踪、审批工作流、支出授权 | 所有写钩子 |
+| **智能体日志/回放(Agent Logs / Replay)** | 每个智能体的完整执行追踪、逐 token 回放 | `agent:heartbeat` |
+| **多租户(Multi-tenant)** | 在单个 Paperclip 实例中隔离多家公司/组织 | `server:started` |
---
-## Implementation Plan
+## 实现计划
-### Phase 1: Core infrastructure
+### 阶段一:核心基础设施
-Add to `@paperclipai/server`:
+添加到 `@paperclipai/server`:
-1. **HookBus** — Event emitter with `register()` and `emit()`, using `Promise.allSettled`
-2. **Module loader** — Scans `modules/`, validates manifests, calls `register(api)`
-3. **Module API object** — `registerRoutes()`, `on()`, `registerService()`, logger, core service access
-4. **Module config** — `paperclip.config.json` with per-module config, env var interpolation
-5. **Module migration runner** — Extends `db:migrate` to discover and run module migrations
-6. **Emit hooks from core services** — Add `hookBus.emit()` calls to existing CRUD operations
+1. **HookBus** — 带有 `register()` 和 `emit()` 的事件触发器,使用 `Promise.allSettled`
+2. **模块加载器** — 扫描 `modules/`,验证清单,调用 `register(api)`
+3. **模块 API 对象** — `registerRoutes()`、`on()`、`registerService()`、日志记录器、核心服务访问
+4. **模块配置** — 带有每模块配置和环境变量插值的 `paperclip.config.json`
+5. **模块迁移运行器** — 扩展 `db:migrate` 以发现并运行模块迁移
+6. **从核心服务触发钩子** — 在现有 CRUD 操作中添加 `hookBus.emit()` 调用
-Add to `@paperclipai/ui`:
+添加到 `@paperclipai/ui`:
-7. **Module page loader** — Reads module manifests, generates lazy routes
-8. **Dashboard widget slots** — Render module-contributed widgets on the Dashboard page
-9. **Sidebar extension** — Dynamically add module nav items
+7. **模块页面加载器** — 读取模块清单,生成懒加载路由
+8. **仪表盘 widget 插槽** — 在仪表盘页面渲染模块贡献的 widget
+9. **侧边栏扩展** — 动态添加模块导航条目
-Add new package:
+新增包:
-10. **`@paperclipai/module-sdk`** — TypeScript types for `ModuleAPI`, `HookEvent`, `HookHandler`, manifest schema
+10. **`@paperclipai/module-sdk`** — `ModuleAPI`、`HookEvent`、`HookHandler`、清单 schema 的 TypeScript 类型
-### Phase 2: First module (observability)
+### 阶段二:第一个模块(可观测性)
-11. Build `modules/observability` as the reference implementation
-12. Token metrics table + migration
-13. Heartbeat hook handler recording token usage
-14. Dashboard widget showing burn rate
-15. API routes for querying metrics
+11. 以 `modules/observability` 作为参考实现进行构建
+12. Token 指标表 + 迁移
+13. 记录 token 使用量的心跳钩子处理器
+14. 显示消耗率的仪表盘 widget
+15. 查询指标的 API 路由
-### Phase 3: Templates
+### 阶段三:模板
-16. Template import endpoint (`POST /api/templates/import`)
-17. Template export endpoint (`GET /api/templates/export`)
-18. First template: "Startup in a Box"
+16. 模板导入端点(`POST /api/templates/import`)
+17. 模板导出端点(`GET /api/templates/export`)
+18. 第一个模板:"Startup in a Box"
-### Phase 4: Company Store
+### 阶段四:公司商店
-19. GitHub-based store index
-20. CLI commands for browse/install/import
-21. UI page for browsing the store
+19. 基于 GitHub 的商店索引
+20. 用于浏览/安装/导入的 CLI 命令
+21. 用于浏览商店的 UI 页面
---
diff --git a/doc/plans/2026-02-18-agent-authentication-implementation.md b/doc/plans/2026-02-18-agent-authentication-implementation.md
index 809d07dd7f..4fd7ba7614 100644
--- a/doc/plans/2026-02-18-agent-authentication-implementation.md
+++ b/doc/plans/2026-02-18-agent-authentication-implementation.md
@@ -1,72 +1,72 @@
-# Agent Authentication — P0 Local Adapter JWT Implementation
+# 代理认证 — P0 本地适配器 JWT 实现
-## Scope
+## 范围
-- In-scope adapters: `claude_local`, `codex_local`.
-- Goal: zero-configuration auth for local adapters while preserving static keys for all other call paths.
-- Out-of-scope for P0: rotation UX, per-device revocation list, and CLI onboarding.
+- 适用范围内的适配器:`claude_local`、`codex_local`。
+- 目标:为本地适配器实现零配置认证,同时为所有其他调用路径保留静态密钥。
+- P0 范围外:轮换 UX、按设备的吊销列表和 CLI 引导。
-## 1) Token format and config
+## 1) 令牌格式和配置
-- Use HS256 JWTs with claims:
- - `sub` (agent id)
+- 使用 HS256 JWT,包含以下声明:
+ - `sub`(代理 ID)
- `company_id`
- `adapter_type`
- `run_id`
- `iat`
- `exp`
- - optional `jti` (run token id)
-- New config/env settings:
+ - 可选的 `jti`(运行令牌 ID)
+- 新增配置/环境设置:
- `PAPERCLIP_AGENT_JWT_SECRET`
- - `PAPERCLIP_AGENT_JWT_TTL_SECONDS` (default: `172800`)
- - `PAPERCLIP_AGENT_JWT_ISSUER` (default: `paperclip`)
- - `PAPERCLIP_AGENT_JWT_AUDIENCE` (default: `paperclip-api`)
+ - `PAPERCLIP_AGENT_JWT_TTL_SECONDS`(默认值:`172800`)
+ - `PAPERCLIP_AGENT_JWT_ISSUER`(默认值:`paperclip`)
+ - `PAPERCLIP_AGENT_JWT_AUDIENCE`(默认值:`paperclip-api`)
-## 2) Dual authentication path in `actorMiddleware`
+## 2) `actorMiddleware` 中的双重认证路径
-1. Keep the existing DB key lookup path unchanged (`agent_api_keys` hash lookup).
-2. If no DB key matches, add JWT verification in `server/src/middleware/auth.ts`.
-3. On JWT success:
- - set `req.actor = { type: "agent", agentId, companyId }`.
- - optionally guard against terminated agents.
-4. Continue board fallback for requests without valid authentication.
+1. 保持现有的数据库密钥查找路径不变(`agent_api_keys` 哈希查找)。
+2. 如果没有数据库密钥匹配,在 `server/src/middleware/auth.ts` 中添加 JWT 验证。
+3. JWT 验证成功时:
+ - 设置 `req.actor = { type: "agent", agentId, companyId }`。
+ - 可选择性地拒绝已终止的代理。
+4. 对于没有有效认证的请求,继续回退到 board 身份。
-## 3) Opt-in adapter capability
+## 3) 可选的适配器能力
-1. Extend `ServerAdapterModule` (likely `packages/adapter-utils/src/types.ts`) with a capability flag:
- - `supportsLocalAgentJwt?: true`.
-2. Enable it on:
- - `server/src/adapters/registry.ts` for `claude_local` and `codex_local`.
-3. Keep `process`/`http` adapters unset for P0.
-4. In `server/src/services/heartbeat.ts`, when adapter supports JWT:
- - mint JWT per heartbeat run before execute.
- - include token in adapter execution context.
+1. 扩展 `ServerAdapterModule`(可能在 `packages/adapter-utils/src/types.ts` 中)添加能力标志:
+ - `supportsLocalAgentJwt?: true`。
+2. 在以下位置启用:
+ - `server/src/adapters/registry.ts` 中的 `claude_local` 和 `codex_local`。
+3. P0 阶段 `process`/`http` 适配器不设置此标志。
+4. 在 `server/src/services/heartbeat.ts` 中,当适配器支持 JWT 时:
+ - 在执行前为每次心跳运行铸造 JWT。
+ - 在适配器执行上下文中包含令牌。
-## 4) Local env injection behavior
+## 4) 本地环境变量注入行为
-1. In:
+1. 在:
- `packages/adapters/claude-local/src/server/execute.ts`
- `packages/adapters/codex-local/src/server/execute.ts`
- inject `PAPERCLIP_API_KEY` from context token.
+ 从上下文令牌注入 `PAPERCLIP_API_KEY`。
-- Preserve existing behavior for explicit user-defined env vars in `adapterConfig.env`:
- - if user already sets `PAPERCLIP_API_KEY`, do not overwrite it.
-- Continue injecting:
+- 保留用户在 `adapterConfig.env` 中定义的显式环境变量的现有行为:
+ - 如果用户已设置 `PAPERCLIP_API_KEY`,则不覆盖。
+- 继续注入:
- `PAPERCLIP_AGENT_ID`
- `PAPERCLIP_COMPANY_ID`
- `PAPERCLIP_API_URL`
-## 5) Documentation updates
+## 5) 文档更新
-- Update operator-facing docs to remove manual key setup expectation for local adapters:
+- 更新面向操作员的文档,移除本地适配器的手动密钥设置期望:
- `skills/paperclip/SKILL.md`
- - `cli/src/commands/heartbeat-run.ts` output/help examples if they mention manual API key setup.
+ - `cli/src/commands/heartbeat-run.ts` 中提到手动 API 密钥设置的输出/帮助示例。
-## 6) P0 acceptance criteria
+## 6) P0 验收标准
-- Local adapters authenticate without manual `PAPERCLIP_API_KEY` config.
-- Existing static keys (`agent_api_keys`) still work unchanged.
-- Auth remains company-scoped (`req.actor.companyId` used by existing checks).
-- JWT generation and verification errors are logged as non-leaking structured events.
-- Scope remains local-only (`claude_local`, `codex_local`) while adapter capability model is generic.
+- 本地适配器无需手动配置 `PAPERCLIP_API_KEY` 即可认证。
+- 现有静态密钥(`agent_api_keys`)仍然正常工作。
+- 认证保持公司范围限定(现有检查使用 `req.actor.companyId`)。
+- JWT 生成和验证错误以不泄露信息的结构化事件方式记录。
+- 范围仅限本地(`claude_local`、`codex_local`),但适配器能力模型是通用的。
diff --git a/doc/plans/2026-02-18-agent-authentication.md b/doc/plans/2026-02-18-agent-authentication.md
index 7721ddf5ad..0622a4978b 100644
--- a/doc/plans/2026-02-18-agent-authentication.md
+++ b/doc/plans/2026-02-18-agent-authentication.md
@@ -1,123 +1,88 @@
-# Agent Authentication & Onboarding
+# 代理认证与引导
-## Problem
+## 问题
-Agents need API keys to authenticate with Paperclip. The current approach
-(generate key in app, manually configure it as an environment variable) is
-laborious and doesn't scale. Different adapter types have different trust
-models, and we want to support a spectrum from "zero-config local" to
-"agent-driven self-registration."
+代理需要 API 密钥来向 Paperclip 进行认证。当前方法(在应用中生成密钥,手动配置为环境变量)操作繁琐且不具扩展性。不同的适配器类型有不同的信任模型,我们希望支持从"零配置本地"到"代理驱动的自注册"的完整范围。
-## Design Principles
+## 设计原则
-1. **Match auth complexity to the trust boundary.** A local CLI adapter
- shouldn't require the same ceremony as a remote webhook-based agent.
-2. **Agents should be able to onboard themselves.** Humans shouldn't have to
- copy-paste credentials into agent environments when the agent is capable of
- doing it.
-3. **Approval gates by default.** Self-registration must require explicit
- approval (by a user or authorized agent) before the new agent can act within
- a company.
+1. **认证复杂度应匹配信任边界。** 本地 CLI 适配器不应与远程基于 webhook 的代理需要同样的认证流程。
+2. **代理应能自行引导。** 当代理有能力自行完成时,人类不应手动将凭据复制粘贴到代理环境中。
+3. **默认需要审批门控。** 自注册必须在新代理可以在公司内操作之前获得明确的审批(由用户或授权代理)。
---
-## Authentication Tiers
+## 认证层级
-### Tier 1: Local Adapter (claude-local, codex-local)
+### 第一层:本地适配器(claude-local、codex-local)
-**Trust model:** The adapter process runs on the same machine as the Paperclip
-server (or is invoked directly by it). There is no meaningful network boundary.
+**信任模型:** 适配器进程与 Paperclip 服务器运行在同一台机器上(或由其直接调用)。没有实质性的网络边界。
-**Approach:** Paperclip generates a token and passes it directly to the agent
-process as a parameter/env var at invocation time. No manual setup required.
+**方法:** Paperclip 生成令牌并在调用时直接作为参数/环境变量传递给代理进程。无需手动设置。
-**Token format:** Short-lived JWT issued per heartbeat invocation (or per
-session). The server mints the token, passes it in the adapter call, and
-accepts it back on API requests.
+**令牌格式:** 每次心跳调用(或每个会话)签发的短期 JWT。服务器铸造令牌,在适配器调用中传递,并在 API 请求中接受返回。
-**Token lifetime considerations:**
+**令牌生命周期考虑:**
-- Coding agents can run for hours, so tokens can't expire too quickly.
-- Infinite-lived tokens are undesirable even in local contexts.
-- Use JWTs with a generous expiry (e.g. 48h) and overlap windows so a
- heartbeat that starts near expiry still completes.
-- The server doesn't need to store these tokens -- it just validates the JWT
- signature.
+- 编程代理可能运行数小时,因此令牌不能过快过期。
+- 即使在本地环境中,无限期令牌也不可取。
+- 使用具有宽松过期时间(例如 48 小时)的 JWT,并设置重叠窗口,使在过期附近开始的心跳仍能完成。
+- 服务器不需要存储这些令牌——只需验证 JWT 签名。
-**Status:** Partially implemented. The local adapter already passes
-`PAPERCLIP_API_URL`, `PAPERCLIP_AGENT_ID`, `PAPERCLIP_COMPANY_ID`. We need to
-add a `PAPERCLIP_API_KEY` (JWT) to the set of injected env vars.
+**状态:** 部分实现。本地适配器已经传递 `PAPERCLIP_API_URL`、`PAPERCLIP_AGENT_ID`、`PAPERCLIP_COMPANY_ID`。我们需要在注入的环境变量集合中添加 `PAPERCLIP_API_KEY`(JWT)。
-### Tier 2: CLI-Driven Key Exchange
+### 第二层:CLI 驱动的密钥交换
-**Trust model:** A developer is setting up a remote or semi-remote agent and
-has shell access to it.
+**信任模型:** 开发者正在设置远程或半远程代理,并拥有其 shell 访问权限。
-**Approach:** Similar to `claude setup-token` -- the developer runs a Paperclip CLI
-command that opens a browser URL for confirmation, then receives a token that
-gets stored in the agent's config automatically.
+**方法:** 类似于 `claude setup-token`——开发者运行 Paperclip CLI 命令,打开浏览器 URL 进行确认,然后收到自动存储在代理配置中的令牌。
```
paperclip auth login
-# Opens browser -> user confirms -> token stored at ~/.paperclip/credentials
+# 打开浏览器 -> 用户确认 -> 令牌存储在 ~/.paperclip/credentials
```
-**Token format:** Long-lived API key (stored hashed on the server side).
-
-**Status:** Future. Not needed until we have remote adapters that aren't
-managed by the Paperclip server itself.
-
-### Tier 3: Agent Self-Registration (Invite Link)
-
-**Trust model:** The agent is an autonomous external system (e.g. an OpenClaw
-agent, a SWE-agent instance). There is no human in the loop during setup. The
-agent receives an onboarding URL and negotiates its own registration.
-
-**Approach:**
-
-1. A company admin (user or agent) generates an **invite URL** from Paperclip.
-2. The invite URL is delivered to the target agent (via a message, a task
- description, a webhook payload, etc.).
-3. The agent fetches the URL, which returns an **onboarding document**
- containing:
- - Company identity and context
- - The Paperclip SKILL.md (or a link to it)
- - What information Paperclip needs from the agent (e.g. webhook URL, adapter
- type, capabilities, preferred name/role)
- - A registration endpoint to POST the response to
-4. The agent responds with its configuration (e.g. "here's my webhook URL,
- here's my name, here are my capabilities").
-5. Paperclip stores the pending registration.
-6. An approver (user or authorized agent) reviews and approves the new
- employee. Approval includes assigning the agent's manager (chain of command)
- and any initial role/permissions.
-7. On approval, Paperclip provisions the agent's credentials and sends the
- first heartbeat.
-
-**Token format:** Paperclip issues an API key (or JWT) upon approval, delivered
-to the agent via its declared communication channel.
-
-**Inspiration:**
-
-- [Allium self-registration](https://agents.allium.so/skills/skill.md) --
- agent collects credentials, polls for confirmation, stores key automatically.
-- [Allium x402](https://agents.allium.so/skills/x402-skill.md) -- multi-step
- credential setup driven entirely by the agent.
-- [OpenClaw webhooks](https://docs.openclaw.ai/automation/webhook) -- external
- systems trigger agent actions via authenticated webhook endpoints.
+**令牌格式:** 长期 API 密钥(在服务器端以哈希形式存储)。
+
+**状态:** 未来实现。在我们拥有不由 Paperclip 服务器自身管理的远程适配器之前不需要。
+
+### 第三层:代理自注册(邀请链接)
+
+**信任模型:** 代理是一个自主的外部系统(例如 OpenClaw 代理、SWE-agent 实例)。设置过程中没有人类参与。代理接收引导 URL 并自行协商注册。
+
+**方法:**
+
+1. 公司管理员(用户或代理)从 Paperclip 生成**邀请 URL**。
+2. 邀请 URL 被传递给目标代理(通过消息、任务描述、webhook 负载等)。
+3. 代理获取 URL,返回一个**引导文档**,包含:
+ - 公司身份和上下文
+ - Paperclip SKILL.md(或其链接)
+ - Paperclip 需要代理提供的信息(例如 webhook URL、适配器类型、能力、首选名称/角色)
+ - 用于 POST 响应的注册端点
+4. 代理回复其配置(例如"这是我的 webhook URL,这是我的名称,这些是我的能力")。
+5. Paperclip 存储待审核的注册。
+6. 审批者(用户或授权代理)审核并批准新员工。审批包括分配代理的管理者(指挥链)和初始角色/权限。
+7. 审批通过后,Paperclip 为代理提供凭据并发送第一次心跳。
+
+**令牌格式:** Paperclip 在审批后签发 API 密钥(或 JWT),通过代理声明的通信渠道发送。
+
+**参考:**
+
+- [Allium 自注册](https://agents.allium.so/skills/skill.md)——代理收集凭据,轮询确认,自动存储密钥。
+- [Allium x402](https://agents.allium.so/skills/x402-skill.md)——完全由代理驱动的多步骤凭据设置。
+- [OpenClaw webhooks](https://docs.openclaw.ai/automation/webhook)——外部系统通过经过认证的 webhook 端点触发代理操作。
---
-## Self-Registration: Onboarding Negotiation Protocol
+## 自注册:引导协商协议
-The invite URL response should be a structured document (JSON or markdown) that
-is both human-readable and machine-parseable:
+邀请 URL 响应应该是一个结构化文档(JSON 或 markdown),既可人类阅读又可机器解析:
```
GET /api/invite/{inviteToken}
```
-Response:
+响应:
```json
{
@@ -139,7 +104,7 @@ Response:
}
```
-The agent POSTs back:
+代理回复 POST:
```json
{
@@ -151,72 +116,63 @@ The agent POSTs back:
}
```
-This goes into a `pending_approval` state until someone approves it.
+这将进入 `pending_approval` 状态,直到有人批准。
---
-## OpenClaw as First External Integration
+## OpenClaw 作为首个外部集成
-OpenClaw is the ideal first target for Tier 3 because:
+OpenClaw 是第三层的理想首选目标,因为:
-- It already has webhook support (`POST /hooks/agent`) for receiving tasks.
-- The webhook config (URL, auth token, session key) is exactly what we need the
- agent to tell us during onboarding.
-- OpenClaw agents can read a URL, parse instructions, and make HTTP calls.
+- 它已经支持 webhook(`POST /hooks/agent`)来接收任务。
+- webhook 配置(URL、认证令牌、会话密钥)正是我们需要代理在引导过程中告诉我们的内容。
+- OpenClaw 代理可以读取 URL、解析指令并发起 HTTP 调用。
-**Workflow:**
+**工作流:**
-1. Generate a Paperclip invite link for the company.
-2. Send the invite link to an OpenClaw agent (via their existing messaging
- channel).
-3. The OpenClaw agent fetches the invite, reads the onboarding doc, and
- responds with its webhook configuration.
-4. A Paperclip company member approves the new agent.
-5. Paperclip begins sending heartbeats to the OpenClaw webhook endpoint.
+1. 为公司生成 Paperclip 邀请链接。
+2. 将邀请链接发送给 OpenClaw 代理(通过其现有的消息通道)。
+3. OpenClaw 代理获取邀请,阅读引导文档,并回复其 webhook 配置。
+4. Paperclip 公司成员批准新代理。
+5. Paperclip 开始向 OpenClaw webhook 端点发送心跳。
---
-## Approval Model
+## 审批模型
-All self-registration requires approval. This is non-negotiable for security.
+所有自注册都需要审批。这对安全性来说是不可协商的。
-- **Default:** A human user in the company must approve.
-- **Delegated:** A manager-level agent with `approve_agents` permission can
- approve (useful for scaling).
-- **Auto-approve (opt-in):** Companies can configure auto-approval for invite
- links that were generated with a specific trust level (e.g. "I trust anyone
- with this link"). Even then, the invite link itself is a secret.
+- **默认:** 公司内的人类用户必须批准。
+- **委托:** 拥有 `approve_agents` 权限的管理级代理可以批准(适用于扩展)。
+- **自动批准(可选加入):** 公司可以为使用特定信任级别生成的邀请链接配置自动批准(例如"我信任任何持有此链接的人")。即便如此,邀请链接本身也是机密信息。
-On approval, the approver sets:
+审批时,审批者设置:
-- `reportsTo` -- who the new agent reports to in the chain of command
-- `role` -- the agent's role within the company
-- `budget` -- initial budget allocation
+- `reportsTo`——新代理在指挥链中向谁报告
+- `role`——代理在公司中的角色
+- `budget`——初始预算分配
---
-## Implementation Priorities
+## 实施优先级
-| Priority | Item | Notes |
+| 优先级 | 项目 | 备注 |
| -------- | --------------------------------- | ------------------------------------------------------------------------------------------------ |
-| **P0** | Local adapter JWT injection | Unblocks zero-config local auth. Mint a JWT per heartbeat, pass as `PAPERCLIP_API_KEY`. |
-| **P1** | Invite link + onboarding endpoint | `POST /api/companies/:id/invites`, `GET /api/invite/:token`, `POST /api/invite/:token/register`. |
-| **P1** | Approval flow | UI + API for reviewing and approving pending agent registrations. |
-| **P2** | OpenClaw integration | First real external agent onboarding via invite link. |
-| **P3** | CLI auth flow | `paperclipai auth login` for developer-managed remote agents. |
+| **P0** | 本地适配器 JWT 注入 | 解锁零配置本地认证。每次心跳铸造 JWT,作为 `PAPERCLIP_API_KEY` 传递。 |
+| **P1** | 邀请链接 + 引导端点 | `POST /api/companies/:id/invites`、`GET /api/invite/:token`、`POST /api/invite/:token/register`。 |
+| **P1** | 审批流程 | 用于审核和批准待处理代理注册的 UI + API。 |
+| **P2** | OpenClaw 集成 | 通过邀请链接实现首个真正的外部代理引导。 |
+| **P3** | CLI 认证流程 | 用于开发者管理的远程代理的 `paperclipai auth login`。 |
-## P0 Implementation Plan
+## P0 实施计划
-See [`doc/plans/agent-authentication-implementation.md`](./agent-authentication-implementation.md) for the P0 local JWT execution plan.
+有关 P0 本地 JWT 执行计划,请参阅 [`doc/plans/agent-authentication-implementation.md`](./agent-authentication-implementation.md)。
---
-## Open Questions
+## 待定问题
-- **JWT signing key rotation:** How do we rotate the signing key without
- invalidating in-flight heartbeats?
-- **Invite link expiry:** Should invite links be single-use or multi-use? Time-limited?
-- **Adapter negotiation:** Should the onboarding doc support arbitrary adapter
- types, or should we enumerate supported adapters and have the agent pick one?
-- **Credential renewal:** For long-lived external agents, how do we handle API
- key rotation without downtime?
+- **JWT 签名密钥轮换:** 如何在不使进行中的心跳失效的情况下轮换签名密钥?
+- **邀请链接过期:** 邀请链接应该是一次性使用还是多次使用?是否有时间限制?
+- **适配器协商:** 引导文档是否应支持任意适配器类型,还是应该枚举支持的适配器让代理选择?
+- **凭据更新:** 对于长期运行的外部代理,如何在不停机的情况下处理 API 密钥轮换?
diff --git a/doc/plans/2026-02-19-agent-mgmt-followup-plan.md b/doc/plans/2026-02-19-agent-mgmt-followup-plan.md
index 5d01d5d404..62647e0f2d 100644
--- a/doc/plans/2026-02-19-agent-mgmt-followup-plan.md
+++ b/doc/plans/2026-02-19-agent-mgmt-followup-plan.md
@@ -1,101 +1,101 @@
-# Agent Management Follow-up Plan (CEO Patch + Config Rollback + Issue↔Approval Linking)
+# 代理管理后续计划(CEO 补丁 + 配置回滚 + Issue↔审批关联)
-Status: Proposed
-Date: 2026-02-19
-Context: Follow-up from run `faeab00e-7857-4acc-b2b2-86f6d078adb4`
+状态:提议
+日期:2026-02-19
+上下文:来自运行 `faeab00e-7857-4acc-b2b2-86f6d078adb4` 的后续
-## 1. Investigation Findings
+## 1. 调查发现
-## 1.1 Why CEO PATCH failed
+## 1.1 CEO PATCH 失败的原因
-Root cause is explicit route logic:
+根本原因是显式的路由逻辑:
-- `server/src/routes/agents.ts` currently blocks any agent patching another agent:
+- `server/src/routes/agents.ts` 当前阻止任何代理修改另一个代理:
- `if (req.actor.type === "agent" && req.actor.agentId !== id) { ... "Agent can only modify itself" }`
-So even though the CEO has hire permission, the route still enforces old self-only patch behavior.
+因此,即使 CEO 拥有招聘权限,路由仍然执行旧的仅限自身修改行为。
-## 1.2 Why comment quality felt wrong
+## 1.2 评论质量不佳的原因
-- `skills/paperclip/SKILL.md` and `skills/paperclip/references/api-reference.md` do not currently require markdown formatting quality for status comments (links, structure, readable updates).
-- Agents therefore produce plain prose comments with raw IDs, not linked entities.
+- `skills/paperclip/SKILL.md` 和 `skills/paperclip/references/api-reference.md` 目前不要求状态评论具备 markdown 格式化质量(链接、结构、可读的更新)。
+- 因此代理生成的评论是包含原始 ID 的纯文本,而非链接实体。
-## 1.3 Issue↔Approval linkage gap
+## 1.3 Issue↔审批关联缺失
-- There is no direct DB relation between issues and approvals today.
-- Approval payloads may include contextual IDs, but this is not canonical linkage.
-- UI pages cannot reliably cross-link issue/approval without manual copy-paste IDs.
+- 目前 issue 和审批之间没有直接的数据库关系。
+- 审批负载可能包含上下文 ID,但这不是规范化的关联。
+- UI 页面在没有手动复制粘贴 ID 的情况下无法可靠地交叉链接 issue/审批。
-## 1.4 Config rollback gap
+## 1.4 配置回滚缺失
-- Agent config updates currently overwrite state with no dedicated revision history table.
-- There is activity logging, but no first-class config version ledger or rollback endpoint.
+- 代理配置更新当前直接覆盖状态,没有专用的版本历史表。
+- 存在活动日志,但没有一等公民的配置版本账本或回滚端点。
-## 2. Product/Behavior Changes
+## 2. 产品/行为变更
-## 2.1 Allow CEO to patch other same-company agents
+## 2.1 允许 CEO 修改同公司的其他代理
-Target behavior:
+目标行为:
-- Board: full patch rights.
-- CEO: can patch agents in same company.
-- Other agents: self-only patch unless explicitly granted future permission.
+- Board:完全修改权限。
+- CEO:可以修改同公司的代理。
+- 其他代理:仅限自身修改,除非未来明确授予权限。
-Note:
+注意:
-- Keep company boundary checks strict.
-- Keep privileged fields separately governed.
+- 保持公司边界检查严格。
+- 保持特权字段的单独管理。
-## 2.2 Add first-class agent configuration revision log + rollback
+## 2.2 添加一等公民的代理配置版本日志 + 回滚
-Every config-affecting mutation must create a revision record with:
+每个影响配置的变更必须创建一个版本记录,包含:
-- before snapshot
-- after snapshot
-- actor info (user/agent)
-- optional reason/comment
-- source run ID (if available)
+- 变更前快照
+- 变更后快照
+- 操作者信息(用户/代理)
+- 可选的原因/评论
+- 来源运行 ID(如有)
-Rollback must be one API call that restores a prior revision atomically.
+回滚必须是一次 API 调用即可原子性地恢复先前版本。
-## 2.3 Enforce markdown and links for issue comments in skills
+## 2.3 在技能中强制 issue 评论使用 markdown 和链接
-Skill guidance should require:
+技能指导应要求:
-- short markdown structure (`Summary`, `Actions`, `Next`)
-- links to created/updated entities when relevant
-- avoid raw IDs without links
+- 简短的 markdown 结构(`Summary`、`Actions`、`Next`)
+- 在相关时包含已创建/更新实体的链接
+- 避免不带链接的原始 ID
-## 2.4 Add explicit Issue↔Approval linkage (many-to-many)
+## 2.4 添加显式的 Issue↔审批关联(多对多)
-Implement canonical join model so one issue can link many approvals and one approval can link many issues.
+实现规范化的关联模型,使一个 issue 可以关联多个审批,一个审批可以关联多个 issue。
-## 3. Data Model Plan
+## 3. 数据模型计划
-## 3.1 New table: `agent_config_revisions`
+## 3.1 新表:`agent_config_revisions`
-Columns:
+列:
- `id` uuid pk
- `company_id` uuid fk
- `agent_id` uuid fk
-- `revision_number` int (monotonic per agent)
+- `revision_number` int(每个代理单调递增)
- `reason` text null
- `changed_by_agent_id` uuid null
- `changed_by_user_id` text null
- `run_id` uuid null
- `before_snapshot` jsonb not null
- `after_snapshot` jsonb not null
-- timestamps
+- 时间戳
-Indexes:
+索引:
- `(company_id, agent_id, revision_number desc)`
- `(agent_id, created_at desc)`
-## 3.2 New table: `issue_approvals`
+## 3.2 新表:`issue_approvals`
-Columns:
+列:
- `id` uuid pk
- `company_id` uuid fk
@@ -104,146 +104,146 @@ Columns:
- `relationship` text default `context`
- `linked_by_agent_id` uuid null
- `linked_by_user_id` text null
-- timestamps
+- 时间戳
-Constraints:
+约束:
- unique `(company_id, issue_id, approval_id)`
-Indexes:
+索引:
- `(company_id, issue_id)`
- `(company_id, approval_id)`
-## 4. API Plan
+## 4. API 计划
-## 4.1 Agent PATCH authz fix
+## 4.1 代理 PATCH 授权修复
-Update `PATCH /api/agents/:id` authz matrix:
+更新 `PATCH /api/agents/:id` 授权矩阵:
-- board: allow
-- agent role `ceo` in same company: allow
-- otherwise: self only
+- board:允许
+- 同公司角色为 `ceo` 的代理:允许
+- 其他:仅限自身
-## 4.2 Separate privileged patch fields
+## 4.2 分离特权修改字段
-Protect these from generic PATCH by non-board/non-ceo:
+保护以下字段不受非 board/非 CEO 的通用 PATCH 修改:
- `permissions`
-- `status` transitions outside allowed scope
+- 超出允许范围的 `status` 转换
-(Continue using dedicated permission route for permission edits.)
+(权限编辑继续使用专用权限路由。)
-## 4.3 Config revision APIs
+## 4.3 配置版本 API
-Add:
+添加:
- `GET /api/agents/:id/config-revisions`
- `GET /api/agents/:id/config-revisions/:revisionId`
- `POST /api/agents/:id/config-revisions/:revisionId/rollback`
-Behavior:
+行为:
-- rollback writes a new revision entry (does not mutate history)
-- rollback response includes resulting active config
+- 回滚写入一条新的版本记录(不修改历史)
+- 回滚响应包含结果活动配置
-## 4.4 Issue↔Approval link APIs
+## 4.4 Issue↔审批关联 API
-Add:
+添加:
- `GET /api/issues/:id/approvals`
-- `POST /api/issues/:id/approvals` (link existing approval)
+- `POST /api/issues/:id/approvals`(关联已有审批)
- `DELETE /api/issues/:id/approvals/:approvalId`
- `GET /api/approvals/:id/issues`
-## 4.5 Auto-link on approval creation
+## 4.5 审批创建时自动关联
-Extend create payloads to optionally include issue context:
+扩展创建负载以可选地包含 issue 上下文:
-- `POST /api/companies/:companyId/approvals` supports `issueId` or `issueIds`
-- `POST /api/companies/:companyId/agent-hires` supports `sourceIssueId` or `sourceIssueIds`
+- `POST /api/companies/:companyId/approvals` 支持 `issueId` 或 `issueIds`
+- `POST /api/companies/:companyId/agent-hires` 支持 `sourceIssueId` 或 `sourceIssueIds`
-Server behavior:
+服务器行为:
-- create approval first
-- insert link rows in `issue_approvals`
+- 先创建审批
+- 在 `issue_approvals` 中插入关联行
-## 5. UI Plan
+## 5. UI 计划
-## 5.1 Agent page
+## 5.1 代理页面
-Add configuration history panel on `AgentDetail`:
+在 `AgentDetail` 上添加配置历史面板:
-- revision list
-- diff preview
-- rollback button with confirmation
+- 版本列表
+- 差异预览
+- 带确认的回滚按钮
-## 5.2 Approval page and Issue page cross-links
+## 5.2 审批页面和 Issue 页面交叉链接
-- On approval detail: show linked issues with links
-- On issue detail: show linked approvals with links
-- link/unlink actions in board context
+- 在审批详情上:显示带链接的关联 issue
+- 在 issue 详情上:显示带链接的关联审批
+- board 上下文中的关联/取消关联操作
-## 5.3 Better comment UX cues
+## 5.3 改善评论 UX 提示
-No hard editor enforcement initially; update helper text and templates to encourage linked markdown updates.
+初始阶段不做硬编辑器强制;更新帮助文本和模板以鼓励使用带链接的 markdown 更新。
-## 6. Skill Updates
+## 6. 技能更新
## 6.1 `skills/paperclip/SKILL.md`
-Add comment standard:
+添加评论标准:
-- Use markdown sections
-- Include links for related entities:
- - approval: `/approvals/{id}`
- - agent: `/agents/{id}`
- - issue: `/issues/{id}`
+- 使用 markdown 章节
+- 包含相关实体的链接:
+ - 审批:`/approvals/{id}`
+ - 代理:`/agents/{id}`
+ - issue:`/issues/{id}`
## 6.2 `skills/paperclip-create-agent/SKILL.md`
-Require:
+要求:
-- include `sourceIssueId` when hire is created from an issue
-- comment back to issue with markdown + links to approval and pending agent
+- 从 issue 创建招聘时包含 `sourceIssueId`
+- 在 issue 中回复评论,使用 markdown + 审批和待处理代理的链接
-## 7. Implementation Phases
+## 7. 实施阶段
-## Phase A: Authz + safety hardening
+## 阶段 A:授权 + 安全加固
-- Fix CEO patch authz in agent route
-- Restrict privileged generic patch fields
-- Add tests for authz matrix
+- 修复代理路由中的 CEO 修改授权
+- 限制特权通用修改字段
+- 添加授权矩阵测试
-## Phase B: Config revision ledger
+## 阶段 B:配置版本账本
-- Add `agent_config_revisions`
-- Write-on-change for all relevant agent mutations
-- rollback endpoints + tests
+- 添加 `agent_config_revisions`
+- 对所有相关代理变更执行变更时写入
+- 回滚端点 + 测试
-## Phase C: Issue↔Approval linking
+## 阶段 C:Issue↔审批关联
-- Add `issue_approvals`
-- add link APIs + auto-link behavior
-- update approvals/issues UI cross-links
+- 添加 `issue_approvals`
+- 添加关联 API + 自动关联行为
+- 更新审批/issue UI 交叉链接
-## Phase D: Skill guidance
+## 阶段 D:技能指导
-- update skills for markdown/link expectations and sourceIssue linking
+- 更新技能中的 markdown/链接期望和 sourceIssue 关联
-## 8. Acceptance Criteria
+## 8. 验收标准
-- CEO can patch CTO (same company) successfully.
-- Every config change creates a retrievable revision.
-- Rollback restores prior config in one action and creates a new revision record.
-- Issue and approval pages show stable bidirectional links from canonical DB relation.
-- Agent comments in hiring workflow use markdown and include entity links.
+- CEO 可以成功修改 CTO(同公司)。
+- 每次配置变更创建可检索的版本记录。
+- 回滚在一次操作中恢复先前配置并创建新的版本记录。
+- Issue 和审批页面显示来自规范化数据库关系的稳定双向链接。
+- 招聘工作流中的代理评论使用 markdown 并包含实体链接。
-## 9. Risks and Mitigations
+## 9. 风险和缓解措施
-- Risk: permission escalation via generic PATCH.
- - Mitigation: isolate privileged fields and validate actor scope.
-- Risk: rollback corruption.
- - Mitigation: snapshot-before/snapshot-after + transaction + tests.
-- Risk: ambiguous linking semantics.
- - Mitigation: explicit join table + unique constraints + typed relationship field.
+- 风险:通过通用 PATCH 进行权限升级。
+ - 缓解:隔离特权字段并验证操作者范围。
+- 风险:回滚损坏。
+ - 缓解:变更前快照/变更后快照 + 事务 + 测试。
+- 风险:关联语义不明确。
+ - 缓解:显式关联表 + 唯一约束 + 类型化关系字段。
diff --git a/doc/plans/2026-02-19-ceo-agent-creation-and-hiring.md b/doc/plans/2026-02-19-ceo-agent-creation-and-hiring.md
index a2631e4f86..7c995e1638 100644
--- a/doc/plans/2026-02-19-ceo-agent-creation-and-hiring.md
+++ b/doc/plans/2026-02-19-ceo-agent-creation-and-hiring.md
@@ -1,160 +1,160 @@
-# CEO Agent Creation and Hiring Governance Plan (V1.1)
+# CEO 代理创建与招聘治理计划(V1.1)
-Status: Proposed
-Date: 2026-02-19
-Owner: Product + Server + UI + Skills
+状态:提议
+日期:2026-02-19
+负责人:产品 + 服务器 + UI + 技能
-## 1. Goal
+## 1. 目标
-Enable a CEO agent to create new agents directly, with lightweight but explicit governance:
+使 CEO 代理能够直接创建新代理,配以轻量但明确的治理机制:
-- Company-level toggle: new hires require board approval (default ON).
-- Agent-level permission: `can_create_agents` (default ON for CEO, OFF for everyone else).
-- Clear hire workflow with draft/limbo state until approval.
-- Config reflection so hiring agents can inspect available adapter configuration and compare existing agent configs (including self).
-- Approval collaboration flow with comments, revision requests, and audit trail.
+- 公司级别开关:新招聘需要 board 审批(默认开启)。
+- 代理级别权限:`can_create_agents`(CEO 默认开启,其他人默认关闭)。
+- 清晰的招聘工作流,具有草稿/待审核状态直到获得审批。
+- 配置反射,使招聘代理可以检查可用的适配器配置并比较现有代理配置(包括自身)。
+- 审批协作流程,包含评论、修订请求和审计追踪。
-## 2. Current State (Repo Reality)
+## 2. 当前状态(仓库实际情况)
-- Agent creation is board-only at `POST /api/companies/:companyId/agents` (`server/src/routes/agents.ts`).
-- Approvals support `pending/approved/rejected/cancelled` and `hire_agent` + `approve_ceo_strategy` (`packages/shared/src/constants.ts`, `server/src/services/approvals.ts`).
-- `hire_agent` approval currently creates the agent only on approval; there is no pre-created limbo agent.
-- There is no agent permissions system today.
-- There is no company setting for "new hires require board approval".
-- Approvals have no comment thread or revision-request state.
-- Inbox and Approvals UIs support approve/reject only; no approval detail route exists in app routes.
-- Agent adapter configuration is free-form JSON; no runtime reflection endpoint exists for machine-readable or text discovery.
+- 代理创建仅限 board,位于 `POST /api/companies/:companyId/agents`(`server/src/routes/agents.ts`)。
+- 审批支持 `pending/approved/rejected/cancelled` 和 `hire_agent` + `approve_ceo_strategy`(`packages/shared/src/constants.ts`、`server/src/services/approvals.ts`)。
+- `hire_agent` 审批目前仅在批准时创建代理;不存在预创建的待审核代理。
+- 目前没有代理权限系统。
+- 没有"新招聘需要 board 审批"的公司设置。
+- 审批没有评论线程或修订请求状态。
+- 收件箱和审批 UI 仅支持批准/拒绝;应用路由中不存在审批详情路由。
+- 代理适配器配置是自由格式 JSON;不存在用于机器可读或文本发现的运行时反射端点。
-## 3. Product Decisions
+## 3. 产品决策
-## 3.1 Company setting
+## 3.1 公司设置
-Add company setting:
+添加公司设置:
- `requireBoardApprovalForNewAgents: boolean`
-- Default: `true`
-- Editable only in company advanced settings (not onboarding/company creation flow UI)
+- 默认值:`true`
+- 仅在公司高级设置中可编辑(不在引导/公司创建流程 UI 中)
-## 3.2 Agent permissions
+## 3.2 代理权限
-Introduce lightweight permission model with one explicit permission now:
+引入轻量级权限模型,目前只有一个显式权限:
- `can_create_agents: boolean`
-Defaults:
+默认值:
-- CEO: `true`
-- Everyone else: `false`
+- CEO:`true`
+- 其他人:`false`
-Authority:
+管理权限:
-- Board can edit permissions for any agent.
-- CEO can edit permissions for agents in same company.
+- Board 可以编辑任何代理的权限。
+- CEO 可以编辑同公司代理的权限。
-No broader RBAC system in this phase.
+此阶段不引入更广泛的 RBAC 系统。
-## 3.3 Limbo state for hires
+## 3.3 招聘的待审核状态
-Introduce dedicated non-operational status:
+引入专用的非运行状态:
- `pending_approval`
-Meaning:
+含义:
-- Agent record exists in org tree and can be reviewed.
-- Agent cannot run, receive assignments, create keys, or be resumed to active states until approved.
+- 代理记录存在于组织树中,可以被审核。
+- 代理在获得批准之前不能运行、接收分配、创建密钥或恢复到活动状态。
-## 4. Data Model Changes
+## 4. 数据模型变更
## 4.1 `companies`
-Add column:
+添加列:
- `require_board_approval_for_new_agents` boolean not null default `true`
-Sync required:
+需要同步:
- `packages/db/src/schema/companies.ts`
- `packages/shared/src/types/company.ts`
- `packages/shared/src/validators/company.ts`
-- UI company API type usage and company advanced settings form
+- UI 公司 API 类型用法和公司高级设置表单
## 4.2 `agents`
-Add columns:
+添加列:
- `permissions` jsonb not null default `{}`
-- status value expansion to include `pending_approval`
+- 状态值扩展以包含 `pending_approval`
-Sync required:
+需要同步:
- `packages/db/src/schema/agents.ts`
-- `packages/shared/src/constants.ts` (`AGENT_STATUSES`)
+- `packages/shared/src/constants.ts`(`AGENT_STATUSES`)
- `packages/shared/src/types/agent.ts`
- `packages/shared/src/validators/agent.ts`
-- status badges, filters, and lifecycle controls in UI
+- UI 中的状态徽章、筛选器和生命周期控制
## 4.3 `approvals`
-Keep approval as central governance record; extend workflow support:
+保持审批作为中央治理记录;扩展工作流支持:
-- add status `revision_requested`
-- ensure payload for hire approvals contains:
+- 添加状态 `revision_requested`
+- 确保招聘审批的负载包含:
- `agentId`
- `requestedByAgentId`
- `requestedConfigurationSnapshot`
-## 4.4 New `approval_comments` table
+## 4.4 新表 `approval_comments`
-Add discussion thread for approvals:
+为审批添加讨论线程:
-- `id`, `company_id`, `approval_id`, `author_agent_id`, `author_user_id`, `body`, timestamps
+- `id`、`company_id`、`approval_id`、`author_agent_id`、`author_user_id`、`body`、时间戳
-Purpose:
+用途:
-- review comments
-- revision requests
-- rationale for approve/reject
-- permanent audit trail
+- 审核评论
+- 修订请求
+- 批准/拒绝的理由
+- 永久审计追踪
-## 5. API and AuthZ Plan
+## 5. API 和授权计划
-## 5.1 Permission helpers
+## 5.1 权限辅助函数
-Add server-side authz helpers:
+添加服务器端授权辅助函数:
- `assertCanCreateAgents(req, companyId)`
- `assertCanManageAgentPermissions(req, companyId)`
-Rules:
+规则:
-- Board always passes.
-- Agent passes `can_create_agents` check if self permission true and same company.
-- Permission management by CEO or board.
+- Board 始终通过。
+- 代理在自身权限为 true 且同公司时通过 `can_create_agents` 检查。
+- 权限管理由 CEO 或 board 执行。
-## 5.2 Hire creation flow
+## 5.2 招聘创建流程
-Add route:
+添加路由:
- `POST /api/companies/:companyId/agent-hires`
-Behavior:
+行为:
-- Requires `can_create_agents` (or board).
-- Creates agent row first.
-- If company setting requires approval:
- - create agent with `status=pending_approval`
- - create `approvals(type=hire_agent,status=pending,payload.agentId=...)`
- - return both agent + approval
-- If setting disabled:
- - create agent as `idle`
- - no approval record required
+- 需要 `can_create_agents`(或 board)。
+- 首先创建代理行。
+- 如果公司设置要求审批:
+ - 以 `status=pending_approval` 创建代理
+ - 创建 `approvals(type=hire_agent,status=pending,payload.agentId=...)`
+ - 返回代理 + 审批
+- 如果设置禁用:
+ - 以 `idle` 状态创建代理
+ - 不需要审批记录
-Board may continue using direct create route, but this route becomes canonical for CEO/agent-led hiring.
+Board 可以继续使用直接创建路由,但此路由成为 CEO/代理主导招聘的规范路由。
-## 5.3 Approval workflow endpoints
+## 5.3 审批工作流端点
-Add/extend:
+添加/扩展:
- `GET /api/approvals/:id`
- `POST /api/approvals/:id/request-revision`
@@ -162,228 +162,228 @@ Add/extend:
- `GET /api/approvals/:id/comments`
- `POST /api/approvals/:id/comments`
-Update existing approve/reject semantics:
+更新现有的批准/拒绝语义:
-- approve of hire transitions linked agent `pending_approval -> idle`
-- reject keeps linked agent in non-active state (`pending_approval` or `terminated`/purged later)
+- 批准招聘将关联代理从 `pending_approval -> idle` 转换
+- 拒绝使关联代理保持非活动状态(`pending_approval` 或稍后 `terminated`/清除)
-## 5.4 Agent permission management endpoints
+## 5.4 代理权限管理端点
-Add:
+添加:
- `PATCH /api/agents/:id/permissions`
-Supports initial key only:
+仅支持初始键:
- `{ "canCreateAgents": boolean }`
-## 5.5 Read config endpoints (protected)
+## 5.5 读取配置端点(受保护)
-Add permission-gated config-read endpoints:
+添加受权限门控的配置读取端点:
- `GET /api/companies/:companyId/agent-configurations`
- `GET /api/agents/:id/configuration`
-Access:
+访问权限:
- board
- CEO
-- any agent with `can_create_agents`
+- 任何拥有 `can_create_agents` 的代理
-Security:
+安全性:
-- redact obvious secret values from adapter config (`env`, API keys, tokens, JWT-looking values)
-- include redaction marker in response
+- 从适配器配置中脱敏明显的秘密值(`env`、API 密钥、令牌、看起来像 JWT 的值)
+- 在响应中包含脱敏标记
-## 5.6 Reflection endpoints for adapter configuration
+## 5.6 适配器配置反射端点
-Add plain-text reflection routes:
+添加纯文本反射路由:
- `GET /llms/agent-configuration.txt`
- `GET /llms/agent-configuration/:adapterType.txt`
-Index file includes:
+索引文件包含:
-- installed adapter list for this Paperclip instance
-- per-adapter doc URLs
-- brief "how to hire" API sequence links
+- 此 Paperclip 实例已安装的适配器列表
+- 每个适配器的文档 URL
+- 简要的"如何招聘"API 序列链接
-Per-adapter file includes:
+每个适配器文件包含:
-- required/optional config keys
-- defaults
-- field descriptions
-- safety notes
-- example payloads
+- 必需/可选配置键
+- 默认值
+- 字段描述
+- 安全注意事项
+- 示例负载
-Auth:
+认证:
-- same gate as config-read endpoints (board/CEO/`can_create_agents`).
+- 与配置读取端点相同的门控(board/CEO/`can_create_agents`)。
-## 6. Adapter Protocol Extension
+## 6. 适配器协议扩展
-Extend `ServerAdapterModule` contract to expose config docs:
+扩展 `ServerAdapterModule` 合约以暴露配置文档:
-- `agentConfigurationDoc` (string) or `getAgentConfigurationDoc()`
+- `agentConfigurationDoc`(字符串)或 `getAgentConfigurationDoc()`
-Implement in:
+在以下位置实现:
- `packages/adapters/claude-local`
- `packages/adapters/codex-local`
- `server/src/adapters/registry.ts`
-This is required so reflection is generated from installed adapters, not hardcoded.
+这是必需的,以便反射从已安装的适配器生成,而不是硬编码。
-## 7. UI Plan
+## 7. UI 计划
-## 7.1 Company advanced settings
+## 7.1 公司高级设置
-In Companies UI, add advanced settings panel/modal with:
+在公司 UI 中,添加高级设置面板/模态框,包含:
-- toggle: "Require board approval for new agent hires" (default on)
+- 开关:"新代理招聘需要 board 审批"(默认开启)
-Not shown in onboarding flow.
+不在引导流程中显示。
-## 7.2 Agent permissions UI
+## 7.2 代理权限 UI
-In Agent Detail (board/CEO context):
+在代理详情中(board/CEO 上下文):
-- permissions section
-- toggle for "Can create new agents"
+- 权限区域
+- "可以创建新代理"开关
-## 7.3 Hire UX
+## 7.3 招聘 UX
-Add "Hire Agent" flow (for CEO/authorized agents):
+添加"招聘代理"流程(用于 CEO/授权代理):
-- choose role/name/title/reportsTo
-- compose initial prompt/capabilities
-- inspect adapter reflection docs
-- inspect existing related agent configurations
-- submit hire
+- 选择角色/名称/职称/汇报对象
+- 编写初始提示/能力
+- 检查适配器反射文档
+- 检查现有相关代理配置
+- 提交招聘
-State messaging:
+状态消息:
-- if approval required: show "Pending board approval"
-- if not required: show active-ready state
+- 如果需要审批:显示"等待 board 审批"
+- 如果不需要:显示活动就绪状态
-## 7.4 Approvals UX
+## 7.4 审批 UX
-Add approval detail page and expand inbox integration:
+添加审批详情页面并扩展收件箱集成:
- `/approvals/:approvalId`
-- threaded comments
-- revision request action
-- approve/reject with decision note
-- activity timeline (created, revisions, decisions)
+- 线程化评论
+- 修订请求操作
+- 带决策备注的批准/拒绝
+- 活动时间线(创建、修订、决策)
-## 7.5 Disapproved agent cleanup
+## 7.5 不通过审批的代理清理
-Provide board-only destructive action in approval detail:
+在审批详情中提供仅限 board 的销毁操作:
-- "Delete disapproved agent"
-- explicit confirmation dialog
-- preserves approval + comment history (audit)
+- "删除未通过审批的代理"
+- 明确的确认对话框
+- 保留审批 + 评论历史(审计)
-## 8. New Skill: `paperclip-create-agent`
+## 8. 新技能:`paperclip-create-agent`
-Create new skill directory:
+创建新技能目录:
- `skills/paperclip-create-agent/SKILL.md`
- `skills/paperclip-create-agent/references/api-reference.md`
-Skill responsibilities:
+技能职责:
-- Discover available adapter configuration via `/llms/agent-configuration*.txt`
-- Read existing agent configurations (including self and related roles)
-- Propose best-fit config for current environment
-- Draft high-quality initial prompt for new agent
-- Set manager/reporting line
-- Execute hire API flow
-- Handle revision loop with board comments
+- 通过 `/llms/agent-configuration*.txt` 发现可用的适配器配置
+- 读取现有代理配置(包括自身和相关角色)
+- 为当前环境提议最佳配置
+- 为新代理草拟高质量的初始提示
+- 设置管理者/汇报关系
+- 执行招聘 API 流程
+- 处理与 board 评论的修订循环
-Also update `skills/paperclip/SKILL.md` to reference this skill for hiring workflows.
+同时更新 `skills/paperclip/SKILL.md` 以引用此技能用于招聘工作流。
-## 9. Enforcement and Invariants
+## 9. 强制规则和不变量
-New/updated invariants:
+新增/更新的不变量:
-- `pending_approval` agents cannot:
- - be invoked/woken
- - be assigned issues
- - create or use API keys
- - transition to active lifecycle states except through hire approval
-- approval transitions:
+- `pending_approval` 代理不能:
+ - 被调用/唤醒
+ - 被分配 issue
+ - 创建或使用 API 密钥
+ - 转换到活动生命周期状态(除非通过招聘审批)
+- 审批转换:
- `pending -> revision_requested | approved | rejected | cancelled`
- `revision_requested -> pending | rejected | cancelled`
-- every mutation writes `activity_log` records.
+- 每个变更写入 `activity_log` 记录。
-## 10. Implementation Phases
+## 10. 实施阶段
-## Phase 1: Contracts and migration
+## 阶段 1:合约和迁移
-- DB schema updates (`companies`, `agents`, approvals status expansion, `approval_comments`)
-- shared constants/types/validators updates
-- migration generation and typecheck
+- 数据库架构更新(`companies`、`agents`、审批状态扩展、`approval_comments`)
+- 共享常量/类型/验证器更新
+- 迁移生成和类型检查
-## Phase 2: Server authz + hire flow
+## 阶段 2:服务器授权 + 招聘流程
-- permission resolver and authz guards
-- `agent-hires` route
-- limbo status enforcement in heartbeat/issue/key flows
-- approval revision/comment endpoints
+- 权限解析器和授权守卫
+- `agent-hires` 路由
+- 在心跳/issue/密钥流程中执行待审核状态
+- 审批修订/评论端点
-## Phase 3: Reflection and config-read APIs
+## 阶段 3:反射和配置读取 API
-- adapter protocol docs support
-- `/llms/agent-configuration*.txt` routes
-- protected config-read endpoints with redaction
+- 适配器协议文档支持
+- `/llms/agent-configuration*.txt` 路由
+- 带脱敏的受保护配置读取端点
-## Phase 4: UI and skilling
+## 阶段 4:UI 和技能
-- company advanced setting UI
-- permission controls
-- approval detail + comments/revision flow in inbox/approvals
-- disapproved agent delete flow
-- `paperclip-create-agent` skill + docs updates
+- 公司高级设置 UI
+- 权限控制
+- 收件箱/审批中的审批详情 + 评论/修订流程
+- 未通过审批代理的删除流程
+- `paperclip-create-agent` 技能 + 文档更新
-## 11. Test Plan
+## 11. 测试计划
-Server tests:
+服务器测试:
-- permission gate tests for hire/config-read/permission-update endpoints
-- hire creation behavior with company setting on/off
-- approval transitions including revision cycle
-- pending_approval enforcement across wakeup/invoke/assignment/keys
-- config redaction tests
+- 招聘/配置读取/权限更新端点的权限门控测试
+- 公司设置开启/关闭时的招聘创建行为
+- 包括修订循环在内的审批转换
+- 唤醒/调用/分配/密钥中的 pending_approval 强制执行
+- 配置脱敏测试
-UI tests:
+UI 测试:
-- advanced setting toggle persistence
-- approval detail comment/revision interactions
-- hire flow states (pending vs immediate)
+- 高级设置开关持久化
+- 审批详情评论/修订交互
+- 招聘流程状态(待审核 vs 即时)
-Repo verification before merge:
+合并前仓库验证:
- `pnpm -r typecheck`
- `pnpm test:run`
- `pnpm build`
-## 12. Risks and Mitigations
+## 12. 风险和缓解措施
-- Risk: leaking secrets through agent config reads.
- - Mitigation: strict redaction pass + allowlist/denylist tests.
-- Risk: status explosion complexity.
- - Mitigation: single added status (`pending_approval`) with explicit transition guards.
-- Risk: approval flow regressions.
- - Mitigation: centralize transition logic in approval service and back it with tests.
+- 风险:通过代理配置读取泄露秘密。
+ - 缓解:严格的脱敏处理 + 允许列表/拒绝列表测试。
+- 风险:状态膨胀复杂性。
+ - 缓解:仅添加一个状态(`pending_approval`),配合明确的转换守卫。
+- 风险:审批流程回归。
+ - 缓解:在审批服务中集中转换逻辑并用测试支撑。
-## 13. Open Decisions (Default Recommendation)
+## 13. 待定决策(默认建议)
-1. Should board direct-create bypass approval setting?
-Recommendation: yes, board is explicit governance override.
+1. Board 直接创建是否应绕过审批设置?
+建议:是,board 是明确的治理覆盖。
-2. Should non-authorized agents still see basic agent metadata?
-Recommendation: yes (name/role/status), but configuration fields stay restricted.
+2. 未授权的代理是否仍应看到基本代理元数据?
+建议:是(名称/角色/状态),但配置字段保持受限。
-3. On rejection, should limbo agent remain `pending_approval` or move to `terminated`?
-Recommendation: move to `terminated` on final reject; keep optional hard delete action for cleanup.
+3. 拒绝后,待审核代理应保持 `pending_approval` 还是转为 `terminated`?
+建议:最终拒绝时转为 `terminated`;保留可选的硬删除操作用于清理。
diff --git a/doc/plans/2026-02-20-issue-run-orchestration-plan.md b/doc/plans/2026-02-20-issue-run-orchestration-plan.md
index 2d204a395b..16d2c9b301 100644
--- a/doc/plans/2026-02-20-issue-run-orchestration-plan.md
+++ b/doc/plans/2026-02-20-issue-run-orchestration-plan.md
@@ -1,141 +1,141 @@
-# Issue Run Orchestration Plan
+# Issue 运行编排计划
-## Context
+## 背景
-We observed cascaded wakeups on a single issue (for example PAP-39) that produced multiple runs at once:
+我们观察到单个 issue(例如 PAP-39)上的级联唤醒产生了多次同时运行:
-- assignee self-wake from `issue_commented`
-- mention wake to manager/CTO from `issue_comment_mentioned`
-- overlapping runs on the same issue
+- 来自 `issue_commented` 的受理人自唤醒
+- 来自 `issue_comment_mentioned` 的向管理者/CTO 的提及唤醒
+- 同一 issue 上的重叠运行
-Current behavior is run-centric and agent-centric. It coalesces per-agent+task in `heartbeat.wakeup`, but does not enforce a single active execution slot per issue across all agents.
+当前行为以运行为中心和以代理为中心。它在 `heartbeat.wakeup` 中按代理+任务进行合并,但不会在所有代理之间强制每个 issue 只有一个活动执行槽位。
-## What We Know Today
+## 当前已知情况
-- The only reliable issue/run linkage today is derived from `heartbeat_runs.context_snapshot.issueId` with run status `queued` or `running`.
-- `checkoutRunId` on issues is a work-ownership lock, not an orchestration lock.
-- Wakeups are created from multiple routes (`issues`, `approvals`, `agents`) and all funnel through `heartbeat.wakeup`.
+- 目前唯一可靠的 issue/运行关联是从 `heartbeat_runs.context_snapshot.issueId` 中派生的,运行状态为 `queued` 或 `running`。
+- issue 上的 `checkoutRunId` 是工作所有权锁,不是编排锁。
+- 唤醒从多个路由创建(`issues`、`approvals`、`agents`),全部通过 `heartbeat.wakeup` 汇集。
-## Goals
+## 目标
-1. Prevent self-wake cascades for the same issue when the target agent has the same normalized name as the currently active issue runner.
-2. Allow cross-agent wake requests, but do not run them until the current issue runner exits.
-3. Guarantee at most one active (queued or running) execution owner per issue at a time.
-4. Keep this enforcement centralized in orchestration (not prompt/skill rules).
+1. 当目标代理与当前活动 issue 运行者具有相同的规范化名称时,防止同一 issue 的自唤醒级联。
+2. 允许跨代理唤醒请求,但在当前 issue 运行者退出之前不执行。
+3. 保证每个 issue 同时最多只有一个活动(排队或运行中的)执行所有者。
+4. 将此强制执行集中在编排中(而非提示/技能规则中)。
-## Non-Goals
+## 非目标
-- Replacing checkout semantics for code-change ownership.
-- Changing manager escalation policy itself.
-- Enforcing uniqueness of agent names globally (handled as a separate governance decision).
+- 替换代码变更所有权的检出语义。
+- 改变管理者升级策略本身。
+- 全局强制代理名称唯一性(作为单独的治理决策处理)。
-## Proposed Model
+## 提议的模型
-Use an explicit issue-level orchestration lock on `issues`.
+在 `issues` 上使用显式的 issue 级别编排锁。
-### New Issue Properties
+### 新的 Issue 属性
-- `executionRunId: uuid | null` (FK to `heartbeat_runs.id`, `ON DELETE SET NULL`)
-- `executionAgentNameKey: text | null` (normalized lowercase/trimmed agent name)
+- `executionRunId: uuid | null`(FK 到 `heartbeat_runs.id`,`ON DELETE SET NULL`)
+- `executionAgentNameKey: text | null`(规范化的小写/去空格代理名称)
- `executionLockedAt: timestamptz | null`
-`executionRunId` is the canonical “who currently owns orchestration for this issue” field.
+`executionRunId` 是"谁当前拥有此 issue 的编排权"的规范字段。
-## Orchestration Rules
+## 编排规则
-### Rule A: No Self-Wake by Same Agent Name
+### 规则 A:同一代理名称不自唤醒
-If a wakeup is issue-scoped and `issues.executionRunId` points to an active run whose `executionAgentNameKey` matches the waking agent name key:
+如果唤醒是 issue 范围的,且 `issues.executionRunId` 指向一个活动运行,其 `executionAgentNameKey` 与唤醒代理名称键匹配:
-- do not create a new heartbeat run
-- write wakeup request as `coalesced` with reason `issue_execution_same_name`
-- return existing run reference
+- 不创建新的心跳运行
+- 将唤醒请求写为 `coalesced`,原因为 `issue_execution_same_name`
+- 返回现有运行引用
-### Rule B: Different Name May Wake, But Waits
+### 规则 B:不同名称可以唤醒,但需等待
-If an issue has an active execution lock held by a different agent-name key:
+如果 issue 有一个由不同代理名称键持有的活动执行锁:
-- accept the wake request
-- persist request as deferred (new wakeup status `deferred_issue_execution`)
-- do not create a run yet
+- 接受唤醒请求
+- 将请求持久化为延迟(新唤醒状态 `deferred_issue_execution`)
+- 暂不创建运行
-When the active issue run finishes, promote the oldest deferred request for that issue into a queued run and transfer `executionRunId`.
+当活动 issue 运行完成时,将该 issue 最早的延迟请求提升为排队运行并转移 `executionRunId`。
-### Rule C: One Active Execution Owner Per Issue
+### 规则 C:每个 Issue 一个活动执行所有者
-For issue-scoped wakeups, run creation is done only while holding a transaction lock on the issue row. This ensures only one queued/running run can become owner at a time.
+对于 issue 范围的唤醒,运行创建仅在持有 issue 行的事务锁时进行。这确保同时只有一个排队/运行中的运行可以成为所有者。
-## Implementation Plan
+## 实施计划
-## Phase 1: Schema + Shared Contracts
+## 阶段 1:架构 + 共享合约
-1. Add issue columns: `execution_run_id`, `execution_agent_name_key`, `execution_locked_at`.
-2. Extend shared `Issue` type in `packages/shared/src/types/issue.ts`.
-3. Add migration and export updates.
+1. 添加 issue 列:`execution_run_id`、`execution_agent_name_key`、`execution_locked_at`。
+2. 扩展 `packages/shared/src/types/issue.ts` 中的共享 `Issue` 类型。
+3. 添加迁移和导出更新。
-## Phase 2: Centralize Issue Execution Gate in `heartbeat.wakeup`
+## 阶段 2:在 `heartbeat.wakeup` 中集中 Issue 执行门控
-1. In `enqueueWakeup`, derive `issueId` from context/payload as today.
-2. If no `issueId`, keep existing behavior.
-3. If `issueId` exists:
- - transaction + `SELECT ... FOR UPDATE` on issue row
- - resolve/repair stale `executionRunId` (if referenced run is not `queued|running`, clear lock)
- - apply Rule A/Rule B/Rule C
-4. Name normalization helper:
+1. 在 `enqueueWakeup` 中,像今天一样从上下文/负载派生 `issueId`。
+2. 如果没有 `issueId`,保持现有行为。
+3. 如果 `issueId` 存在:
+ - 事务 + `SELECT ... FOR UPDATE` 对 issue 行加锁
+ - 解析/修复过时的 `executionRunId`(如果引用的运行不是 `queued|running`,清除锁)
+ - 应用规则 A/规则 B/规则 C
+4. 名称规范化辅助函数:
- `agentNameKey = agent.name.trim().toLowerCase()`
-## Phase 3: Deferred Queue Promotion on Run Finalization
+## 阶段 3:运行完成时的延迟队列提升
-1. On run terminal states (`succeeded`, `failed`, `cancelled`, orphan reaped):
- - if run owns `issues.executionRunId`, clear issue lock
- - promote oldest deferred issue wakeup to queued run
- - set issue lock to the promoted run
- - trigger `startNextQueuedRunForAgent(promotedAgentId)`
+1. 在运行终态(`succeeded`、`failed`、`cancelled`、孤儿回收)时:
+ - 如果运行拥有 `issues.executionRunId`,清除 issue 锁
+ - 提升该 issue 最早的延迟唤醒为排队运行
+ - 将 issue 锁设置为提升的运行
+ - 触发 `startNextQueuedRunForAgent(promotedAgentId)`
-## Phase 4: Route Hygiene (“Apply Everywhere”)
+## 阶段 4:路由清理("全面应用")
-1. Keep route-side wakeup dedupe by agent id, but rely on heartbeat gate as source of truth.
-2. Ensure all issue-related wakeup calls include `issueId` in payload/context snapshot.
-3. Add explicit reason codes so logs make suppression/deferral obvious.
+1. 保持路由端按代理 ID 的唤醒去重,但以心跳门控作为事实来源。
+2. 确保所有 issue 相关的唤醒调用在负载/上下文快照中包含 `issueId`。
+3. 添加明确的原因代码,使日志中的抑制/延迟清晰可见。
-## Phase 5: Tests
+## 阶段 5:测试
-1. Unit tests for `heartbeat.wakeup`:
- - same-name self-wake suppressed
- - different-name wake deferred
- - lock released and deferred wake promoted on owner completion
- - stale lock recovery
-2. Integration tests:
- - comment with `@CTO` during active assignee run does not create concurrent active run
- - only one active owner per issue at any time
-3. Regression tests:
- - non-issue wakeups unchanged
- - existing assignment/timer behavior unchanged for tasks without issue context
+1. `heartbeat.wakeup` 的单元测试:
+ - 同名自唤醒被抑制
+ - 不同名唤醒被延迟
+ - 所有者完成时锁释放并提升延迟唤醒
+ - 过时锁恢复
+2. 集成测试:
+ - 在活动受理人运行期间带 `@CTO` 的评论不会创建并发活动运行
+ - 任何时候每个 issue 只有一个活动所有者
+3. 回归测试:
+ - 非 issue 唤醒不受影响
+ - 现有的分配/计时器行为对于没有 issue 上下文的任务不受影响
-## Telemetry + Debuggability
+## 遥测 + 可调试性
-- Add structured reasons in `agent_wakeup_requests.reason`:
+- 在 `agent_wakeup_requests.reason` 中添加结构化原因:
- `issue_execution_same_name`
- `issue_execution_deferred`
- `issue_execution_promoted`
-- Add activity log details for lock transfer events:
- - from run id / to run id / issue id / agent name key
+- 为锁转移事件添加活动日志详情:
+ - 来源运行 ID / 目标运行 ID / issue ID / 代理名称键
-## Rollout Strategy
+## 发布策略
-1. Ship schema + feature flag (`ISSUE_EXECUTION_LOCK_ENABLED`) default off.
-2. Enable in dev and verify PAP-39 style scenarios.
-3. Enable in staging with high log verbosity.
-4. Enable by default after stable run.
+1. 发布架构 + 功能标志(`ISSUE_EXECUTION_LOCK_ENABLED`),默认关闭。
+2. 在开发环境中启用并验证 PAP-39 类型的场景。
+3. 在预发布环境中启用,提高日志详细程度。
+4. 稳定运行后默认启用。
-## Acceptance Criteria
+## 验收标准
-1. A single issue never has more than one active execution owner run (`queued|running`) at once.
-2. Same-name self-wakes for the same issue are suppressed, not spawned.
-3. Different-name wakeups are accepted but deferred until issue execution lock is released.
-4. Mentioning CTO during an active issue run does not start CTO concurrently on that issue.
-5. Parallelism remains available via separate issues/subissues.
+1. 单个 issue 同时不会有超过一个活动执行所有者运行(`queued|running`)。
+2. 同一 issue 的同名自唤醒被抑制,不会生成新运行。
+3. 不同名唤醒被接受但延迟,直到 issue 执行锁释放。
+4. 在活动 issue 运行期间提及 CTO 不会在该 issue 上同时启动 CTO。
+5. 通过不同的 issue/子 issue 仍可实现并行。
-## Follow-Up (Separate but Related)
+## 后续工作(独立但相关)
-Checkout conflict logic should be corrected independently so assignees with `checkoutRunId = null` can acquire checkout by current run id without false 409 loops.
+检出冲突逻辑应独立修正,使 `checkoutRunId = null` 的受理人可以通过当前运行 ID 获取检出,而不会产生虚假的 409 循环。
diff --git a/doc/plans/2026-02-20-storage-system-implementation.md b/doc/plans/2026-02-20-storage-system-implementation.md
index d4b9c2fd0d..d875b1908e 100644
--- a/doc/plans/2026-02-20-storage-system-implementation.md
+++ b/doc/plans/2026-02-20-storage-system-implementation.md
@@ -1,192 +1,192 @@
-# Storage System Implementation Plan (V1)
+# 存储系统实施计划(V1)
-Status: Draft
-Owner: Backend + UI
-Date: 2026-02-20
+状态:草案
+负责人:后端 + UI
+日期:2026-02-20
-## Goal
+## 目标
-Add a single storage subsystem for Paperclip that supports:
+为 Paperclip 添加统一的存储子系统,支持:
-- local disk storage for single-user local deployment
-- S3-compatible object storage for cloud deployment
-- a provider-agnostic interface for issue images and future file attachments
+- 单用户本地部署的本地磁盘存储
+- 云部署的 S3 兼容对象存储
+- 用于 issue 图片和未来文件附件的存储提供商无关接口
-## V1 Scope
+## V1 范围
-- First consumer: issue attachments/images.
-- Storage adapters: `local_disk` and `s3`.
-- Files are always company-scoped and access-controlled.
-- API serves attachment bytes through authenticated Paperclip endpoints.
+- 首个消费者:issue 附件/图片。
+- 存储适配器:`local_disk` 和 `s3`。
+- 文件始终以公司为范围并有访问控制。
+- API 通过经过认证的 Paperclip 端点提供附件字节。
-## Out of Scope (This Draft)
+## 范围外(本草案)
-- Public unauthenticated object URLs.
-- CDN/signed URL optimization.
-- Image transformations/thumbnails.
-- Malware scanning pipeline.
+- 公开的未认证对象 URL。
+- CDN/签名 URL 优化。
+- 图片转换/缩略图。
+- 恶意软件扫描流水线。
-## Key Decisions
+## 关键决策
-- Default local path is under instance root: `~/.paperclip/instances//data/storage`.
-- Object bytes live in storage provider; metadata lives in Postgres.
-- `assets` is generic metadata table; `issue_attachments` links assets to issues/comments.
-- S3 credentials come from runtime environment/default AWS provider chain, not DB rows.
-- All object keys include company prefix to preserve hard tenancy boundaries.
+- 默认本地路径位于实例根目录下:`~/.paperclip/instances//data/storage`。
+- 对象字节存储在存储提供商中;元数据存储在 Postgres 中。
+- `assets` 是通用元数据表;`issue_attachments` 将资产链接到 issue/评论。
+- S3 凭据来自运行时环境/默认 AWS 提供商链,不是数据库行。
+- 所有对象键包含公司前缀以保持严格的租户边界。
-## Phase 1: Shared Config + Provider Contract
+## 阶段 1:共享配置 + 提供商合约
-### Checklist (Per File)
+### 检查清单(按文件)
-- [ ] `packages/shared/src/constants.ts`: add `STORAGE_PROVIDERS` and `StorageProvider` type.
-- [ ] `packages/shared/src/config-schema.ts`: add `storageConfigSchema` with:
+- [ ] `packages/shared/src/constants.ts`:添加 `STORAGE_PROVIDERS` 和 `StorageProvider` 类型。
+- [ ] `packages/shared/src/config-schema.ts`:添加 `storageConfigSchema`,包含:
- provider: `local_disk | s3`
- localDisk.baseDir
- - s3.bucket, s3.region, s3.endpoint?, s3.prefix?, s3.forcePathStyle?
-- [ ] `packages/shared/src/index.ts`: export new storage config/types.
-- [ ] `cli/src/config/schema.ts`: ensure re-export includes new storage schema/types.
-- [ ] `cli/src/commands/configure.ts`: add `storage` section support.
-- [ ] `cli/src/commands/onboard.ts`: initialize default storage config.
-- [ ] `cli/src/prompts/storage.ts`: new prompt flow for local disk vs s3 settings.
-- [ ] `cli/src/prompts/index` (if present) or direct imports: wire new storage prompt.
-- [ ] `server/src/config.ts`: load storage config and resolve home-aware local path.
-- [ ] `server/src/home-paths.ts`: add `resolveDefaultStorageDir()`.
-- [ ] `doc/CLI.md`: document `configure --section storage`.
-- [ ] `doc/DEVELOPING.md`: document default local storage path and overrides.
+ - s3.bucket、s3.region、s3.endpoint?、s3.prefix?、s3.forcePathStyle?
+- [ ] `packages/shared/src/index.ts`:导出新的存储配置/类型。
+- [ ] `cli/src/config/schema.ts`:确保重新导出包含新的存储架构/类型。
+- [ ] `cli/src/commands/configure.ts`:添加 `storage` 部分支持。
+- [ ] `cli/src/commands/onboard.ts`:初始化默认存储配置。
+- [ ] `cli/src/prompts/storage.ts`:新的本地磁盘 vs S3 设置提示流程。
+- [ ] `cli/src/prompts/index`(如存在)或直接导入:连接新的存储提示。
+- [ ] `server/src/config.ts`:加载存储配置并解析带主目录感知的本地路径。
+- [ ] `server/src/home-paths.ts`:添加 `resolveDefaultStorageDir()`。
+- [ ] `doc/CLI.md`:记录 `configure --section storage`。
+- [ ] `doc/DEVELOPING.md`:记录默认本地存储路径和覆盖方式。
-### Acceptance Criteria
+### 验收标准
-- `paperclipai onboard` writes a valid `storage` config block by default.
-- `paperclipai configure --section storage` can switch between local and s3 modes.
-- Server startup reads storage config without env-only hacks.
+- `paperclipai onboard` 默认写入有效的 `storage` 配置块。
+- `paperclipai configure --section storage` 可以在本地和 S3 模式之间切换。
+- 服务器启动时读取存储配置,无需仅依赖环境变量的技巧。
-## Phase 2: Server Storage Subsystem + Providers
+## 阶段 2:服务器存储子系统 + 提供商
-### Checklist (Per File)
+### 检查清单(按文件)
-- [ ] `server/src/storage/types.ts`: define provider + service interfaces.
-- [ ] `server/src/storage/service.ts`: provider-agnostic service (key generation, validation, stream APIs).
-- [ ] `server/src/storage/local-disk-provider.ts`: implement local disk provider with safe path resolution.
-- [ ] `server/src/storage/s3-provider.ts`: implement S3-compatible provider (`@aws-sdk/client-s3`).
-- [ ] `server/src/storage/provider-registry.ts`: provider lookup by configured id.
-- [ ] `server/src/storage/index.ts`: export storage factory helpers.
-- [ ] `server/src/services/index.ts`: export `storageService` factory.
-- [ ] `server/src/app.ts` or route wiring point: inject/use storage service where needed.
-- [ ] `server/package.json`: add AWS SDK dependency if not present.
+- [ ] `server/src/storage/types.ts`:定义提供商 + 服务接口。
+- [ ] `server/src/storage/service.ts`:提供商无关的服务(键生成、验证、流 API)。
+- [ ] `server/src/storage/local-disk-provider.ts`:实现带安全路径解析的本地磁盘提供商。
+- [ ] `server/src/storage/s3-provider.ts`:实现 S3 兼容提供商(`@aws-sdk/client-s3`)。
+- [ ] `server/src/storage/provider-registry.ts`:按配置 ID 查找提供商。
+- [ ] `server/src/storage/index.ts`:导出存储工厂辅助函数。
+- [ ] `server/src/services/index.ts`:导出 `storageService` 工厂。
+- [ ] `server/src/app.ts` 或路由连接点:在需要的地方注入/使用存储服务。
+- [ ] `server/package.json`:如未安装,添加 AWS SDK 依赖。
-### Acceptance Criteria
+### 验收标准
-- In `local_disk` mode, uploading + reading a file round-trips bytes on disk.
-- In `s3` mode, service can `put/get/delete` against S3-compatible endpoint.
-- Invalid provider config yields clear startup/config errors.
+- 在 `local_disk` 模式下,上传 + 读取文件可以在磁盘上完成字节往返。
+- 在 `s3` 模式下,服务可以针对 S3 兼容端点执行 `put/get/delete`。
+- 无效的提供商配置会产生清晰的启动/配置错误。
-## Phase 3: Database Metadata Model
+## 阶段 3:数据库元数据模型
-### Checklist (Per File)
+### 检查清单(按文件)
-- [ ] `packages/db/src/schema/assets.ts`: new generic asset metadata table.
-- [ ] `packages/db/src/schema/issue_attachments.ts`: issue-to-asset linking table.
-- [ ] `packages/db/src/schema/index.ts`: export new tables.
-- [ ] `packages/db/src/migrations/*`: generate migration for both tables and indexes.
-- [ ] `packages/shared/src/types/issue.ts` (or new asset types file): add `IssueAttachment` type.
-- [ ] `packages/shared/src/index.ts`: export new types.
+- [ ] `packages/db/src/schema/assets.ts`:新的通用资产元数据表。
+- [ ] `packages/db/src/schema/issue_attachments.ts`:issue 到资产的关联表。
+- [ ] `packages/db/src/schema/index.ts`:导出新表。
+- [ ] `packages/db/src/migrations/*`:为两个表和索引生成迁移。
+- [ ] `packages/shared/src/types/issue.ts`(或新的资产类型文件):添加 `IssueAttachment` 类型。
+- [ ] `packages/shared/src/index.ts`:导出新类型。
-### Suggested Columns
+### 建议列
-- `assets`:
- - `id`, `company_id`, `provider`, `object_key`
- - `content_type`, `byte_size`, `sha256`, `original_filename`
- - `created_by_agent_id`, `created_by_user_id`, timestamps
-- `issue_attachments`:
- - `id`, `company_id`, `issue_id`, `asset_id`, `issue_comment_id` (nullable), timestamps
+- `assets`:
+ - `id`、`company_id`、`provider`、`object_key`
+ - `content_type`、`byte_size`、`sha256`、`original_filename`
+ - `created_by_agent_id`、`created_by_user_id`、时间戳
+- `issue_attachments`:
+ - `id`、`company_id`、`issue_id`、`asset_id`、`issue_comment_id`(可空)、时间戳
-### Acceptance Criteria
+### 验收标准
-- Migration applies cleanly on empty and existing local dev DB.
-- Metadata rows are company-scoped and indexed for issue lookup.
+- 迁移在空数据库和现有本地开发数据库上均可干净地应用。
+- 元数据行以公司为范围,并为 issue 查找建立索引。
-## Phase 4: Issue Attachment API
+## 阶段 4:Issue 附件 API
-### Checklist (Per File)
+### 检查清单(按文件)
-- [ ] `packages/shared/src/validators/issue.ts`: add schemas for upload/list/delete attachment operations.
-- [ ] `server/src/services/issues.ts`: add attachment CRUD helpers with company checks.
-- [ ] `server/src/routes/issues.ts`: add endpoints:
- - `POST /companies/:companyId/issues/:issueId/attachments` (multipart)
+- [ ] `packages/shared/src/validators/issue.ts`:为上传/列表/删除附件操作添加 schema。
+- [ ] `server/src/services/issues.ts`:添加带公司检查的附件 CRUD 辅助函数。
+- [ ] `server/src/routes/issues.ts`:添加端点:
+ - `POST /companies/:companyId/issues/:issueId/attachments`(multipart)
- `GET /issues/:issueId/attachments`
- `GET /attachments/:attachmentId/content`
- `DELETE /attachments/:attachmentId`
-- [ ] `server/src/routes/authz.ts`: reuse/enforce company access for attachment endpoints.
-- [ ] `server/src/services/activity-log.ts` usage callsites: log attachment add/remove mutations.
-- [ ] `server/src/app.ts`: ensure multipart parsing middleware is in place for upload route.
+- [ ] `server/src/routes/authz.ts`:复用/强制执行附件端点的公司访问。
+- [ ] `server/src/services/activity-log.ts` 使用调用点:记录附件添加/删除变更。
+- [ ] `server/src/app.ts`:确保上传路由有 multipart 解析中间件。
-### API Behavior
+### API 行为
-- Enforce max size and image/content-type allowlist in V1.
-- Return consistent errors: `400/401/403/404/409/422/500`.
-- Stream bytes instead of buffering large payloads in memory.
+- V1 中强制最大大小和图片/内容类型白名单。
+- 返回一致的错误:`400/401/403/404/409/422/500`。
+- 流式传输字节而非在内存中缓冲大负载。
-### Acceptance Criteria
+### 验收标准
-- Board and same-company agents can upload and read attachments per issue permissions.
-- Cross-company access is denied even with valid attachment id.
-- Activity log records attachment add/remove actions.
+- Board 和同公司代理可以按 issue 权限上传和读取附件。
+- 即使有有效的附件 ID,跨公司访问也被拒绝。
+- 活动日志记录附件添加/删除操作。
-## Phase 5: UI Issue Attachment Integration
+## 阶段 5:UI Issue 附件集成
-### Checklist (Per File)
+### 检查清单(按文件)
-- [ ] `ui/src/api/issues.ts`: add attachment API client methods.
-- [ ] `ui/src/api/client.ts`: support multipart upload helper (no JSON `Content-Type` for `FormData`).
-- [ ] `ui/src/lib/queryKeys.ts`: add issue attachment query keys.
-- [ ] `ui/src/pages/IssueDetail.tsx`: add upload UI + attachment list/query invalidation.
-- [ ] `ui/src/components/CommentThread.tsx`: optional comment image attach or display linked images.
-- [ ] `packages/shared/src/types/index.ts`: ensure attachment types are consumed cleanly in UI.
+- [ ] `ui/src/api/issues.ts`:添加附件 API 客户端方法。
+- [ ] `ui/src/api/client.ts`:支持 multipart 上传辅助函数(`FormData` 不使用 JSON `Content-Type`)。
+- [ ] `ui/src/lib/queryKeys.ts`:添加 issue 附件查询键。
+- [ ] `ui/src/pages/IssueDetail.tsx`:添加上传 UI + 附件列表/查询失效。
+- [ ] `ui/src/components/CommentThread.tsx`:可选的评论图片附加或显示关联图片。
+- [ ] `packages/shared/src/types/index.ts`:确保附件类型在 UI 中被干净地消费。
-### Acceptance Criteria
+### 验收标准
-- User can upload an image from issue detail and see it listed immediately.
-- Uploaded image can be opened/rendered via authenticated API route.
-- Upload and fetch failures are visible to users (no silent errors).
+- 用户可以从 issue 详情上传图片并立即看到列表。
+- 上传的图片可以通过经过认证的 API 路由打开/渲染。
+- 上传和获取失败对用户可见(无静默错误)。
-## Phase 6: CLI Doctor + Operational Hardening
+## 阶段 6:CLI 诊断 + 运维加固
-### Checklist (Per File)
+### 检查清单(按文件)
-- [ ] `cli/src/checks/storage-check.ts`: add storage check (local writable dir, optional S3 reachability check).
-- [ ] `cli/src/checks/index.ts`: export new storage check.
-- [ ] `cli/src/commands/doctor.ts`: include storage check in doctor sequence.
-- [ ] `doc/DATABASE.md` or `doc/DEVELOPING.md`: mention storage backend behavior by deployment mode.
-- [ ] `doc/SPEC-implementation.md`: add storage subsystem and issue-attachment endpoint contract.
+- [ ] `cli/src/checks/storage-check.ts`:添加存储检查(本地可写目录、可选的 S3 可达性检查)。
+- [ ] `cli/src/checks/index.ts`:导出新的存储检查。
+- [ ] `cli/src/commands/doctor.ts`:在诊断序列中包含存储检查。
+- [ ] `doc/DATABASE.md` 或 `doc/DEVELOPING.md`:说明按部署模式的存储后端行为。
+- [ ] `doc/SPEC-implementation.md`:添加存储子系统和 issue 附件端点合约。
-### Acceptance Criteria
+### 验收标准
-- `paperclipai doctor` reports actionable storage status.
-- Local single-user install works without extra cloud credentials.
-- Cloud config supports S3-compatible endpoint without code changes.
+- `paperclipai doctor` 报告可操作的存储状态。
+- 本地单用户安装无需额外的云凭据即可工作。
+- 云配置支持 S3 兼容端点,无需代码更改。
-## Test Plan
+## 测试计划
-### Server Integration Tests
+### 服务器集成测试
-- [ ] `server/src/__tests__/issue-attachments.auth.test.ts`: company boundary and permission tests.
-- [ ] `server/src/__tests__/issue-attachments.lifecycle.test.ts`: upload/list/read/delete flow.
-- [ ] `server/src/__tests__/storage-local-provider.test.ts`: local provider path safety and round-trip.
-- [ ] `server/src/__tests__/storage-s3-provider.test.ts`: s3 provider contract (mocked client).
-- [ ] `server/src/__tests__/activity-log.attachments.test.ts`: mutation logging assertions.
+- [ ] `server/src/__tests__/issue-attachments.auth.test.ts`:公司边界和权限测试。
+- [ ] `server/src/__tests__/issue-attachments.lifecycle.test.ts`:上传/列表/读取/删除流程。
+- [ ] `server/src/__tests__/storage-local-provider.test.ts`:本地提供商路径安全和往返。
+- [ ] `server/src/__tests__/storage-s3-provider.test.ts`:S3 提供商合约(模拟客户端)。
+- [ ] `server/src/__tests__/activity-log.attachments.test.ts`:变更日志断言。
-### CLI Tests
+### CLI 测试
-- [ ] `cli/src/__tests__/configure-storage.test.ts`: configure section writes valid config.
-- [ ] `cli/src/__tests__/doctor-storage-check.test.ts`: storage health output and repair behavior.
+- [ ] `cli/src/__tests__/configure-storage.test.ts`:配置部分写入有效配置。
+- [ ] `cli/src/__tests__/doctor-storage-check.test.ts`:存储健康输出和修复行为。
-### UI Tests (if present in current stack)
+### UI 测试(如当前技术栈中存在)
-- [ ] `ui/src/...`: issue detail upload and error handling tests.
+- [ ] `ui/src/...`:issue 详情上传和错误处理测试。
-## Verification Gate Before Merge
+## 合并前验证关卡
-Run:
+运行:
```sh
pnpm -r typecheck
@@ -194,13 +194,12 @@ pnpm test:run
pnpm build
```
-If any command is skipped, document exactly what was skipped and why.
+如果跳过了任何命令,需准确记录跳过了什么以及原因。
-## Implementation Order
-
-1. Phase 1 and Phase 2 (foundation, no user-visible breakage)
-2. Phase 3 (DB contract)
-3. Phase 4 (API)
-4. Phase 5 (UI consumer)
-5. Phase 6 (doctor/docs hardening)
+## 实施顺序
+1. 阶段 1 和阶段 2(基础,不会造成用户可见的破坏)
+2. 阶段 3(数据库合约)
+3. 阶段 4(API)
+4. 阶段 5(UI 消费者)
+5. 阶段 6(诊断/文档加固)
diff --git a/doc/plans/2026-02-21-humans-and-permissions-implementation.md b/doc/plans/2026-02-21-humans-and-permissions-implementation.md
index 9de5947fb3..5bc66499e9 100644
--- a/doc/plans/2026-02-21-humans-and-permissions-implementation.md
+++ b/doc/plans/2026-02-21-humans-and-permissions-implementation.md
@@ -1,76 +1,76 @@
-# Humans and Permissions Implementation (V1)
+# 人类用户与权限实现方案(V1)
-Status: Draft
-Date: 2026-02-21
-Owners: Server + UI + CLI + DB + Shared
-Companion plan: `doc/plan/humans-and-permissions.md`
+状态:草稿
+日期:2026-02-21
+负责人:Server + UI + CLI + DB + Shared
+配套方案:`doc/plan/humans-and-permissions.md`
-## 1. Document role
+## 1. 文档职责
-This document is the engineering implementation contract for the humans-and-permissions plan.
-It translates product decisions into concrete schema, API, middleware, UI, CLI, and test work.
+本文档是人类用户与权限方案的工程实现合同。
+它将产品决策转化为具体的 schema、API、中间件、UI、CLI 和测试工作。
-If this document conflicts with prior exploratory notes, this document wins for V1 execution.
+如本文档与早期探索性笔记存在冲突,以本文档为准执行 V1。
-## 2. Locked V1 decisions
+## 2. V1 锁定决策
-1. Two deployment modes remain:
+1. 保留两种部署模式:
- `local_trusted`
- `cloud_hosted`
-2. `local_trusted`:
-- no login UX
-- implicit local instance admin actor
-- loopback-only server binding
-- full admin/settings/invite/approval capabilities available locally
-
-3. `cloud_hosted`:
-- Better Auth for humans
-- email/password only
-- no email verification requirement in V1
-
-4. Permissions:
-- one shared authorization system for humans and agents
-- normalized grants table (`principal_permission_grants`)
-- no separate “agent permissions engine”
-
-5. Invites:
-- copy-link only (no outbound email sending in V1)
-- unified `company_join` link that supports human or agent path
-- acceptance creates `pending_approval` join request
-- no access until admin approval
-
-6. Join review metadata:
-- source IP required
-- no GeoIP/country lookup in V1
-
-7. Agent API keys:
-- indefinite by default
-- hash at rest
-- display once on claim
-- revoke/regenerate supported
-
-8. Local ingress:
-- public/untrusted ingress is out of scope for V1
-- no `--dangerous-agent-ingress` in V1
-
-## 3. Current baseline and delta
-
-Current baseline (repo as of this doc):
-
-- server actor model defaults to `board` in `server/src/middleware/auth.ts`
-- authorization is mostly `assertBoard` + company check in `server/src/routes/authz.ts`
-- no human auth/session tables in local schema
-- no principal membership or grants tables
-- no invite or join-request lifecycle
-
-Required delta:
-
-- move from board-vs-agent authz to principal-based authz
-- add Better Auth integration in cloud mode
-- add membership/grants/invite/join-request persistence
-- add approval inbox signals and actions
-- preserve local no-login UX without weakening cloud security
+2. `local_trusted`:
+- 无登录 UI
+- 隐式本地实例管理员角色
+- 仅绑定回环地址
+- 本地可使用完整的管理/设置/邀请/审批功能
+
+3. `cloud_hosted`:
+- 人类用户使用 Better Auth
+- 仅支持邮箱/密码登录
+- V1 不要求邮箱验证
+
+4. 权限:
+- 人类与智能体共用同一套授权系统
+- 规范化授权表(`principal_permission_grants`)
+- 不单独设立”智能体权限引擎”
+
+5. 邀请:
+- 仅复制链接(V1 不发送外部邮件)
+- 统一的 `company_join` 链接,同时支持人类或智能体路径
+- 接受后创建 `pending_approval` 加入请求
+- 管理员审批前不授予任何访问权限
+
+6. 加入审核元数据:
+- 必须记录来源 IP
+- V1 不进行 GeoIP/国家查询
+
+7. 智能体 API 密钥:
+- 默认永久有效
+- 哈希存储
+- 领取时仅显示一次明文
+- 支持吊销/重新生成
+
+8. 本地入口:
+- V1 不支持公共/不受信任的入口
+- V1 不实现 `--dangerous-agent-ingress`
+
+## 3. 当前基准与变更增量
+
+当前基准(截至本文档的代码库状态):
+
+- 服务器角色模型在 `server/src/middleware/auth.ts` 中默认为 `board`
+- 授权主要依赖 `server/src/routes/authz.ts` 中的 `assertBoard` + 公司检查
+- 本地 schema 中无人类身份验证/会话表
+- 无主体成员资格或授权表
+- 无邀请或加入请求生命周期
+
+所需变更:
+
+- 从 board-vs-agent 授权迁移至基于主体的授权
+- 在云模式中集成 Better Auth
+- 添加成员资格/授权/邀请/加入请求的持久化
+- 添加审批收件箱信号与操作
+- 在不削弱云端安全性的前提下保留本地无登录体验
## 4. Architecture
diff --git a/doc/plans/2026-02-21-humans-and-permissions.md b/doc/plans/2026-02-21-humans-and-permissions.md
index a64c583b9f..086a096cf6 100644
--- a/doc/plans/2026-02-21-humans-and-permissions.md
+++ b/doc/plans/2026-02-21-humans-and-permissions.md
@@ -1,177 +1,177 @@
-# Humans and Permissions Plan
+# 人类用户与权限方案
-Status: Draft
-Date: 2026-02-21
-Owner: Server + UI + Shared + DB
+状态:草稿
+日期:2026-02-21
+负责人:Server + UI + Shared + DB
-## Goal
+## 目标
-Add first-class human users and permissions while preserving two deployment modes:
+在保留两种部署模式的同时,添加一流的人类用户支持和权限体系:
-- local trusted single-user mode with no login friction
-- cloud-hosted multi-user mode with mandatory authentication and authorization
+- 无登录摩擦的本地受信单用户模式
+- 强制身份验证和授权的云托管多用户模式
-## Why this plan
+## 为什么需要此方案
-Current V1 assumptions are centered on one board operator. We now need:
+当前 V1 假设以单一看板操作员为中心。我们现在需要:
-- multi-human collaboration with per-user permissions
-- safe cloud deployment defaults (no accidental loginless production)
-- local mode that still feels instant (`npx paperclipai run` and go)
-- agent-to-human task delegation, including a human inbox
-- one user account with access to multiple companies in one deployment
-- instance admins who can manage company access across the instance
-- join approvals surfaced as actionable inbox alerts, not buried in admin-only pages
-- a symmetric invite-and-approve onboarding path for both humans and agents
-- one shared membership and permission model for both humans and agents
+- 支持按用户权限的多人协作
+- 安全的云部署默认值(避免意外上线无登录的生产环境)
+- 本地模式仍保持即时体验(`npx paperclipai run` 即可使用)
+- 智能体向人类委派任务,包括人类收件箱
+- 一个用户账户可在同一部署中访问多家公司
+- 实例管理员可跨实例管理公司访问权限
+- 加入审批以可操作收件箱提醒的形式呈现,而非埋在仅管理员可见的页面
+- 人类与智能体均采用对称的邀请-审批入职路径
+- 人类与智能体共用同一套成员资格与权限模型
-## Product constraints
+## 产品约束
-1. Keep company scoping strict for every new table, endpoint, and permission check.
-2. Preserve existing control-plane invariants:
+1. 对每个新表、端点和权限检查严格保持公司作用域隔离。
+2. 保留现有控制平面不变量:
-- single-assignee task model
-- approval gates
-- budget hard-stop behavior
-- mutation activity logging
+- 单一受托人任务模型
+- 审批关卡
+- 预算硬停止行为
+- 变更操作日志记录
-3. Keep local mode easy and trusted, but prevent unsafe cloud posture.
+3. 保持本地模式简便可信,但防止不安全的云姿态。
-## Deployment modes
+## 部署模式
-## Mode A: `local_trusted`
+## 模式 A:`local_trusted`
-Behavior:
+行为:
-- no login UI
-- browser opens directly into board context
-- embedded DB and local storage defaults remain
-- a local implicit human actor exists for attribution
-- local implicit actor has effective `instance_admin` authority for that instance
-- full invite/approval/permission settings flows remain available in local mode (including agent enrollment)
+- 无登录 UI
+- 浏览器直接进入看板上下文
+- 保持嵌入式数据库和本地存储默认值
+- 存在本地隐式人类角色用于归因
+- 本地隐式角色对该实例具有有效的 `instance_admin` 权限
+- 本地模式下完整的邀请/审批/权限设置流程仍然可用(包括智能体入职)
-Guardrails:
+安全护栏:
-- server binds to loopback by default
-- fail startup if mode is `local_trusted` with non-loopback bind
-- UI shows a persistent "Local trusted mode" badge
+- 服务器默认绑定回环地址
+- 如模式为 `local_trusted` 但绑定非回环地址,则启动失败
+- UI 显示持久的"本地受信模式"标识
-## Mode B: `cloud_hosted`
+## 模式 B:`cloud_hosted`
-Behavior:
+行为:
-- login required for all human endpoints
-- Better Auth for human auth
-- initial auth method: email + password
-- email verification is not required for initial release
-- hosted DB and remote deployment supported
-- multi-user sessions and role/permission enforcement
+- 所有人类端点均需登录
+- 使用 Better Auth 进行人类身份验证
+- 初始验证方式:邮箱 + 密码
+- 初始版本不要求邮箱验证
+- 支持托管数据库和远程部署
+- 多用户会话及角色/权限强制执行
-Guardrails:
+安全护栏:
-- fail startup if auth provider/session config is missing
-- fail startup if insecure auth bypass flag is set
-- health payload includes mode and auth readiness
+- 如缺少 auth provider/会话配置,则启动失败
+- 如设置了不安全的 auth 绕过标志,则启动失败
+- 健康检查载荷包含模式和 auth 就绪状态
-## Authentication choice
+## 身份验证选择
-- use Better Auth for human users
-- start with email/password login only
-- no email confirmation requirement in V1
-- keep implementation structured so social/SSO providers can be added later without changing membership/permission semantics
+- 人类用户使用 Better Auth
+- 初始仅支持邮箱/密码登录
+- V1 不要求邮箱确认
+- 保持实现结构化,以便后续添加社交/SSO 提供商时无需更改成员资格/权限语义
-## Auth and actor model
+## Auth 与角色模型
-Unify request actors into a single model:
+将请求角色统一为单一模型:
-- `user` (authenticated human)
-- `agent` (API key)
-- `local_board_implicit` (local trusted mode only)
+- `user`(已认证人类)
+- `agent`(API 密钥)
+- `local_board_implicit`(仅限本地受信模式)
-Rules:
+规则:
-- in `cloud_hosted`, only `user` and `agent` are valid actors
-- in `local_trusted`, unauthenticated browser/API requests resolve to `local_board_implicit`
-- `local_board_implicit` is authorized as an instance admin principal for local operations
-- all mutating actions continue writing `activity_log` with actor type/id
+- 在 `cloud_hosted` 中,仅 `user` 和 `agent` 是合法角色
+- 在 `local_trusted` 中,未认证的浏览器/API 请求解析为 `local_board_implicit`
+- `local_board_implicit` 被授权为本地操作的实例管理员主体
+- 所有变更操作继续将角色类型/ID 写入 `activity_log`
-## First admin bootstrap
+## 首位管理员引导
-Problem:
+问题:
-- new cloud deployments need a safe, explicit first human admin path
-- app cannot assume a pre-existing admin account
-- `local_trusted` does not use bootstrap flow because implicit local instance admin already exists
+- 新云部署需要一条安全、显式的首位人类管理员路径
+- 应用不能假设预先存在管理员账户
+- `local_trusted` 不使用引导流程,因为隐式本地实例管理员已存在
-Bootstrap flow:
+引导流程:
-1. If no `instance_admin` user exists for the deployment, instance is in `bootstrap_pending` state.
-2. CLI command `pnpm paperclipai auth bootstrap-ceo` creates a one-time CEO onboarding invite URL for that instance.
-3. `pnpm paperclipai onboard` runs this bootstrap check and prints the invite URL automatically when `bootstrap_pending`.
-4. Visiting the app while `bootstrap_pending` shows a blocking setup page with the exact CLI command to run (`pnpm paperclipai onboard`).
-5. Accepting that CEO invite creates the first admin user and exits bootstrap mode.
+1. 若该部署不存在 `instance_admin` 用户,实例处于 `bootstrap_pending` 状态。
+2. CLI 命令 `pnpm paperclipai auth bootstrap-ceo` 为该实例创建一次性 CEO 入职邀请 URL。
+3. `pnpm paperclipai onboard` 运行此引导检查,并在 `bootstrap_pending` 时自动打印邀请 URL。
+4. 在 `bootstrap_pending` 状态下访问应用,将显示一个阻塞式设置页面,提示需运行的确切 CLI 命令(`pnpm paperclipai onboard`)。
+5. 接受 CEO 邀请后创建首位管理员用户并退出引导模式。
-Security rules:
+安全规则:
-- bootstrap invite is single-use, short-lived, and token-hash stored at rest
-- only one active bootstrap invite at a time per instance (regeneration revokes prior token)
-- bootstrap actions are audited in `activity_log`
+- 引导邀请为一次性、短时效,令牌哈希存储
+- 每个实例同时只能有一个活跃的引导邀请(重新生成会吊销前一个令牌)
+- 引导操作记录在 `activity_log` 中
-## Data model additions
+## 数据模型新增
-## New tables
+## 新增表
1. `users`
-- identity record for human users (email-based)
-- optional instance-level role field (or companion table) for admin rights
+- 人类用户的身份记录(基于邮箱)
+- 可选的实例级角色字段(或配套表)用于管理员权限
2. `company_memberships`
-- `company_id`, `principal_type` (`user | agent`), `principal_id`
-- status (`pending | active | suspended`), role metadata
-- stores effective access state for both humans and agents
-- many-to-many: one principal can belong to multiple companies
+- `company_id`、`principal_type`(`user | agent`)、`principal_id`
+- 状态(`pending | active | suspended`)、角色元数据
+- 存储人类与智能体的有效访问状态
+- 多对多:一个主体可属于多家公司
3. `invites`
-- `company_id`, `invite_type` (`company_join | bootstrap_ceo`), token hash, expires_at, invited_by, revoked_at, accepted_at
-- one-time share link (no pre-bound invite email)
-- `allowed_join_types` (`human | agent | both`) for `company_join` links
-- optional defaults payload keyed by join type:
- - human defaults: initial permissions/membership role
- - agent defaults: proposed role/title/adapter defaults
+- `company_id`、`invite_type`(`company_join | bootstrap_ceo`)、令牌哈希、expires_at、invited_by、revoked_at、accepted_at
+- 一次性分享链接(无预绑定邀请邮箱)
+- `company_join` 链接的 `allowed_join_types`(`human | agent | both`)
+- 按加入类型区分的可选默认载荷:
+ - 人类默认值:初始权限/成员角色
+ - 智能体默认值:建议的角色/职称/适配器默认值
4. `principal_permission_grants`
-- `company_id`, `principal_type` (`user | agent`), `principal_id`, `permission_key`
-- explicit grants such as `agents:create`
-- includes scope payload for chain-of-command limits
-- normalized table (not JSON blob) for auditable grant/revoke history
+- `company_id`、`principal_type`(`user | agent`)、`principal_id`、`permission_key`
+- 显式授权,如 `agents:create`
+- 包含指挥链限制的作用域载荷
+- 规范化表(非 JSON blob),便于审计授权/撤销历史
5. `join_requests`
-- `invite_id`, `company_id`, `request_type` (`human | agent`)
-- `status` (`pending_approval | approved | rejected`)
-- common review metadata:
+- `invite_id`、`company_id`、`request_type`(`human | agent`)
+- `status`(`pending_approval | approved | rejected`)
+- 通用审核元数据:
- `request_ip`
- - `approved_by_user_id`, `approved_at`, `rejected_by_user_id`, `rejected_at`
-- human request fields:
- - `requesting_user_id`, `request_email_snapshot`
-- agent request fields:
- - `agent_name`, `adapter_type`, `capabilities`, `created_agent_id` nullable until approved
-- each consumed invite creates exactly one join request record after join type is selected
+ - `approved_by_user_id`、`approved_at`、`rejected_by_user_id`、`rejected_at`
+- 人类请求字段:
+ - `requesting_user_id`、`request_email_snapshot`
+- 智能体请求字段:
+ - `agent_name`、`adapter_type`、`capabilities`、`created_agent_id`(审批前为空)
+- 每个已消费邀请在选择加入类型后恰好创建一条加入请求记录
-6. `issues` extension
+6. `issues` 扩展
-- add `assignee_user_id` nullable
-- preserve single-assignee invariant with XOR check:
- - exactly zero or one of `assignee_agent_id` / `assignee_user_id`
+- 添加可空的 `assignee_user_id`
+- 通过 XOR 检查保留单一受托人不变量:
+ - `assignee_agent_id` / `assignee_user_id` 中恰好有零个或一个非空
-## Compatibility
+## 兼容性
-- existing `created_by_user_id` / `author_user_id` fields remain and become fully active
-- agent API keys remain auth credentials; membership + grants remain authorization source
+- 现有的 `created_by_user_id` / `author_user_id` 字段保留并完全启用
+- 智能体 API 密钥仍为身份验证凭据;成员资格 + 授权为授权来源
## Permission model (initial set)
diff --git a/doc/plans/2026-02-23-deployment-auth-mode-consolidation.md b/doc/plans/2026-02-23-deployment-auth-mode-consolidation.md
index dbb0f45467..e24dc9c1cd 100644
--- a/doc/plans/2026-02-23-deployment-auth-mode-consolidation.md
+++ b/doc/plans/2026-02-23-deployment-auth-mode-consolidation.md
@@ -1,223 +1,223 @@
-# Deployment/Auth Mode Consolidation Plan
+# 部署/认证模式整合方案
-Status: Proposal
-Owner: Server + CLI + UI
-Date: 2026-02-23
+状态:提案
+负责方:Server + CLI + UI
+日期:2026-02-23
-## Goal
+## 目标
-Keep Paperclip low-friction while making the mode model simpler and safer:
+保持 Paperclip 的低摩擦体验,同时使模式模型更简洁、更安全:
-1. `local_trusted` remains the default and easiest path.
-2. one authenticated runtime mode supports both private-network local use and public cloud use.
-3. onboarding/configure/doctor stay primarily interactive and flagless.
-4. Board identity is represented by a real user row in the database, with explicit role/membership integration points.
+1. `local_trusted` 仍然是默认且最简单的路径。
+2. 一种认证运行时模式同时支持私有网络本地使用和公有云使用。
+3. onboarding/configure/doctor 主要保持交互式且无需标志位。
+4. 面板身份由数据库中的真实用户行表示,具备明确的角色/成员关系集成点。
-## Product Constraints (From Review)
+## 产品约束(来自评审)
-1. `onboard` default flow is interactive (no flags required).
-2. first mode choice defaults to `local_trusted`, with clear UX copy.
-3. authenticated flow gives guidance for private vs public exposure.
-4. `doctor` should also be flagless by default (read config and evaluate the selected mode/profile).
-5. do not add backward-compatibility alias layers for abandoned mode names.
-6. plan must explicitly cover how users/Board are represented in DB and how that affects task assignment and permissions.
+1. `onboard` 默认流程是交互式的(不需要标志位)。
+2. 首次模式选择默认为 `local_trusted`,并提供清晰的 UX 文案。
+3. 认证流程为私有部署与公共暴露提供指导。
+4. `doctor` 默认也应无需标志位(读取配置并评估所选模式/配置文件)。
+5. 不为已废弃的模式名称添加向后兼容的别名层。
+6. 方案必须明确说明用户/面板在数据库中的表示方式,以及这如何影响任务分配和权限。
-## Current Implementation Audit (As Of 2026-02-23)
+## 当前实现审计(截至 2026-02-23)
-## Runtime/Auth
+## 运行时/认证
-- Runtime deployment modes are currently `local_trusted | cloud_hosted` (`packages/shared/src/constants.ts`).
-- `local_trusted` actor is currently synthetic:
- - `req.actor = { type: "board", userId: "local-board", source: "local_implicit" }` (`server/src/middleware/auth.ts`).
- - this is not a real auth user row by default.
-- `cloud_hosted` uses Better Auth sessions and `authUsers` rows (`server/src/auth/better-auth.ts`, `packages/db/src/schema/auth.ts`).
+- 运行时部署模式当前为 `local_trusted | cloud_hosted`(`packages/shared/src/constants.ts`)。
+- `local_trusted` 的 actor 当前是合成的:
+ - `req.actor = { type: "board", userId: "local-board", source: "local_implicit" }`(`server/src/middleware/auth.ts`)。
+ - 默认情况下这不是一个真实的认证用户行。
+- `cloud_hosted` 使用 Better Auth 会话和 `authUsers` 行(`server/src/auth/better-auth.ts`、`packages/db/src/schema/auth.ts`)。
-## Bootstrap/Admin
+## 引导/管理员
-- `cloud_hosted` requires `BETTER_AUTH_SECRET` and reports bootstrap status from `instance_user_roles` (`server/src/index.ts`, `server/src/routes/health.ts`).
-- bootstrap invite acceptance promotes the signed-in user to `instance_admin` (`server/src/routes/access.ts`, `server/src/services/access.ts`).
+- `cloud_hosted` 需要 `BETTER_AUTH_SECRET` 并从 `instance_user_roles` 报告引导状态(`server/src/index.ts`、`server/src/routes/health.ts`)。
+- 引导邀请接受会将已登录用户提升为 `instance_admin`(`server/src/routes/access.ts`、`server/src/services/access.ts`)。
-## Membership/Assignment Integration
+## 成员/分配集成
-- User task assignment requires active `company_memberships` entry for that user (`server/src/services/issues.ts`).
-- Local implicit board identity is not automatically a real membership principal; this is a gap for “board as assignable user” semantics.
+- 用户任务分配要求该用户具有活跃的 `company_memberships` 条目(`server/src/services/issues.ts`)。
+- 本地隐式面板身份不会自动成为真实的成员主体;这对"面板作为可分配用户"的语义来说是一个缺口。
-## Proposed Runtime Model
+## 提议的运行时模型
-## Modes
+## 模式
1. `local_trusted`
-- no login required
-- localhost/loopback only
-- optimized for single-operator local setup
+- 不需要登录
+- 仅限 localhost/回环地址
+- 针对单操作员本地安装优化
2. `authenticated`
-- login required for human actions
-- same auth stack for both private and public deployments
+- 人工操作需要登录
+- 私有部署和公共部署使用相同的认证栈
-## Exposure Policy (Within `authenticated`)
+## 暴露策略(在 `authenticated` 模式下)
1. `private`
-- private-network deployments (LAN, VPN, Tailscale)
-- low-friction URL handling (`auto` base URL)
-- strict host allow policy for private targets
+- 私有网络部署(局域网、VPN、Tailscale)
+- 低摩擦 URL 处理(`auto` 基础 URL)
+- 针对私有目标的严格主机允许策略
2. `public`
-- internet-facing deployments
-- explicit public base URL required
-- stricter deployment checks in doctor
+- 面向互联网的部署
+- 需要明确的公共基础 URL
+- doctor 中有更严格的部署检查
-This is one authenticated mode with two safety policies, not two different auth systems.
+这是一种具有两种安全策略的认证模式,而非两个不同的认证系统。
-## UX Contract
+## UX 契约
-## Onboard (Primary Path: Interactive)
+## Onboard(主要路径:交互式)
-Default command remains:
+默认命令保持不变:
```sh
pnpm paperclipai onboard
```
-Interactive server step:
+交互式服务器步骤:
-1. ask mode with default selection `local_trusted`
-2. copy for options:
-- `local_trusted`: "Easiest for local setup (no login, localhost-only)"
-- `authenticated`: "Login required; use for private network or public hosting"
-3. if `authenticated`, ask exposure:
-- `private`: "Private network access (for example Tailscale), lower setup friction"
-- `public`: "Internet-facing deployment, stricter security requirements"
-4. only if `authenticated + public`, ask for explicit public URL
+1. 询问模式,默认选择 `local_trusted`
+2. 选项文案:
+- `local_trusted`:"本地安装最简单(无需登录,仅限 localhost)"
+- `authenticated`:"需要登录;用于私有网络或公共托管"
+3. 如果选择 `authenticated`,询问暴露方式:
+- `private`:"私有网络访问(例如 Tailscale),较低的安装摩擦"
+- `public`:"面向互联网的部署,更严格的安全要求"
+4. 仅在 `authenticated + public` 时,要求提供明确的公共 URL
-Flags are optional power-user overrides, not required for normal setup.
+标志位是可选的高级用户覆盖项,正常安装不需要。
## Configure
-Default command remains interactive:
+默认命令保持交互式:
```sh
pnpm paperclipai configure --section server
```
-Same mode/exposure questions and defaults as onboarding.
+与 onboarding 相同的模式/暴露问题和默认值。
## Doctor
-Default command remains flagless:
+默认命令保持无需标志位:
```sh
pnpm paperclipai doctor
```
-Doctor reads configured mode/exposure and applies relevant checks.
-Optional flags may exist for override/testing, but are not required for normal operation.
+Doctor 读取已配置的模式/暴露设置并应用相关检查。
+可选标志位可用于覆盖/测试,但正常操作不需要。
-## Board/User Data Model Integration (Required)
+## 面板/用户数据模型集成(必需)
-## Requirement
+## 需求
-Board must be a real DB user principal so user-centric features (task assignment, membership, audit identity) work consistently.
+面板必须是一个真实的数据库用户主体,这样以用户为中心的功能(任务分配、成员关系、审计身份)才能一致地工作。
-## Target Behavior
+## 目标行为
1. `local_trusted`
-- seed/ensure a deterministic local board user row in `authUsers` during setup/startup.
-- actor middleware uses that real user id instead of synthetic-only identity.
-- ensure:
- - `instance_user_roles` includes `instance_admin` for this user.
- - company membership can be created/maintained for this user where needed.
+- 在安装/启动期间种子化/确保一个确定性的本地面板用户行存在于 `authUsers` 中。
+- actor 中间件使用该真实用户 ID,而非仅使用合成身份。
+- 确保:
+ - `instance_user_roles` 包含该用户的 `instance_admin`。
+ - 可以在需要时为该用户创建/维护 company 成员关系。
2. `authenticated`
-- Better Auth sign-up creates user row.
-- bootstrap/admin flow promotes that real user to `instance_admin`.
-- first company creation flow should ensure creator membership is active.
+- Better Auth 注册创建用户行。
+- 引导/管理员流程将该真实用户提升为 `instance_admin`。
+- 首次 company 创建流程应确保创建者的成员关系处于活跃状态。
-## Why This Matters
+## 为何重要
-- `assigneeUserId` validation checks company membership.
-- without a real board user + membership path, assigning tasks to board user is inconsistent.
+- `assigneeUserId` 验证检查 company 成员关系。
+- 没有真实的面板用户 + 成员关系路径,向面板用户分配任务就是不一致的。
-## Configuration Contract (Target)
+## 配置契约(目标)
-- `server.mode`: `local_trusted | authenticated`
-- `server.exposure`: `private | public` (required when mode is `authenticated`)
-- `auth.baseUrlMode`: `auto | explicit`
-- `auth.publicBaseUrl`: required when `authenticated + public`
+- `server.mode`:`local_trusted | authenticated`
+- `server.exposure`:`private | public`(当模式为 `authenticated` 时必需)
+- `auth.baseUrlMode`:`auto | explicit`
+- `auth.publicBaseUrl`:当 `authenticated + public` 时必需
-No compatibility aliases for discarded naming variants.
+不为已废弃的命名变体设置兼容性别名。
-## No Backward-Compatibility Layer
+## 无向后兼容层
-This change is a clean cut:
+此变更是一次干净的切换:
-- remove use of old split terminology in code and prompts.
-- config schema uses only canonical fields/values above.
-- existing dev instances can rerun onboarding or update config once.
+- 移除代码和提示中旧的拆分术语。
+- 配置模式仅使用上述规范字段/值。
+- 现有开发实例可以重新运行 onboarding 或一次性更新配置。
-## Implementation Phases
+## 实施阶段
-## Phase 1: Shared Schema + Config Surface
+## 阶段 1:共享模式 + 配置表面
-- `packages/shared/src/constants.ts`: define canonical mode/exposure constants.
-- `packages/shared/src/config-schema.ts`: add mode/exposure/auth URL fields.
-- `server/src/config.ts` and CLI config types: consume canonical fields only.
+- `packages/shared/src/constants.ts`:定义规范的模式/暴露常量。
+- `packages/shared/src/config-schema.ts`:添加模式/暴露/认证 URL 字段。
+- `server/src/config.ts` 和 CLI 配置类型:仅消费规范字段。
-## Phase 2: CLI Interactive UX
+## 阶段 2:CLI 交互式 UX
-- `cli/src/prompts/server.ts`: implement defaulted mode prompt and authenticated exposure guidance copy.
-- `cli/src/commands/onboard.ts`: keep interactive-first flow; optional overrides only.
-- `cli/src/commands/configure.ts`: same behavior for server section.
-- `cli/src/commands/doctor.ts`: mode-aware checks from config, flagless default flow.
+- `cli/src/prompts/server.ts`:实现带默认值的模式提示和认证暴露指导文案。
+- `cli/src/commands/onboard.ts`:保持交互优先流程;仅可选覆盖。
+- `cli/src/commands/configure.ts`:服务器部分相同行为。
+- `cli/src/commands/doctor.ts`:基于配置的模式感知检查,默认无需标志位。
-## Phase 3: Runtime/Auth Policy
+## 阶段 3:运行时/认证策略
-- `server/src/index.ts`: enforce mode-specific startup constraints.
-- `server/src/auth/better-auth.ts`: implement `auto` vs `explicit` base URL behavior.
-- host/origin trust helper for `authenticated + private`.
+- `server/src/index.ts`:强制执行模式特定的启动约束。
+- `server/src/auth/better-auth.ts`:实现 `auto` 与 `explicit` 基础 URL 行为。
+- 用于 `authenticated + private` 的主机/来源信任辅助工具。
-## Phase 4: Board Principal Integration
+## 阶段 4:面板主体集成
-- add ensure-board-user startup/setup step:
- - real local board user row
- - instance admin role row
-- ensure first-company creation path grants creator membership.
-- remove synthetic-only assumptions where they break user assignment/membership semantics.
+- 添加确保面板用户的启动/安装步骤:
+ - 真实的本地面板用户行
+ - 实例管理员角色行
+- 确保首次 company 创建路径授予创建者成员关系。
+- 移除在破坏用户分配/成员关系语义处的仅合成假设。
-## Phase 5: UI + Docs
+## 阶段 5:UI + 文档
-- update UI labels/help text around mode and exposure guidance.
-- update docs:
+- 更新围绕模式和暴露指导的 UI 标签/帮助文本。
+- 更新文档:
- `doc/DEPLOYMENT-MODES.md`
- `doc/DEVELOPING.md`
- `doc/CLI.md`
- `doc/SPEC-implementation.md`
-## Test Plan
+## 测试计划
-- config schema tests for canonical mode/exposure/auth fields.
-- CLI prompt tests for default interactive selections and copy.
-- doctor tests by mode/exposure.
-- runtime tests:
- - authenticated/private works without explicit URL
- - authenticated/public requires explicit URL
- - private host policy rejects untrusted hosts
-- Board principal tests:
- - local_trusted board user exists as real DB user
- - board can be assigned tasks via `assigneeUserId` after membership setup
- - creator membership behavior for authenticated flows
+- 规范模式/暴露/认证字段的配置模式测试。
+- 默认交互式选择和文案的 CLI 提示测试。
+- 按模式/暴露的 doctor 测试。
+- 运行时测试:
+ - authenticated/private 无需显式 URL 即可工作
+ - authenticated/public 需要显式 URL
+ - private 主机策略拒绝不可信主机
+- 面板主体测试:
+ - local_trusted 面板用户作为真实数据库用户存在
+ - 面板在成员关系设置后可通过 `assigneeUserId` 被分配任务
+ - authenticated 流程的创建者成员关系行为
-## Acceptance Criteria
+## 验收标准
-1. `pnpm paperclipai onboard` is interactive-first and defaults to `local_trusted`.
-2. authenticated mode is one runtime mode with `private/public` exposure guidance.
-3. `pnpm paperclipai doctor` works flagless with mode-aware checks.
-4. no extra compatibility aliases for dropped naming variants.
-5. Board identity is represented by real DB user/role/membership integration points, enabling consistent task assignment and permission behavior.
+1. `pnpm paperclipai onboard` 以交互式为先且默认为 `local_trusted`。
+2. 认证模式是一个运行时模式,带有 `private/public` 暴露指导。
+3. `pnpm paperclipai doctor` 无需标志位即可工作,具有模式感知检查。
+4. 无额外的兼容性别名用于已废弃的命名变体。
+5. 面板身份由真实的数据库用户/角色/成员关系集成点表示,支持一致的任务分配和权限行为。
-## Verification Gate
+## 验证关卡
-Before merge:
+合并前:
```sh
pnpm -r typecheck
diff --git a/doc/plans/2026-03-10-workspace-strategy-and-git-worktrees.md b/doc/plans/2026-03-10-workspace-strategy-and-git-worktrees.md
index 8ab63794c1..ae28ce218e 100644
--- a/doc/plans/2026-03-10-workspace-strategy-and-git-worktrees.md
+++ b/doc/plans/2026-03-10-workspace-strategy-and-git-worktrees.md
@@ -1,305 +1,305 @@
-# Workspace Strategy and Git Worktrees
+# 工作区策略与 Git Worktrees
-## Context
+## 背景
-`PAP-447` asks how Paperclip should support worktree-driven coding workflows for local coding agents without turning that into a universal product requirement.
+`PAP-447` 探讨 Paperclip 应如何在不将其作为通用产品要求的前提下,为本地编码代理支持基于 worktree 的编码工作流。
-The motivating use case is strong:
+该动机用例十分充分:
-- when an issue starts, a local coding agent may want its own isolated checkout
-- the agent may need a dedicated branch and a predictable path to push later
-- the agent may need to start one or more long-lived workspace runtime services, discover reachable ports or URLs, and report them back into the issue
-- the workflow should reuse the same Paperclip instance and embedded database instead of creating a blank environment
-- local agent auth should remain low-friction
+- 当一个问题开始时,本地编码代理可能需要自己的独立检出(isolated checkout)
+- 代理可能需要一个专用分支,以及之后推送的可预测路径
+- 代理可能需要启动一个或多个长期运行的工作区运行时服务,发现可达的端口或 URL,并将其报告回该问题
+- 该工作流应复用同一个 Paperclip 实例和嵌入式数据库,而不是创建一个空白环境
+- 本地代理的身份验证应保持低摩擦
-At the same time, we do not want to hard-code "every agent uses git worktrees" into Paperclip:
+与此同时,我们不希望将"每个代理都使用 git worktrees"硬编码到 Paperclip 中:
-- some operators use Paperclip to manage Paperclip and want worktrees heavily
-- other operators will not want worktrees at all
-- not every adapter runs in a local git repository
-- not every adapter runs on the same machine as Paperclip
-- Claude and Codex expose different built-in affordances, so Paperclip should not overfit to one tool
+- 部分运营者使用 Paperclip 来管理 Paperclip 本身,并大量依赖 worktrees
+- 其他运营者完全不需要 worktrees
+- 并非每个适配器都在本地 git 仓库中运行
+- 并非每个适配器都与 Paperclip 运行在同一台机器上
+- Claude 和 Codex 暴露了不同的内置功能,因此 Paperclip 不应过度适配某一工具
-## Core Product Decision
+## 核心产品决策
-Paperclip should model **execution workspaces**, not **worktrees**.
+Paperclip 应建模**执行工作区(execution workspaces)**,而非 **worktrees**。
-More specifically:
+更具体地说:
-- the durable anchor is the **project workspace** or repo checkout
-- an issue may derive a temporary **execution workspace** from that project workspace
-- one implementation of an execution workspace is a **git worktree**
-- adapters decide whether and how to use that derived workspace
+- 持久锚点是**项目工作区(project workspace)**或仓库检出
+- 一个问题可以从该项目工作区派生出一个临时的**执行工作区(execution workspace)**
+- 执行工作区的一种实现方式是 **git worktree**
+- 适配器决定是否以及如何使用该派生工作区
-This keeps the abstraction portable:
+这保持了抽象的可移植性:
-- `project workspace` is the repo/project-level concept
-- `execution workspace` is the runtime checkout/cwd for a run
-- `git worktree` is one strategy for creating that execution workspace
-- `workspace runtime services` are long-lived processes or previews attached to that workspace
+- `project workspace` 是仓库/项目层面的概念
+- `execution workspace` 是一次运行时的运行时检出/cwd
+- `git worktree` 是创建该执行工作区的一种策略
+- `workspace runtime services` 是附属于该工作区的长期运行进程或预览
-This also keeps the abstraction valid for non-local adapters:
+这也使抽象对非本地适配器保持有效:
-- local adapters may receive a real filesystem cwd produced by Paperclip
-- remote or cloud adapters may receive the same execution intent in structured form and realize it inside their own environment
-- Paperclip should not assume that every adapter can see or use a host filesystem path directly
+- 本地适配器可以接收 Paperclip 生成的真实文件系统 cwd
+- 远程或云适配器可以以结构化形式接收相同的执行意图,并在其自己的环境中实现
+- Paperclip 不应假设每个适配器都能看到或直接使用宿主文件系统路径
-## Answer to the Main Framing Questions
+## 主要框架问题的解答
-### Are worktrees for agents or for repos/projects?
+### Worktrees 是用于代理的还是用于仓库/项目的?
-They should be treated as **repo/project-scoped infrastructure**, not agent identity.
+它们应被视为**仓库/项目范围的基础设施**,而非代理身份的一部分。
-The stable object is the project workspace. Agents come and go, ownership changes, and the same issue may be reassigned. A git worktree is a derived checkout of a repo workspace for a specific task or issue. The agent uses it, but should not own the abstraction.
+稳定的对象是项目工作区。代理来来去去,所有权会发生变化,同一个问题也可能被重新分配。git worktree 是针对特定任务或问题从仓库工作区派生的检出。代理使用它,但不应拥有该抽象。
-If Paperclip makes worktrees agent-first, it will blur:
+如果 Paperclip 将 worktrees 以代理为先,将会混淆:
-- agent home directories
-- project repo roots
-- issue-specific branches/checkouts
+- 代理主目录
+- 项目仓库根目录
+- 问题特定的分支/检出
-That makes reuse, reassignment, cleanup, and UI visibility harder.
+这会使复用、重新分配、清理和 UI 可见性变得更加困难。
-### How do we preserve optionality?
+### 我们如何保持灵活性?
-By making execution workspace strategy **opt-in at the adapter/config layer**, not a global invariant.
+通过使执行工作区策略**在适配器/配置层面选择性启用**,而非作为全局不变量。
-Defaults should remain:
+默认值应保持:
-- existing project workspace resolution
-- existing task-session resume
-- existing agent-home fallback
+- 现有的项目工作区解析
+- 现有的任务会话恢复
+- 现有的代理主目录回退
-Then local coding agents can opt into a strategy like `git_worktree`.
+然后本地编码代理可以选择加入 `git_worktree` 这样的策略。
-### How do we make this portable and adapter-appropriate?
+### 我们如何使其可移植且适配器友好?
-By splitting responsibilities:
+通过拆分职责:
-- Paperclip core resolves and records execution workspace state
-- a shared local runtime helper can implement git-based checkout strategies
-- each adapter launches its tool inside the resolved cwd using adapter-specific flags
+- Paperclip 核心解析并记录执行工作区状态
+- 共享的本地运行时助手可以实现基于 git 的检出策略
+- 每个适配器使用适配器特定的标志在解析后的 cwd 内启动其工具
-This avoids forcing a Claude-shaped or Codex-shaped model onto all adapters.
+这避免了将 Claude 形态或 Codex 形态的模型强加给所有适配器。
-It also avoids forcing a host-filesystem model onto cloud agents. A cloud adapter may interpret the same requested strategy as:
+这也避免了将宿主文件系统模型强加给云代理。云适配器可以将相同的请求策略解释为:
-- create a fresh sandbox checkout from repo + ref
-- create an isolated branch/workspace inside the provider's remote environment
-- ignore local-only fields like host cwd while still honoring branch/ref/isolation intent
+- 从 repo + ref 创建一个全新的沙盒检出
+- 在提供商的远程环境中创建一个隔离的分支/工作区
+- 忽略宿主 cwd 等仅限本地的字段,同时仍遵循分支/ref/隔离意图
-## Product and UX Requirements
+## 产品与用户体验要求
-The current technical model is directionally right, but the product surface needs clearer separation between:
+当前的技术模型方向正确,但产品界面需要在以下概念之间进行更清晰的分离:
-- the generic cross-adapter concept of an **execution workspace**
-- the user-visible local-git implementation concept of an **isolated issue checkout**
-- the specific git implementation detail of a **git worktree**
+- 跨适配器通用概念**执行工作区(execution workspace)**
+- 面向用户的本地 git 实现概念**独立问题检出(isolated issue checkout)**
+- 特定 git 实现细节 **git worktree**
-Those should not be collapsed into one label in the UI.
+这些不应在 UI 中合并为一个标签。
-### Terminology recommendation
+### 术语建议
-For product/UI copy:
+对于产品/UI 文案:
-- use **execution workspace** for the generic cross-adapter concept
-- use **isolated issue checkout** for the user-facing feature when we want to say "this issue gets its own branch/checkout"
-- reserve **git worktree** for advanced or implementation detail views
+- 使用**执行工作区(execution workspace)**表示跨适配器的通用概念
+- 使用**独立问题检出(isolated issue checkout)**表示面向用户的功能,即"该问题拥有自己的分支/检出"
+- 将 **git worktree** 保留用于高级或实现细节视图
-That gives Paperclip room to support:
+这为 Paperclip 提供了支持以下内容的空间:
-- local git worktrees
-- remote sandbox checkouts
-- adapter-managed remote workspaces
+- 本地 git worktrees
+- 远程沙盒检出
+- 适配器管理的远程工作区
-without teaching users that "workspace" always means "git worktree on my machine".
+而无需让用户认为"工作区"总是意味着"我机器上的 git worktree"。
-### Project-level defaults should drive the feature
+### 项目级默认值应驱动该功能
-The main place this should be configured is the **project**, not the agent form.
+主要配置位置应在**项目**层面,而非代理表单。
-Reasoning:
+原因:
-- whether a repo/project wants isolated issue checkouts is primarily a project workflow decision
-- most operators do not want to configure runtime JSON per agent
-- agents should inherit the project's workspace policy unless there is a strong adapter-specific override
-- the board needs a place to express repo workflow defaults such as branching, PRs, cleanup, and preview lifecycle
+- 仓库/项目是否需要独立问题检出,主要是项目工作流决策
+- 大多数运营者不希望为每个代理配置运行时 JSON
+- 除非有强烈的适配器特定覆盖,代理应继承项目的工作区策略
+- 看板需要一个地方来表达仓库工作流默认值,例如分支、PR、清理和预览生命周期
-So the project should own a setting like:
+因此项目应拥有如下设置:
-- `isolatedIssueCheckouts.enabled` or equivalent
+- `isolatedIssueCheckouts.enabled` 或等效项
-and that should be the default driver for new issues in that project.
+这应作为该项目中新问题的默认驱动器。
-### Issue-level use should stay optional
+### 问题级使用应保持可选
-Even when a project supports isolated issue checkouts, not every issue should be forced into one.
+即使项目支持独立问题检出,也不应强制每个问题都使用。
-Examples:
+示例:
-- a small fix may be fine in the main project workspace
-- an operator may want to work directly on a long-lived branch
-- a board user may want to create a task without paying the setup/cleanup overhead
+- 小修复可能在主项目工作区中就够用了
+- 运营者可能希望直接在长期分支上工作
+- 看板用户可能希望创建任务而不需要付出设置/清理的开销
-So the model should be:
+因此模型应为:
-- project defines whether isolated issue checkouts are available and what the defaults are
-- each issue can opt in or out when created
-- the default issue value can be inherited from the project
+- 项目定义独立问题检出是否可用以及默认值是什么
+- 每个问题在创建时可以选择加入或退出
+- 问题的默认值可以从项目继承
-This should not require showing advanced adapter config in normal issue creation flows.
+这不应要求在正常问题创建流程中显示高级适配器配置。
-### Runtime services should usually be hidden from the agent form
+### 运行时服务通常应隐藏在代理表单之外
-The current raw runtime service JSON is too low-level as a primary UI for most local agents.
+当前原始运行时服务 JSON 对于大多数本地代理来说作为主要 UI 层级过低。
-For `claude_local` and `codex_local`, the likely desired behavior is:
+对于 `claude_local` 和 `codex_local`,可能期望的行为是:
-- Paperclip handles workspace runtime services under the hood using project/workspace policy
-- operators do not need to hand-author generic runtime JSON in the agent form
-- if a provider-specific adapter later needs richer runtime configuration, give it a purpose-built UI rather than generic JSON by default
+- Paperclip 使用项目/工作区策略在后台处理工作区运行时服务
+- 运营者不需要在代理表单中手写通用运行时 JSON
+- 如果某个提供商特定的适配器将来需要更丰富的运行时配置,提供专用 UI,而非默认使用通用 JSON
-So the UI recommendation is:
+因此 UI 建议为:
-- keep runtime service JSON out of the default local-agent editing experience
-- allow it only behind an advanced section or adapter-specific expert mode
-- move the common workflow settings up to project-level workspace automation settings
+- 将运行时服务 JSON 排除在默认本地代理编辑体验之外
+- 仅在高级部分或适配器特定专家模式后面允许使用
+- 将常见工作流设置移至项目级工作区自动化设置
-### Pull request workflow needs explicit ownership and approval rules
+### Pull request 工作流需要明确的所有权和审批规则
-Once Paperclip is creating isolated issue checkouts, it is implicitly touching a bigger workflow:
+一旦 Paperclip 创建独立问题检出,就隐式涉及更大的工作流:
-- branch creation
-- runtime service start/stop
-- commit and push
-- PR creation
-- cleanup after merge or abandonment
+- 分支创建
+- 运行时服务启动/停止
+- 提交和推送
+- PR 创建
+- 合并或放弃后的清理
-That means the product needs an explicit model for **who owns PR creation and merge readiness**.
+这意味着产品需要一个明确的模型来定义 **PR 创建和合并就绪的所有者**。
-At minimum there are two valid modes:
+至少有两种有效模式:
-- agent-managed PR creation
-- approval-gated PR creation
+- 代理管理的 PR 创建
+- 审批门控的 PR 创建
-And likely three distinct decision points:
+以及可能的三个不同决策点:
-1. should the agent commit automatically?
-2. should the agent open the PR automatically?
-3. does opening or marking-ready require board approval?
+1. 代理是否应自动提交?
+2. 代理是否应自动打开 PR?
+3. 打开或标记为就绪是否需要看板审批?
-Those should not be buried inside adapter prompts. They are workflow policy.
+这些不应埋藏在适配器提示中。它们是工作流策略。
-### Human operator workflows are different from issue-isolation workflows
+### 人工运营者工作流与问题隔离工作流不同
-A human operator may want a long-lived personal integration branch such as `dotta` and may not want every task to create a new branch/workspace dance.
+人工运营者可能希望有一个长期个人集成分支(例如 `dotta`),且可能不希望每个任务都创建新的分支/工作区。
-That is a legitimate workflow and should be supported directly.
+这是合理的工作流,应直接支持。
-So Paperclip should distinguish:
+因此 Paperclip 应区分:
-- **isolated issue checkout workflows**: optimized for agent parallelism and issue-scoped isolation
-- **personal branch workflows**: optimized for a human or operator making multiple related changes on a long-lived branch and creating PRs back to the main branch when convenient
+- **独立问题检出工作流(isolated issue checkout workflows)**:针对代理并行性和问题范围隔离进行优化
+- **个人分支工作流(personal branch workflows)**:针对人工或运营者在长期分支上进行多项相关更改,并在方便时向主分支创建 PR 进行优化
-This implies:
+这意味着:
-- isolated issue checkouts should be optional even when available
-- project workflow settings should support a "use base branch directly" or "use preferred operator branch" path
-- PR policy should not assume that every unit of work maps 1:1 to a new branch or PR
+- 即使独立问题检出可用,它也应是可选的
+- 项目工作流设置应支持"直接使用基础分支"或"使用首选运营者分支"的路径
+- PR 策略不应假设每个工作单元都与新分支或 PR 一一对应
-## Recommended UX Model
+## 推荐的用户体验模型
-### 1. Project-level "Execution Workspace" settings
+### 1. 项目级"执行工作区"设置
-Projects should have a dedicated settings area for workspace automation.
+项目应拥有专门的工作区自动化设置区域。
-Suggested structure:
+建议结构:
-- `Execution Workspaces`
- - `Enable isolated issue checkouts`
- - `Default for new issues`
- - `Checkout implementation`
- - `Branch and PR behavior`
- - `Runtime services`
- - `Cleanup behavior`
+- `执行工作区(Execution Workspaces)`
+ - `启用独立问题检出(Enable isolated issue checkouts)`
+ - `新问题的默认值(Default for new issues)`
+ - `检出实现方式(Checkout implementation)`
+ - `分支与 PR 行为(Branch and PR behavior)`
+ - `运行时服务(Runtime services)`
+ - `清理行为(Cleanup behavior)`
-For a local git-backed project, the visible language can be more concrete:
+对于本地 git 支持的项目,可见语言可以更具体:
-- `Enable isolated issue checkouts`
-- `Implementation: Git worktree`
+- `启用独立问题检出(Enable isolated issue checkouts)`
+- `实现方式:Git worktree(Implementation: Git worktree)`
-For remote or adapter-managed projects, the same section can instead say:
+对于远程或适配器管理的项目,同一部分可改为:
-- `Implementation: Adapter-managed workspace`
+- `实现方式:适配器管理的工作区(Implementation: Adapter-managed workspace)`
-### 2. Issue creation should expose a simple opt-in
+### 2. 问题创建应暴露简单的选择加入选项
-When creating an issue inside a project with execution workspace support enabled:
+在启用了执行工作区支持的项目中创建问题时:
-- show a checkbox or toggle such as `Use isolated issue checkout`
-- default it from the project setting
-- hide advanced workspace controls unless the operator has expanded an advanced section
+- 显示一个复选框或开关,例如 `使用独立问题检出(Use isolated issue checkout)`
+- 从项目设置中获取默认值
+- 除非运营者展开了高级部分,否则隐藏高级工作区控件
-If the project does not support execution workspaces, do not show the control at all.
+如果项目不支持执行工作区,则完全不显示该控件。
-This keeps the default UI light while preserving control.
+这在保持控制的同时保持了默认 UI 的简洁。
-### 3. Agent configuration should be mostly inheritance-based
+### 3. 代理配置应主要基于继承
-The agent form should not be the primary place where operators assemble worktree/runtime policy for common local agents.
+代理表单不应是运营者为常见本地代理组装 worktree/运行时策略的主要位置。
-Instead:
+取而代之:
-- local coding agents inherit the project's execution workspace policy
-- the agent form only exposes an override when truly necessary
-- raw JSON config is advanced-only
+- 本地编码代理继承项目的执行工作区策略
+- 代理表单仅在真正必要时暴露覆盖项
+- 原始 JSON 配置仅限高级用户
-That means the common case becomes:
+这意味着常见情况变为:
-- configure the project once
-- assign a local coding agent
-- create issues with optional isolated checkout behavior
+- 一次性配置项目
+- 分配本地编码代理
+- 创建具有可选独立检出行为的问题
-### 4. Advanced implementation detail can still exist
+### 4. 高级实现细节仍然可以存在
-There should still be an advanced view for power users that shows:
+仍应为高级用户提供高级视图,显示:
-- execution workspace strategy payload
-- runtime service intent payload
-- adapter-specific overrides
+- 执行工作区策略载荷
+- 运行时服务意图载荷
+- 适配器特定覆盖项
-But that should be treated like an expert/debugging surface, not the default mental model.
+但这应被视为专家/调试界面,而非默认的思维模型。
-## Recommended Workflow Policy Model
+## 推荐的工作流策略模型
-### Workspace realization policy
+### 工作区实现策略
-Suggested policy values:
+建议的策略值:
- `shared_project_workspace`
- `isolated_issue_checkout`
- `adapter_managed_isolated_workspace`
-For local git projects, `isolated_issue_checkout` may map to `git_worktree`.
+对于本地 git 项目,`isolated_issue_checkout` 可以映射到 `git_worktree`。
-### Branch policy
+### 分支策略
-Suggested project-level branch policy fields:
+建议的项目级分支策略字段:
- `baseBranch`
- `branchMode`: `issue_scoped | operator_branch | project_primary`
-- `branchTemplate` for issue-scoped branches
-- `operatorPreferredBranch` for human/operator workflows
+- `branchTemplate` 用于问题范围的分支
+- `operatorPreferredBranch` 用于人工/运营者工作流
-This allows:
+这允许:
-- strict issue branches for agents
-- long-lived personal branches for humans
-- direct use of the project primary workspace when desired
+- 代理使用严格的问题分支
+- 人工使用长期个人分支
+- 在需要时直接使用项目主工作区
-### Pull request policy
+### Pull request 策略
-Suggested project-level PR policy fields:
+建议的项目级 PR 策略字段:
- `prMode`: `none | agent_may_open | agent_auto_open | approval_required`
- `autoPushOnDone`: boolean
@@ -307,11 +307,11 @@ Suggested project-level PR policy fields:
- `requireApprovalBeforeReady`: boolean
- `defaultBaseBranch`
-This keeps PR behavior explicit and governable.
+这使 PR 行为明确且可治理。
-### Cleanup policy
+### 清理策略
-Suggested project-level cleanup fields:
+建议的项目级清理字段:
- `stopRuntimeServicesOnDone`
- `removeIsolatedCheckoutOnDone`
@@ -319,63 +319,63 @@ Suggested project-level cleanup fields:
- `deleteIssueBranchOnMerged`
- `retainFailedWorkspaceForInspection`
-These matter because workspace automation is not just setup. The cleanup path is part of the product.
+这些很重要,因为工作区自动化不仅仅是设置。清理路径也是产品的一部分。
-## Design Recommendations for the Current UI Problem
+## 当前 UI 问题的设计建议
-Based on the concerns above, the UI should change in these ways:
+基于上述考虑,UI 应进行以下更改:
-### Agent UI
+### 代理 UI
-- remove generic runtime service JSON from the default local-agent configuration surface
-- keep raw workspace/runtime JSON behind advanced settings only
-- prefer inheritance from project settings for `claude_local` and `codex_local`
-- only add adapter-specific runtime UI when an adapter truly needs settings that Paperclip cannot infer
+- 从默认本地代理配置界面移除通用运行时服务 JSON
+- 将原始工作区/运行时 JSON 置于高级设置之后
+- 对于 `claude_local` 和 `codex_local`,优先从项目设置继承
+- 仅在适配器真正需要 Paperclip 无法推断的设置时添加适配器特定运行时 UI
-### Project UI
+### 项目 UI
-- add a project-level execution workspace settings section
-- allow enabling isolated issue checkouts for that project
-- store default issue behavior there
-- expose branch, PR, runtime service, and cleanup defaults there
+- 添加项目级执行工作区设置部分
+- 允许为该项目启用独立问题检出
+- 在那里存储问题默认行为
+- 在那里暴露分支、PR、运行时服务和清理默认值
-### Issue creation UI
+### 问题创建 UI
-- only show `Use isolated issue checkout` when the project has execution workspace support enabled
-- keep it as an issue-level opt-in/out, defaulted from the project
-- hide advanced execution workspace details unless requested
+- 仅在项目启用了执行工作区支持时显示 `使用独立问题检出(Use isolated issue checkout)`
+- 将其保持为问题级的选择加入/退出,从项目继承默认值
+- 除非被请求,否则隐藏高级执行工作区详情
-## Consequences for the Spec
+## 对规范的影响
-This changes the emphasis of the plan in a useful way:
+这以有益的方式改变了计划的重点:
-- the project becomes the main workflow configuration owner
-- the issue becomes the unit of opt-in/out for isolated checkout behavior
-- the agent becomes an executor that usually inherits the workflow policy
-- raw runtime JSON becomes an advanced/internal representation, not the main UX
+- 项目成为主要的工作流配置所有者
+- 问题成为独立检出行为选择加入/退出的单元
+- 代理成为通常继承工作流策略的执行者
+- 原始运行时 JSON 成为高级/内部表示,而非主要的用户体验
-It also clarifies that PR creation and cleanup are not optional side notes. They are core parts of the workspace automation product surface.
+这也明确了 PR 创建和清理不是可选的附注,它们是工作区自动化产品界面的核心部分。
-## Concrete Integration Checklist
+## 具体集成清单
-This section turns the product requirements above into a concrete implementation plan for the current codebase.
+本部分将上述产品要求转化为当前代码库的具体实现计划。
-### Guiding precedence rule
+### 指导优先级规则
-The runtime decision order should become:
+运行时决策顺序应变为:
-1. issue-level execution workspace override
-2. project-level execution workspace policy
-3. agent-level adapter override
-4. current default behavior
+1. 问题级执行工作区覆盖
+2. 项目级执行工作区策略
+3. 代理级适配器覆盖
+4. 当前默认行为
-That is the key architectural change. Today the implementation is too agent-config-centered for the desired UX.
+这是关键的架构变更。目前的实现对于所期望的用户体验来说过于以代理配置为中心。
-## Proposed Field Names
+## 建议的字段名称
-### Project-level fields
+### 项目级字段
-Add a project-owned execution workspace policy object. Suggested shared shape:
+添加项目拥有的执行工作区策略对象。建议的共享形态:
```ts
type ProjectExecutionWorkspacePolicy = {
@@ -409,16 +409,16 @@ type ProjectExecutionWorkspacePolicy = {
};
```
-Notes:
+注意:
-- `enabled` controls whether the project exposes isolated issue checkout behavior at all
-- `defaultMode` controls issue creation defaults
-- `implementation` stays generic enough for local or remote adapters
-- runtime service config stays nested here, not in the default agent form
+- `enabled` 控制项目是否完全暴露独立问题检出行为
+- `defaultMode` 控制问题创建的默认值
+- `implementation` 保持足够通用以适配本地或远程适配器
+- 运行时服务配置嵌套在此处,不在默认代理表单中
-### Issue-level fields
+### 问题级字段
-Add issue-owned opt-in/override fields. Suggested shape:
+添加问题拥有的选择加入/覆盖字段。建议的形态:
```ts
type IssueExecutionWorkspaceSettings = {
@@ -428,112 +428,112 @@ type IssueExecutionWorkspaceSettings = {
};
```
-This should usually be hidden behind simple UI:
+这通常应隐藏在简单 UI 背后:
-- a checkbox like `Use isolated issue checkout`
-- advanced controls only when needed
+- 一个复选框,如 `使用独立问题检出(Use isolated issue checkout)`
+- 仅在需要时显示高级控件
-### Agent-level fields
+### 代理级字段
-Keep agent-level workspace/runtime configuration, but reposition it as advanced override only.
+保留代理级工作区/运行时配置,但将其重新定位为仅限高级覆盖。
-Suggested semantics:
+建议的语义:
-- if absent, inherit project + issue policy
-- if present, override only the implementation detail needed for that adapter
+- 如果不存在,继承项目 + 问题策略
+- 如果存在,仅覆盖该适配器所需的实现细节
-## Shared Type and API Changes
+## 共享类型与 API 变更
-### 1. Shared project types
+### 1. 共享项目类型
-Files to change first:
+首先需要修改的文件:
- `packages/shared/src/types/project.ts`
- `packages/shared/src/validators/project.ts`
-Add:
+添加:
- `executionWorkspacePolicy?: ProjectExecutionWorkspacePolicy | null`
-### 2. Shared issue types
+### 2. 共享问题类型
-Files to change:
+需要修改的文件:
- `packages/shared/src/types/issue.ts`
- `packages/shared/src/validators/issue.ts`
-Add:
+添加:
- `executionWorkspaceSettings?: IssueExecutionWorkspaceSettings | null`
-### 3. DB schema
+### 3. 数据库模式
-If we want these fields persisted directly on existing entities instead of living in opaque JSON:
+如果希望这些字段直接持久化在现有实体上,而非存储在不透明的 JSON 中:
- `packages/db/src/schema/projects.ts`
- `packages/db/src/schema/issues.ts`
-- migration generation in `packages/db/src/migrations/`
+- 迁移生成位于 `packages/db/src/migrations/`
-Recommended first cut:
+建议的第一步:
-- store project policy as JSONB on `projects`
-- store issue setting override as JSONB on `issues`
+- 将项目策略作为 JSONB 存储在 `projects` 上
+- 将问题设置覆盖作为 JSONB 存储在 `issues` 上
-That minimizes schema churn while the product model is still moving.
+这在产品模型仍在演进时最大程度减少了模式变动。
-Suggested columns:
+建议的列:
- `projects.execution_workspace_policy jsonb`
- `issues.execution_workspace_settings jsonb`
-## Server-Side Resolution Changes
+## 服务端解析变更
-### 4. Project service read/write path
+### 4. 项目服务读写路径
-Files:
+文件:
- `server/src/services/projects.ts`
-- project routes in `server/src/routes/projects.ts`
+- `server/src/routes/projects.ts` 中的项目路由
-Tasks:
+任务:
-- accept and validate project execution workspace policy
-- return it from project API payloads
-- enforce company scoping as usual
+- 接受并验证项目执行工作区策略
+- 从项目 API 载荷中返回它
+- 像往常一样强制执行公司范围
-### 5. Issue service create/update path
+### 5. 问题服务创建/更新路径
-Files:
+文件:
- `server/src/services/issues.ts`
- `server/src/routes/issues.ts`
-Tasks:
+任务:
-- accept issue-level `executionWorkspaceSettings`
-- when creating an issue in a project with execution workspaces enabled, default the issue setting from the project policy if not explicitly provided
-- keep issue payload simple for normal clients; advanced fields may be optional
+- 接受问题级 `executionWorkspaceSettings`
+- 在启用了执行工作区的项目中创建问题时,如果未明确提供,则从项目策略中默认问题设置
+- 对普通客户端保持问题载荷简单;高级字段可以是可选的
-### 6. Heartbeat and run resolution
+### 6. 心跳与运行解析
-Primary file:
+主要文件:
- `server/src/services/heartbeat.ts`
-Current behavior should be refactored so workspace resolution is based on:
+当前行为应重构,使工作区解析基于:
-- issue setting
-- then project policy
-- then adapter override
+- 问题设置
+- 然后是项目策略
+- 然后是适配器覆盖
-Specific technical work:
+具体技术工作:
-- load project execution workspace policy during run resolution
-- load issue execution workspace settings during run resolution
-- derive an effective execution workspace decision object before adapter launch
-- keep adapter config as override only
+- 在运行解析期间加载项目执行工作区策略
+- 在运行解析期间加载问题执行工作区设置
+- 在适配器启动前推导有效执行工作区决策对象
+- 将适配器配置保持为仅覆盖
-Suggested internal helper:
+建议的内部助手:
```ts
type EffectiveExecutionWorkspaceDecision = {
@@ -546,64 +546,62 @@ type EffectiveExecutionWorkspaceDecision = {
};
```
-## UI Changes
+## UI 变更
-### 7. Project settings UI
+### 7. 项目设置 UI
-Likely files:
+可能涉及的文件:
- `ui/src/components/ProjectProperties.tsx`
-- project detail/settings pages under `ui/src/pages/`
-- project API client in `ui/src/api/projects.ts`
-
-Add a project-owned section:
+- `ui/src/pages/` 下的项目详情/设置页面
+- `ui/src/api/projects.ts` 中的项目 API 客户端
-- `Execution Workspaces`
- - enable isolated issue checkouts
- - default for new issues
- - implementation type
- - branch settings
- - PR settings
- - cleanup settings
- - runtime service defaults
+添加项目拥有的部分:
-Important UX rule:
+- `执行工作区(Execution Workspaces)`
+ - 启用独立问题检出
+ - 新问题的默认值
+ - 实现类型
+ - 分支设置
+ - PR 设置
+ - 清理设置
+ - 运行时服务默认值
-- runtime service config should not default to raw JSON
-- if the first cut must use JSON internally, wrap it in a minimal structured form or advanced disclosure
+重要的 UX 规则:
-### 8. Issue creation/edit UI
+- 运行时服务配置不应默认为原始 JSON
+- 如果第一步必须在内部使用 JSON,将其包装在最简结构化表单或高级展开区中
-Likely files:
+### 8. 问题创建/编辑 UI
-- issue create UI components and issue detail edit surfaces in `ui/src/pages/`
-- issue API client in `ui/src/api/issues.ts`
+可能涉及的文件:
-Add:
+- `ui/src/pages/` 中的问题创建 UI 组件和问题详情编辑界面
+- `ui/src/api/issues.ts` 中的问题 API 客户端
-- `Use isolated issue checkout` toggle, only when project policy enables it
-- advanced workspace behavior controls only when expanded
+添加:
-Do not show:
+- `使用独立问题检出(Use isolated issue checkout)` 开关,仅在项目策略启用时显示
+- 仅在展开时显示高级工作区行为控件
-- raw runtime service JSON
-- raw strategy payloads
+不在默认问题创建流程中显示:
-in the default issue creation flow.
+- 原始运行时服务 JSON
+- 原始策略载荷
-### 9. Agent UI cleanup
+### 9. 代理 UI 清理
-Files:
+文件:
- `ui/src/adapters/local-workspace-runtime-fields.tsx`
- `ui/src/adapters/codex-local/config-fields.tsx`
- `ui/src/adapters/claude-local/config-fields.tsx`
-Technical direction:
+技术方向:
-- keep the existing config surface as advanced override
-- remove it from the default form flow for local coding agents
-- add explanatory copy that project execution workspace policy is inherited unless overridden
+- 将现有配置界面保持为高级覆盖
+- 将其从本地编码代理的默认表单流程中移除
+- 添加解释性文案,说明项目执行工作区策略将被继承,除非被覆盖
## Adapter and Orchestration Changes
diff --git a/doc/plans/2026-03-11-agent-chat-ui-and-issue-backed-conversations.md b/doc/plans/2026-03-11-agent-chat-ui-and-issue-backed-conversations.md
index 7364b6d0a2..68d351a4e6 100644
--- a/doc/plans/2026-03-11-agent-chat-ui-and-issue-backed-conversations.md
+++ b/doc/plans/2026-03-11-agent-chat-ui-and-issue-backed-conversations.md
@@ -1,329 +1,329 @@
-# Agent Chat UI and Issue-Backed Conversations
+# 智能体聊天界面与基于 Issue 的对话
-## Context
+## 背景
-`PAP-475` asks two related questions:
+`PAP-475` 提出了两个相关问题:
-1. What UI kit should Paperclip use if we add a chat surface with an agent?
-2. How should chat fit the product without breaking the current issue-centric model?
+1. 如果 Paperclip 要添加与智能体的聊天界面,应该使用什么 UI 工具包?
+2. 聊天功能应如何融入产品,同时不破坏当前以 issue 为中心的模型?
-This is not only a component-library decision. In Paperclip today:
+这不仅仅是一个组件库的选择问题。在当前的 Paperclip 中:
-- V1 explicitly says communication is `tasks + comments only`, with no separate chat system.
-- Issues already carry assignment, audit trail, billing code, project linkage, goal linkage, and active run linkage.
-- Live run streaming already exists on issue detail pages.
-- Agent sessions already persist by `taskKey`, and today `taskKey` falls back to `issueId`.
-- The OpenClaw gateway adapter already supports an issue-scoped session key strategy.
+- V1 明确指出通信方式仅限于 `tasks + comments only`,没有单独的聊天系统。
+- Issue 已经承载了指派、审计追踪、计费代码、项目关联、目标关联和活跃运行关联。
+- Issue 详情页面已经支持实时运行流式输出。
+- 智能体会话已经通过 `taskKey` 持久化,目前 `taskKey` 会回退到 `issueId`。
+- OpenClaw 网关适配器已经支持基于 issue 范围的会话密钥策略。
-That means the cheapest useful path is not "add a second messaging product inside Paperclip." It is "add a better conversational UI on top of issue and run primitives we already have."
+这意味着最经济实用的路径不是"在 Paperclip 内部添加第二个消息产品",而是"在我们已有的 issue 和运行原语之上添加更好的对话界面"。
-## Current Constraints From the Codebase
+## 代码库中的当前约束
-### Durable work object
+### 持久化工作对象
-The durable object in Paperclip is the issue, not a chat thread.
+Paperclip 中的持久化对象是 issue,而不是聊天线程。
-- `IssueDetail` already combines comments, linked runs, live runs, and activity into one timeline.
-- `CommentThread` already renders markdown comments and supports reply/reassignment flows.
-- `LiveRunWidget` already renders streaming assistant/tool/system output for active runs.
+- `IssueDetail` 已经将评论、关联运行、实时运行和活动整合到一个时间线中。
+- `CommentThread` 已经渲染 markdown 评论并支持回复/重新指派流程。
+- `LiveRunWidget` 已经为活跃运行渲染流式的助手/工具/系统输出。
-### Session behavior
+### 会话行为
-Session continuity is already task-shaped.
+会话连续性已经是以任务为形态的。
-- `heartbeat.ts` derives `taskKey` from `taskKey`, then `taskId`, then `issueId`.
-- `agent_task_sessions` stores session state per company + agent + adapter + task key.
-- OpenClaw gateway supports `sessionKeyStrategy=issue|fixed|run`, and `issue` already matches the Paperclip mental model well.
+- `heartbeat.ts` 从 `taskKey` 派生 `taskKey`,然后是 `taskId`,最后是 `issueId`。
+- `agent_task_sessions` 按公司 + 智能体 + 适配器 + 任务密钥存储会话状态。
+- OpenClaw 网关支持 `sessionKeyStrategy=issue|fixed|run`,其中 `issue` 已经很好地匹配了 Paperclip 的心智模型。
-That means "chat with the CEO about this issue" naturally maps to one durable session per issue today without inventing a second session system.
+这意味着"就这个 issue 与 CEO 聊天"在当前无需发明第二套会话系统,就能自然映射到每个 issue 一个持久会话。
-### Billing behavior
+### 计费行为
-Billing is already issue-aware.
+计费已经具有 issue 感知能力。
-- `cost_events` can attach to `issueId`, `projectId`, `goalId`, and `billingCode`.
-- heartbeat context already propagates issue linkage into runs and cost rollups.
+- `cost_events` 可以关联到 `issueId`、`projectId`、`goalId` 和 `billingCode`。
+- 心跳上下文已经将 issue 关联传播到运行和成本汇总中。
-If chat leaves the issue model, Paperclip would need a second billing story. That is avoidable.
+如果聊天脱离 issue 模型,Paperclip 将需要第二套计费方案。这是可以避免的。
-## UI Kit Recommendation
+## UI 工具包推荐
-## Recommendation: `assistant-ui`
+## 推荐:`assistant-ui`
-Use `assistant-ui` as the chat presentation layer.
+使用 `assistant-ui` 作为聊天展示层。
-Why it fits Paperclip:
+为什么它适合 Paperclip:
-- It is a real chat UI kit, not just a hook.
-- It is composable and aligned with shadcn-style primitives, which matches the current UI stack well.
-- It explicitly supports custom backends, which matters because Paperclip talks to agents through issue comments, heartbeats, and run streams rather than direct provider calls.
-- It gives us polished chat affordances quickly: message list, composer, streaming text, attachments, thread affordances, and markdown-oriented rendering.
+- 它是一个真正的聊天 UI 工具包,不仅仅是一个 hook。
+- 它是可组合的,与 shadcn 风格的原语对齐,这与当前的 UI 技术栈很好地匹配。
+- 它明确支持自定义后端,这很重要,因为 Paperclip 通过 issue 评论、心跳和运行流与智能体通信,而不是直接的提供商调用。
+- 它能快速提供完善的聊天交互能力:消息列表、编辑器、流式文本、附件、线程功能和面向 markdown 的渲染。
-Why not make "the Vercel one" the primary choice:
+为什么不将"Vercel 的方案"作为首选:
-- Vercel AI SDK is stronger today than the older "just `useChat` over `/api/chat`" framing. Its transport layer is flexible and can support custom protocols.
-- But AI SDK is still better understood here as a transport/runtime protocol layer than as the best end-user chat surface for Paperclip.
-- Paperclip does not need Vercel to own message state, persistence, or the backend contract. Paperclip already has its own issue, run, and session model.
+- Vercel AI SDK 目前比早期"仅仅是在 `/api/chat` 上使用 `useChat`"的定位要强大得多。它的传输层很灵活,可以支持自定义协议。
+- 但 AI SDK 在这里仍然更适合被理解为传输/运行时协议层,而不是 Paperclip 最佳的终端用户聊天界面。
+- Paperclip 不需要 Vercel 来拥有消息状态、持久化或后端契约。Paperclip 已经有自己的 issue、运行和会话模型。
-So the clean split is:
+因此,清晰的分工是:
-- `assistant-ui` for UI primitives
-- Paperclip-owned runtime/store for state, persistence, and transport
-- optional AI SDK usage later only if we want its stream protocol or client transport abstraction
+- `assistant-ui` 用于 UI 原语
+- Paperclip 自有的运行时/存储用于状态、持久化和传输
+- 仅在后续需要其流协议或客户端传输抽象时才可选使用 AI SDK
-## Product Options
+## 产品方案
-### Option A: Separate chat object
+### 方案 A:独立聊天对象
-Create a new top-level chat/thread model unrelated to issues.
+创建一个与 issue 无关的新顶级聊天/线程模型。
-Pros:
+优点:
-- clean mental model if users want freeform conversation
-- easy to hide from issue boards
+- 如果用户需要自由形式的对话,心智模型很清晰
+- 容易从 issue 看板中隐藏
-Cons:
+缺点:
-- breaks the current V1 product decision that communication is issue-centric
-- needs new persistence, billing, session, permissions, activity, and wakeup rules
-- creates a second "why does this exist?" object beside issues
-- makes "pick up an old chat" a separate retrieval problem
+- 打破了当前 V1 中通信以 issue 为中心的产品决策
+- 需要新的持久化、计费、会话、权限、活动和唤醒规则
+- 在 issue 旁边创建了第二个"为什么要有这个?"的对象
+- 使"找回旧对话"成为一个独立的检索问题
-Verdict: not recommended for V1.
+结论:V1 不推荐。
-### Option B: Every chat is an issue
+### 方案 B:每次聊天都是一个 issue
-Treat chat as a UI mode over an issue. The issue remains the durable record.
+将聊天视为 issue 之上的一种 UI 模式。Issue 仍然是持久记录。
-Pros:
+优点:
-- matches current product spec
-- billing, runs, comments, approvals, and activity already work
-- sessions already resume on issue identity
-- works with all adapters, including OpenClaw, without new agent auth or a second API surface
+- 符合当前产品规格
+- 计费、运行、评论、审批和活动已经可以正常工作
+- 会话已经基于 issue 身份恢复
+- 适用于所有适配器,包括 OpenClaw,无需新的智能体认证或第二个 API 接口
-Cons:
+缺点:
-- some chats are not really "tasks" in a board sense
-- onboarding and review conversations may clutter normal issue lists
+- 某些聊天在看板意义上并不真正是"任务"
+- 入职引导和评审对话可能会使正常的 issue 列表变得杂乱
-Verdict: best V1 foundation.
+结论:最佳的 V1 基础。
-### Option C: Hybrid with hidden conversation issues
+### 方案 C:带隐藏对话 issue 的混合方案
-Back every conversation with an issue, but allow a conversation-flavored issue mode that is hidden from default execution boards unless promoted.
+每个对话都由一个 issue 支撑,但允许一种对话风格的 issue 模式,默认从执行看板中隐藏,除非被提升。
-Pros:
+优点:
-- preserves the issue-centric backend
-- gives onboarding/review chat a cleaner UX
-- preserves billing and session continuity
+- 保留了以 issue 为中心的后端
+- 为入职引导/评审聊天提供了更简洁的用户体验
+- 保留了计费和会话的连续性
-Cons:
+缺点:
-- requires extra UI rules and possibly a small schema or filtering addition
-- can become a disguised second system if not kept narrow
+- 需要额外的 UI 规则,可能还需要少量的 schema 或过滤增补
+- 如果不加以限制,可能会变成伪装的第二套系统
-Verdict: likely the right product shape after a basic issue-backed MVP.
+结论:在基本的基于 issue 的 MVP 之后,很可能是正确的产品形态。
-## Recommended Product Model
+## 推荐的产品模型
-### Phase 1 product decision
+### 第一阶段产品决策
-For the first implementation, chat should be issue-backed.
+在首次实现中,聊天应当基于 issue。
-More specifically:
+更具体地说:
-- the board opens a chat surface for an issue
-- sending a message is a comment mutation on that issue
-- the assigned agent is woken through the existing issue-comment flow
-- streaming output comes from the existing live run stream for that issue
-- durable assistant output remains comments and run history, not an extra transcript store
+- 看板为一个 issue 打开聊天界面
+- 发送消息就是对该 issue 的评论变更
+- 通过现有的 issue 评论流程唤醒已指派的智能体
+- 流式输出来自该 issue 现有的实时运行流
+- 持久化的助手输出保留为评论和运行历史,而不是额外的对话记录存储
-This keeps Paperclip honest about what it is:
+这使 Paperclip 保持了自身的定位:
-- the control plane stays issue-centric
-- chat is a better way to interact with issue work, not a new collaboration product
+- 控制平面保持以 issue 为中心
+- 聊天是与 issue 工作交互的更好方式,而不是一个新的协作产品
-### Onboarding and CEO conversations
+### 入职引导和 CEO 对话
-For onboarding, weekly reviews, and "chat with the CEO", use a conversation issue rather than a global chat tab.
+对于入职引导、周回顾和"与 CEO 聊天",使用对话 issue 而不是全局聊天标签。
-Suggested shape:
+建议的形态:
-- create a board-initiated issue assigned to the CEO
-- mark it as conversation-flavored in UI treatment
-- optionally hide it from normal issue boards by default later
-- keep all cost/run/session linkage on that issue
+- 创建一个由看板发起的、指派给 CEO 的 issue
+- 在 UI 中将其标记为对话风格
+- 后续可选择默认从普通 issue 看板中隐藏
+- 保持该 issue 上的所有成本/运行/会话关联
-This solves several concerns at once:
+这同时解决了几个问题:
-- no separate API key or direct provider wiring is needed
-- the same CEO adapter is used
-- old conversations are recovered through normal issue history
-- the CEO can still create or update real child issues from the conversation
+- 不需要单独的 API 密钥或直接的提供商接入
+- 使用相同的 CEO 适配器
+- 通过正常的 issue 历史恢复旧对话
+- CEO 仍然可以从对话中创建或更新真正的子 issue
-## Session Model
+## 会话模型
### V1
-Use one durable conversation session per issue.
+每个 issue 使用一个持久对话会话。
-That already matches current behavior:
+这已经匹配了当前行为:
-- adapter task sessions persist against `taskKey`
-- `taskKey` already falls back to `issueId`
-- OpenClaw already supports an issue-scoped session key
+- 适配器任务会话基于 `taskKey` 持久化
+- `taskKey` 已经回退到 `issueId`
+- OpenClaw 已经支持基于 issue 范围的会话密钥
-This means "resume the CEO conversation later" works by reopening the same issue and waking the same agent on the same issue.
+这意味着"稍后恢复 CEO 对话"只需重新打开同一个 issue 并在同一个 issue 上唤醒同一个智能体即可工作。
-### What not to add yet
+### 暂时不要添加的功能
-Do not add multi-thread-per-issue chat in the first pass.
+在第一阶段不要添加每个 issue 多线程聊天。
-If Paperclip later needs several parallel threads on one issue, then add an explicit conversation identity and derive:
+如果 Paperclip 后续需要在一个 issue 上进行多个并行线程,那时再添加显式的对话身份并派生:
- `taskKey = issue::conversation:`
- OpenClaw `sessionKey = paperclip:conversation:`
-Until that requirement becomes real, one issue == one durable conversation is the simpler and better rule.
+在该需求真正出现之前,一个 issue == 一个持久对话是更简单更好的规则。
-## Billing Model
+## 计费模型
-Chat should not invent a separate billing pipeline.
+聊天不应发明独立的计费流水线。
-All chat cost should continue to roll up through the issue:
+所有聊天成本应继续通过 issue 汇总:
- `cost_events.issueId`
-- project and goal rollups through existing relationships
-- issue `billingCode` when present
+- 通过现有关系进行项目和目标汇总
+- 存在 `billingCode` 时使用 issue 的 `billingCode`
-If a conversation is important enough to exist, it is important enough to have a durable issue-backed audit and cost trail.
+如果一个对话重要到需要存在,那它就重要到应该有持久的、基于 issue 的审计和成本追踪。
-This is another reason ephemeral freeform chat should not be the default.
+这是临时性自由形式聊天不应成为默认方式的另一个原因。
-## UI Architecture
+## UI 架构
-### Recommended stack
+### 推荐的技术栈
-1. Keep Paperclip as the source of truth for message history and run state.
-2. Add `assistant-ui` as the rendering/composer layer.
-3. Build a Paperclip runtime adapter that maps:
- - issue comments -> user/assistant messages
- - live run deltas -> streaming assistant messages
- - issue attachments -> chat attachments
-4. Keep current markdown rendering and code-block support where possible.
+1. 保持 Paperclip 作为消息历史和运行状态的唯一真实来源。
+2. 添加 `assistant-ui` 作为渲染/编辑器层。
+3. 构建一个 Paperclip 运行时适配器来映射:
+ - issue 评论 -> 用户/助手消息
+ - 实时运行增量 -> 流式助手消息
+ - issue 附件 -> 聊天附件
+4. 尽可能保留当前的 markdown 渲染和代码块支持。
-### Interaction flow
+### 交互流程
-1. Board opens issue detail in "Chat" mode.
-2. Existing comment history is mapped into chat messages.
-3. When the board sends a message:
+1. 看板以"聊天"模式打开 issue 详情。
+2. 现有评论历史被映射为聊天消息。
+3. 当看板发送消息时:
- `POST /api/issues/{id}/comments`
- - optionally interrupt the active run if the UX wants "send and replace current response"
-4. Existing issue comment wakeup logic wakes the assignee.
-5. Existing `/issues/{id}/live-runs` and `/issues/{id}/active-run` data feeds drive streaming.
-6. When the run completes, durable state remains in comments/runs/activity as it does now.
+ - 如果用户体验需要"发送并替换当前响应",可选择中断当前活跃运行
+4. 现有的 issue 评论唤醒逻辑唤醒被指派者。
+5. 现有的 `/issues/{id}/live-runs` 和 `/issues/{id}/active-run` 数据源驱动流式输出。
+6. 当运行完成时,持久状态像现在一样保留在评论/运行/活动中。
-### Why this fits the current code
+### 为什么这适合当前代码
-Paperclip already has most of the backend pieces:
+Paperclip 已经拥有大部分后端组件:
-- issue comments
-- run timeline
-- run log and event streaming
-- markdown rendering
-- attachment support
-- assignee wakeups on comments
+- issue 评论
+- 运行时间线
+- 运行日志和事件流
+- markdown 渲染
+- 附件支持
+- 评论时唤醒被指派者
-The missing piece is mostly the presentation and the mapping layer, not a new backend domain.
+缺少的部分主要是展示层和映射层,而不是新的后端领域。
-## Agent Scope
+## 智能体范围
-Do not launch this as "chat with every agent."
+不要以"与每个智能体聊天"的形式发布此功能。
-Start narrower:
+从更窄的范围开始:
-- onboarding chat with CEO
-- workflow/review chat with CEO
-- maybe selected exec roles later
+- 与 CEO 的入职引导聊天
+- 与 CEO 的工作流/评审聊天
+- 后续可能扩展到选定的高管角色
-Reasons:
+原因:
-- it keeps the feature from becoming a second inbox/chat product
-- it limits permission and UX questions early
-- it matches the stated product demand
+- 防止该功能变成第二个收件箱/聊天产品
+- 在早期限制权限和用户体验问题
+- 符合已表述的产品需求
-If direct chat with other agents becomes useful later, the same issue-backed pattern can expand cleanly.
+如果后续与其他智能体的直接聊天变得有用,同样基于 issue 的模式可以干净地扩展。
-## Recommended Delivery Phases
+## 推荐的交付阶段
-### Phase 1: Chat UI on existing issues
+### 第一阶段:在现有 issue 上添加聊天 UI
-- add a chat presentation mode to issue detail
-- use `assistant-ui`
-- map comments + live runs into the chat surface
-- no schema change
-- no new API surface
+- 在 issue 详情页添加聊天展示模式
+- 使用 `assistant-ui`
+- 将评论 + 实时运行映射到聊天界面
+- 无 schema 变更
+- 无新 API 接口
-This is the highest-leverage step because it tests whether the UX is actually useful before product model expansion.
+这是杠杆效率最高的步骤,因为它在产品模型扩展之前测试用户体验是否真正有用。
-### Phase 2: Conversation-flavored issues for CEO chat
+### 第二阶段:为 CEO 聊天创建对话风格的 issue
-- add a lightweight conversation classification
-- support creation of CEO conversation issues from onboarding and workflow entry points
-- optionally hide these from normal backlog/board views by default
+- 添加轻量级的对话分类
+- 支持从入职引导和工作流入口创建 CEO 对话 issue
+- 可选择默认从普通积压/看板视图中隐藏这些 issue
-The smallest implementation could be a label or issue metadata flag. If it becomes important enough, then promote it to a first-class issue subtype later.
+最小化实现可以是一个标签或 issue 元数据标志。如果后续变得足够重要,再将其提升为一等 issue 子类型。
-### Phase 3: Promotion and thread splitting only if needed
+### 第三阶段:仅在需要时进行提升和线程拆分
-Only if we later see a real need:
+仅在确实有需求时:
-- allow promoting a conversation to a formal task issue
-- allow several threads per issue with explicit conversation identity
+- 允许将对话提升为正式的任务 issue
+- 允许每个 issue 有多个线程,带有显式的对话身份
-This should be demand-driven, not designed up front.
+这应该由需求驱动,而不是预先设计。
-## Clear Recommendation
+## 明确的推荐
-If the question is "what should we use?", the answer is:
+如果问题是"我们应该用什么?",答案是:
-- use `assistant-ui` for the chat UI
-- do not treat raw Vercel AI SDK UI hooks as the main product answer
-- keep chat issue-backed in V1
-- use the current issue comment + run + session + billing model rather than inventing a parallel chat subsystem
+- 使用 `assistant-ui` 作为聊天 UI
+- 不要将原始的 Vercel AI SDK UI hooks 作为主要的产品方案
+- 在 V1 中保持聊天基于 issue
+- 使用当前的 issue 评论 + 运行 + 会话 + 计费模型,而不是发明一个并行的聊天子系统
-If the question is "how should we think about chat in Paperclip?", the answer is:
+如果问题是"我们应该如何看待 Paperclip 中的聊天?",答案是:
-- chat is a mode of interacting with issue-backed agent work
-- not a separate product silo
-- not an excuse to stop tracing work, cost, and session history back to the issue
+- 聊天是与基于 issue 的智能体工作交互的一种模式
+- 不是一个独立的产品竖井
+- 不是停止将工作、成本和会话历史追溯到 issue 的借口
-## Implementation Notes
+## 实施说明
-### Immediate implementation target
+### 直接实施目标
-The most defensible first build is:
+最具防御性的首次构建是:
-- add a chat tab or chat-focused layout on issue detail
-- back it with the currently assigned agent on that issue
-- use `assistant-ui` primitives over existing comments and live run events
+- 在 issue 详情页添加聊天标签或以聊天为中心的布局
+- 以该 issue 当前指派的智能体作为后端
+- 在现有评论和实时运行事件之上使用 `assistant-ui` 原语
-### Defer these until proven necessary
+### 推迟到确有必要时再做
-- standalone global chat objects
-- multi-thread chat inside one issue
-- chat with every agent in the org
-- a second persistence layer for message history
-- separate cost tracking for chats
+- 独立的全局聊天对象
+- 单个 issue 内的多线程聊天
+- 与组织中每个智能体聊天
+- 消息历史的第二持久化层
+- 聊天的单独成本追踪
-## References
+## 参考资料
-- V1 communication model: `doc/SPEC-implementation.md`
-- Current issue/comment/run UI: `ui/src/pages/IssueDetail.tsx`, `ui/src/components/CommentThread.tsx`, `ui/src/components/LiveRunWidget.tsx`
-- Session persistence and task key derivation: `server/src/services/heartbeat.ts`, `packages/db/src/schema/agent_task_sessions.ts`
-- OpenClaw session routing: `packages/adapters/openclaw-gateway/README.md`
-- assistant-ui docs:
-- assistant-ui repo:
-- AI SDK transport docs:
+- V1 通信模型:`doc/SPEC-implementation.md`
+- 当前 issue/评论/运行 UI:`ui/src/pages/IssueDetail.tsx`、`ui/src/components/CommentThread.tsx`、`ui/src/components/LiveRunWidget.tsx`
+- 会话持久化和任务密钥派生:`server/src/services/heartbeat.ts`、`packages/db/src/schema/agent_task_sessions.ts`
+- OpenClaw 会话路由:`packages/adapters/openclaw-gateway/README.md`
+- assistant-ui 文档:
+- assistant-ui 代码库:
+- AI SDK 传输文档:
diff --git a/doc/plans/2026-03-13-TOKEN-OPTIMIZATION-PLAN.md b/doc/plans/2026-03-13-TOKEN-OPTIMIZATION-PLAN.md
index 7053e97f10..22ceb9cd4d 100644
--- a/doc/plans/2026-03-13-TOKEN-OPTIMIZATION-PLAN.md
+++ b/doc/plans/2026-03-13-TOKEN-OPTIMIZATION-PLAN.md
@@ -1,141 +1,141 @@
-# Token Optimization Plan
+# Token 优化计划
-Date: 2026-03-13
-Related discussion: https://github.com/paperclipai/paperclip/discussions/449
+日期:2026-03-13
+相关讨论:https://github.com/paperclipai/paperclip/discussions/449
-## Goal
+## 目标
-Reduce token consumption materially without reducing agent capability, control-plane visibility, or task completion quality.
+在不降低 agent 能力、控制平面可见性或任务完成质量的前提下,实质性地减少 token 消耗。
-This plan is based on:
+本计划基于:
-- the current V1 control-plane design
-- the current adapter and heartbeat implementation
-- the linked user discussion
-- local runtime data from the default Paperclip instance on 2026-03-13
+- 当前 V1 控制平面设计
+- 当前 adapter 和心跳(heartbeat)实现
+- 上述关联的用户讨论
+- 2026-03-13 默认 Paperclip 实例的本地运行时数据
-## Executive Summary
+## 执行摘要
-The discussion is directionally right about two things:
+该讨论在两个方向上是正确的:
-1. We should preserve session and prompt-cache locality more aggressively.
-2. We should separate stable startup instructions from per-heartbeat dynamic context.
+1. 我们应该更积极地保持 session 和提示缓存的局部性。
+2. 我们应该将稳定的启动指令与每次心跳的动态上下文分离。
-But that is not enough on its own.
+但仅靠这两点还不够。
-After reviewing the code and local run data, the token problem appears to have four distinct causes:
+在审查代码和本地运行数据之后,token 问题似乎有四个不同的原因:
-1. **Measurement inflation on sessioned adapters.** Some token counters, especially for `codex_local`, appear to be recorded as cumulative session totals instead of per-heartbeat deltas.
-2. **Avoidable session resets.** Task sessions are intentionally reset on timer wakes and manual wakes, which destroys cache locality for common heartbeat paths.
-3. **Repeated context reacquisition.** The `paperclip` skill tells agents to re-fetch assignments, issue details, ancestors, and full comment threads on every heartbeat. The API does not currently offer efficient delta-oriented alternatives.
-4. **Large static instruction surfaces.** Agent instruction files and globally injected skills are reintroduced at startup even when most of that content is unchanged and not needed for the current task.
+1. **有 session 的 adapter 上的计量虚高。** 部分 token 计数器,尤其是 `codex_local`,似乎记录的是累计 session 总量而非每次心跳的增量。
+2. **可避免的 session 重置。** 任务 session 在定时器唤醒和手动唤醒时被有意重置,这破坏了常见心跳路径的缓存局部性。
+3. **重复获取上下文。** `paperclip` skill 要求 agent 在每次心跳时重新获取任务分配、issue 详情、祖先链和完整评论线程。当前 API 尚未提供高效的增量替代方案。
+4. **庞大的静态指令面。** Agent 指令文件和全局注入的 skill 在启动时被重新引入,即使其中大部分内容未变且当前任务并不需要。
-The correct approach is:
+正确的做法是:
-1. fix telemetry so we can trust the numbers
-2. preserve reuse where it is safe
-3. make context retrieval incremental
-4. add session compaction/rotation so long-lived sessions do not become progressively more expensive
+1. 修复遥测数据,使数字可信
+2. 在安全的地方保持复用
+3. 使上下文检索增量化
+4. 添加 session 压缩/轮换,防止长期 session 变得越来越昂贵
-## Validated Findings
+## 已验证的发现
-### 1. Token telemetry is at least partly overstated today
+### 1. Token 遥测数据目前至少存在部分虚高
-Observed from the local default instance:
+从本地默认实例观察到:
-- `heartbeat_runs`: 11,360 runs between 2026-02-18 and 2026-03-13
-- summed `usage_json.inputTokens`: `2,272,142,368,952`
-- summed `usage_json.cachedInputTokens`: `2,217,501,559,420`
+- `heartbeat_runs`:2026-02-18 至 2026-03-13 期间共 11,360 次运行
+- `usage_json.inputTokens` 汇总:`2,272,142,368,952`
+- `usage_json.cachedInputTokens` 汇总:`2,217,501,559,420`
-Those totals are not credible as true per-heartbeat usage for the observed prompt sizes.
+对于观测到的提示大小,这些总量作为真实的每次心跳使用量是不可信的。
-Supporting evidence:
+佐证:
-- `adapter.invoke.payload.prompt` averages were small:
- - `codex_local`: ~193 chars average, 6,067 chars max
- - `claude_local`: ~160 chars average, 1,160 chars max
-- despite that, many `codex_local` runs report millions of input tokens
-- one reused Codex session in local data spans 3,607 runs and recorded `inputTokens` growing up to `1,155,283,166`
+- `adapter.invoke.payload.prompt` 平均值较小:
+ - `codex_local`:平均约 193 字符,最大 6,067 字符
+ - `claude_local`:平均约 160 字符,最大 1,160 字符
+- 尽管如此,许多 `codex_local` 运行报告了数百万个输入 token
+- 本地数据中某个复用的 Codex session 跨越 3,607 次运行,记录的 `inputTokens` 增长至 `1,155,283,166`
-Interpretation:
+解读:
-- for sessioned adapters, especially Codex, we are likely storing usage reported by the runtime as a **session total**, not a **per-run delta**
-- this makes trend reporting, optimization work, and customer trust worse
+- 对于有 session 的 adapter,尤其是 Codex,我们很可能将运行时报告的使用量存储为 **session 总量**,而非**每次运行的增量**
+- 这使趋势报告、优化工作和客户信任都变得更差
-This does **not** mean there is no real token problem. It means we need a trustworthy baseline before we can judge optimization impact.
+这**并不**意味着没有真实的 token 问题。这意味着我们在评估优化效果之前,需要一个可信的基准。
-### 2. Timer wakes currently throw away reusable task sessions
+### 2. 定时器唤醒目前会丢弃可复用的任务 session
-In `server/src/services/heartbeat.ts`, `shouldResetTaskSessionForWake(...)` returns `true` for:
+在 `server/src/services/heartbeat.ts` 中,`shouldResetTaskSessionForWake(...)` 在以下情况下返回 `true`:
- `wakeReason === "issue_assigned"`
- `wakeSource === "timer"`
-- manual on-demand wakes
+- 手动按需唤醒
-That means many normal heartbeats skip saved task-session resume even when the workspace is stable.
+这意味着许多正常的心跳即使在工作区稳定的情况下也会跳过已保存的任务 session 恢复。
-Local data supports the impact:
+本地数据支持这一影响:
-- `timer/system` runs: 6,587 total
-- only 976 had a previous session
-- only 963 ended with the same session
+- `timer/system` 运行次数:共 6,587 次
+- 仅 976 次有前一个 session
+- 仅 963 次以相同的 session 结束
-So timer wakes are the largest heartbeat path and are mostly not resuming prior task state.
+因此,定时器唤醒是最主要的心跳路径,但大多数情况下并未恢复先前的任务状态。
-### 3. We repeatedly ask agents to reload the same task context
+### 3. 我们反复要求 agent 重新加载相同的任务上下文
-The `paperclip` skill currently tells agents to do this on essentially every heartbeat:
+`paperclip` skill 目前在几乎每次心跳时都要求 agent 执行以下操作:
-- fetch assignments
-- fetch issue details
-- fetch ancestor chain
-- fetch full issue comments
+- 获取任务分配
+- 获取 issue 详情
+- 获取祖先链
+- 获取完整的 issue 评论
-Current API shape reinforces that pattern:
+当前 API 的形态强化了这种模式:
-- `GET /api/issues/:id/comments` returns the full thread
-- there is no `since`, cursor, digest, or summary endpoint for heartbeat consumption
-- `GET /api/issues/:id` returns full enriched issue context, not a minimal delta payload
+- `GET /api/issues/:id/comments` 返回完整的评论线程
+- 没有面向心跳消费的 `since`、游标、摘要或汇总端点
+- `GET /api/issues/:id` 返回完整的丰富 issue 上下文,而非最小化的增量负载
-This is safe but expensive. It forces the model to repeatedly consume unchanged information.
+这是安全的,但代价高昂。它迫使模型反复消费未发生变化的信息。
-### 4. Static instruction payloads are not separated cleanly from dynamic heartbeat prompts
+### 4. 静态指令负载与动态心跳提示未被清晰分离
-The user discussion suggested a bootstrap prompt. That is the right direction.
+用户讨论建议使用引导提示(bootstrap prompt),方向是正确的。
-Current state:
+当前状态:
-- the UI exposes `bootstrapPromptTemplate`
-- adapter execution paths do not currently use it
-- several adapters prepend `instructionsFilePath` content directly into the per-run prompt or system prompt
+- UI 暴露了 `bootstrapPromptTemplate`
+- adapter 执行路径目前并未使用它
+- 多个 adapter 直接将 `instructionsFilePath` 内容添加到每次运行的提示或系统提示中
-Result:
+结果:
-- stable instructions are re-sent or re-applied in the same path as dynamic heartbeat content
-- we are not deliberately optimizing for provider prompt caching
+- 稳定指令与动态心跳内容走同一路径被重新发送或重新应用
+- 我们没有刻意针对提供商的提示缓存进行优化
-### 5. We inject more skill surface than most agents need
+### 5. 我们注入的 skill 面超出了大多数 agent 的实际需求
-Local adapters inject repo skills into runtime skill directories.
+本地 adapter 将仓库 skill 注入到运行时 skill 目录中。
-Important `codex_local` nuance:
+关于 `codex_local` 的重要细节:
-- Codex does not read skills directly from the active worktree.
-- Paperclip discovers repo skills from the current checkout, then symlinks them into `$CODEX_HOME/skills` or `~/.codex/skills`.
-- If an existing Paperclip skill symlink already points at another live checkout, the current implementation skips it instead of repointing it.
-- This can leave Codex using stale skill content from a different worktree even after Paperclip-side skill changes land.
-- That is both a correctness risk and a token-analysis risk, because runtime behavior may not reflect the instructions in the checkout being tested.
+- Codex 不会直接从当前工作树读取 skill。
+- Paperclip 从当前检出中发现仓库 skill,然后将其符号链接到 `$CODEX_HOME/skills` 或 `~/.codex/skills`。
+- 如果已有的 Paperclip skill 符号链接指向另一个活跃的检出,当前实现会跳过它,而不是重新指向。
+- 即使 Paperclip 侧的 skill 变更已落地,这也可能导致 Codex 使用来自不同工作树的过期 skill 内容。
+- 这既是正确性风险,也是 token 分析风险,因为运行时行为可能无法反映被测试检出中的指令。
-Current repo skill sizes:
+当前仓库 skill 大小:
-- `skills/paperclip/SKILL.md`: 17,441 bytes
-- `.agents/skills/create-agent-adapter/SKILL.md`: 31,832 bytes
-- `skills/paperclip-create-agent/SKILL.md`: 4,718 bytes
-- `skills/para-memory-files/SKILL.md`: 3,978 bytes
+- `skills/paperclip/SKILL.md`:17,441 字节
+- `.agents/skills/create-agent-adapter/SKILL.md`:31,832 字节
+- `skills/paperclip-create-agent/SKILL.md`:4,718 字节
+- `skills/para-memory-files/SKILL.md`:3,978 字节
-That is nearly 58 KB of skill markdown before any company-specific instructions.
+在任何公司特定指令之前,skill markdown 接近 58 KB。
-Not all of that is necessarily loaded into model context every run, but it increases startup surface area and should be treated as a token budget concern.
+并非所有这些内容都一定在每次运行时加载到模型上下文中,但它增加了启动时的指令面,应视为 token 预算问题。
## Principles
diff --git a/doc/plans/2026-03-13-agent-evals-framework.md b/doc/plans/2026-03-13-agent-evals-framework.md
index 6c4cc55ebb..f2c46bd65a 100644
--- a/doc/plans/2026-03-13-agent-evals-framework.md
+++ b/doc/plans/2026-03-13-agent-evals-framework.md
@@ -1,26 +1,26 @@
-# Agent Evals Framework Plan
+# Agent Evals 框架计划
-Date: 2026-03-13
+日期:2026-03-13
-## Context
+## 背景
-We need evals for the thing Paperclip actually ships:
+我们需要针对 Paperclip 实际交付内容的评估(evals):
-- agent behavior produced by adapter config
-- prompt templates and bootstrap prompts
-- skill sets and skill instructions
-- model choice
-- runtime policy choices that affect outcomes and cost
+- 由 adapter 配置产生的 agent 行为
+- prompt 模板和 bootstrap prompts
+- 技能集与技能指令
+- 模型选择
+- 影响结果和成本的运行时策略选择
-We do **not** primarily need a fine-tuning pipeline.
-We need a regression framework that can answer:
+我们**并不**主要需要微调流水线。
+我们需要一个能回答以下问题的回归测试框架:
-- if we change prompts or skills, do agents still do the right thing?
-- if we switch models, what got better, worse, or more expensive?
-- if we optimize tokens, did we preserve task outcomes?
-- can we grow the suite over time from real Paperclip usage?
+- 如果我们修改 prompts 或技能,agents 是否仍然做正确的事情?
+- 如果我们切换模型,哪些方面变好了、变差了,或者变贵了?
+- 如果我们优化 token 用量,是否保留了任务结果?
+- 我们能否随时间从真实的 Paperclip 使用情况中扩充测试套件?
-This plan is based on:
+本计划基于:
- `doc/GOAL.md`
- `doc/PRODUCT.md`
@@ -33,187 +33,187 @@ This plan is based on:
- LangSmith complex agent eval docs:
- Braintrust dataset/scorer docs: and
-## Recommendation
+## 建议
-Paperclip should take a **two-stage approach**:
+Paperclip 应采取**两阶段方法**:
-1. **Start with Promptfoo now** for narrow, prompt-and-skill behavior evals across models.
-2. **Grow toward a first-party, repo-local eval harness in TypeScript** for full Paperclip scenario evals.
+1. **现在先使用 Promptfoo**,针对跨模型的 prompt 和技能行为进行有针对性的评估。
+2. **逐步发展为 TypeScript 实现的、存储在 repo 内的第一方评估框架**,用于完整的 Paperclip 场景评估。
-So the recommendation is no longer “skip Promptfoo.” It is:
+因此,建议不再是”跳过 Promptfoo”,而是:
-- use Promptfoo as the fastest bootstrap layer
-- keep eval cases and fixtures in this repo
-- avoid making Promptfoo config the deepest long-term abstraction
+- 将 Promptfoo 作为最快的引导层
+- 将评估用例和 fixtures 保留在本 repo 中
+- 避免将 Promptfoo 配置作为最深层的长期抽象
-More specifically:
+更具体地说:
-1. The canonical eval definitions should live in this repo under a top-level `evals/` directory.
-2. `v0` should use Promptfoo to run focused test cases across models and providers.
-3. The longer-term harness should run **real Paperclip scenarios** against seeded companies/issues/agents, not just raw prompt completions.
-4. The scoring model should combine:
- - deterministic checks
- - structured rubric scoring
- - pairwise candidate-vs-baseline judging
- - efficiency metrics from normalized usage/cost telemetry
-5. The framework should compare **bundles**, not just models.
+1. 规范的评估定义应放在本 repo 的顶层 `evals/` 目录下。
+2. `v0` 应使用 Promptfoo 跨模型和 provider 运行有针对性的测试用例。
+3. 长期框架应针对预置的 companies/issues/agents 运行**真实的 Paperclip 场景**,而不仅仅是原始的 prompt completions。
+4. 评分模型应结合:
+ - 确定性检查
+ - 结构化评分标准(rubric scoring)
+ - 候选方案与基线的两两对比评判
+ - 来自标准化使用量/成本遥测的效率指标
+5. 框架应比较 **bundles**,而不仅仅是模型。
-A bundle is:
+一个 bundle 包括:
-- adapter type
+- adapter 类型
- model id
-- prompt template(s)
-- bootstrap prompt template
-- skill allowlist / skill content version
-- relevant runtime flags
+- prompt 模板
+- bootstrap prompt 模板
+- 技能白名单 / 技能内容版本
+- 相关运行时标志
-That is the right unit because that is what actually changes behavior in Paperclip.
+这是正确的比较单元,因为它才是真正改变 Paperclip 行为的内容。
-## Why This Is The Right Shape
+## 为什么这是正确的方向
-### 1. We need to evaluate system behavior, not only prompt output
+### 1. 我们需要评估系统行为,而不仅仅是 prompt 输出
-Prompt-only tools are useful, but Paperclip’s real failure modes are often:
+仅针对 prompt 的工具有其价值,但 Paperclip 真正的失败模式通常是:
-- wrong issue chosen
-- wrong API call sequence
-- bad delegation
-- failure to respect approval boundaries
-- stale session behavior
-- over-reading context
-- claiming completion without producing artifacts or comments
+- 选择了错误的 issue
+- 错误的 API 调用顺序
+- 错误的委派
+- 未能遵守审批边界
+- 过时的 session 行为
+- 过度读取上下文
+- 在未产出 artifacts 或评论的情况下声称已完成
-Those are control-plane behaviors. They require scenario setup, execution, and trace inspection.
+这些都是控制面行为,需要场景设置、执行以及 trace 检查。
-### 2. The repo is already TypeScript-first
+### 2. Repo 已经是 TypeScript 优先
-The existing monorepo already uses:
+现有的 monorepo 已经使用:
- `pnpm`
- `tsx`
- `vitest`
-- TypeScript across server, UI, shared contracts, and adapters
+- 跨 server、UI、共享合约和 adapters 的 TypeScript
-A TypeScript-first harness will fit the repo and CI better than introducing a Python-first test subsystem as the default path.
+相比引入 Python 优先的测试子系统作为默认路径,TypeScript 优先的框架将更好地适配 repo 和 CI。
-Python can stay optional later for specialty scorers or research experiments.
+Python 可在之后作为特殊评分器或研究实验的可选项保留。
-### 3. We need provider/model comparison without vendor lock-in
+### 3. 我们需要不依赖特定厂商的 provider/模型对比
-OpenAI’s guidance is directionally right:
+OpenAI 的指导方向是正确的:
-- eval early and often
-- use task-specific evals
-- log everything
-- prefer pairwise/comparison-style judging over open-ended scoring
+- 尽早且频繁地评估
+- 使用任务特定的评估
+- 记录所有内容
+- 比起开放式评分,优先使用两两对比式评判
-But OpenAI’s Evals API is not the right control plane for Paperclip as the primary system because our target is explicitly multi-model and multi-provider.
+但 OpenAI 的 Evals API 并不适合作为 Paperclip 的主要控制面,因为我们明确的目标是多模型和多 provider。
-### 4. Hosted eval products are useful, and Promptfoo is the right bootstrap tool
+### 4. 托管评估产品有其价值,Promptfoo 是正确的引导工具
-The current tradeoff:
+当前的权衡:
-- Promptfoo is very good for local, repo-based prompt/provider matrices and CI integration.
-- LangSmith is strong on trajectory-style agent evals.
-- Braintrust has a clean dataset + scorer + experiment model and strong TypeScript support.
+- Promptfoo 非常适合本地、基于 repo 的 prompt/provider 矩阵测试以及 CI 集成。
+- LangSmith 在轨迹式 agent 评估方面很强。
+- Braintrust 拥有简洁的 dataset + scorer + experiment 模型,以及强大的 TypeScript 支持。
-The community suggestion is directionally right:
+社区的建议方向是正确的:
-- Promptfoo lets us start small
-- it supports simple assertions like contains / not-contains / regex / custom JS
-- it can run the same cases across multiple models
-- it supports OpenRouter
-- it can move into CI later
+- Promptfoo 让我们可以从小处着手
+- 它支持简单的断言,如 contains / not-contains / regex / custom JS
+- 它可以跨多个模型运行相同的用例
+- 它支持 OpenRouter
+- 之后可以接入 CI
-That makes it the best `v0` tool for “did this prompt/skill/model change obviously regress?”
+这使它成为”这次 prompt/技能/模型变更是否有明显的回归?”这类问题的最佳 `v0` 工具。
-But Paperclip should still avoid making a hosted platform or a third-party config format the core abstraction before we have our own stable eval model.
+但 Paperclip 仍应避免在拥有自己稳定的评估模型之前,将托管平台或第三方配置格式作为核心抽象。
-The right move is:
+正确的做法是:
-- start with Promptfoo for quick wins
-- keep the data portable and repo-owned
-- build a thin first-party harness around Paperclip concepts as the system grows
-- optionally export to or integrate with other tools later if useful
+- 先使用 Promptfoo 获取快速成果
+- 保持数据的可移植性并归属于 repo
+- 随着系统增长,围绕 Paperclip 概念构建一个轻量的第一方框架
+- 之后视需要选择性地导出至其他工具或与其集成
-## What We Should Evaluate
+## 我们应该评估什么
-We should split evals into four layers.
+我们应将评估分为四个层次。
-### Layer 1: Deterministic contract evals
+### 第一层:确定性合约评估
-These should require no judge model.
+这些评估不需要评判模型。
-Examples:
+示例:
-- agent comments on the assigned issue
-- no mutation outside the agent’s company
-- approval-required actions do not bypass approval flow
-- task transitions are legal
-- output contains required structured fields
-- artifact links exist when the task required an artifact
-- no full-thread refetch on delta-only cases once the API supports it
+- agent 对已分配的 issue 发表评论
+- 不在 agent 所属 company 之外进行任何变更
+- 需要审批的操作不绕过审批流程
+- 任务状态转换是合法的
+- 输出包含所需的结构化字段
+- 当任务需要 artifact 时,artifact 链接存在
+- 一旦 API 支持,仅有增量变化的用例不触发全线程重新获取
-These are cheap, reliable, and should be the first line of defense.
+这些检查成本低、可靠性高,应作为第一道防线。
-### Layer 2: Single-step behavior evals
+### 第二层:单步行为评估
-These test narrow behaviors in isolation.
+这些测试在隔离环境中测试具体的行为。
-Examples:
+示例:
-- chooses the correct issue from inbox
-- writes a reasonable first status comment
-- decides to ask for approval instead of acting directly
-- delegates to the correct report
-- recognizes blocked state and reports it clearly
+- 从收件箱中选择正确的 issue
+- 撰写合理的首条状态评论
+- 决定请求审批而非直接行动
+- 委派给正确的下属
+- 识别被阻塞状态并清晰地上报
-These are the closest thing to prompt evals, but still framed in Paperclip terms.
+这些最接近 prompt 评估,但仍以 Paperclip 术语进行描述。
-### Layer 3: End-to-end scenario evals
+### 第三层:端到端场景评估
-These run a full heartbeat or short sequence of heartbeats against a seeded scenario.
+这些针对预置场景运行完整的 heartbeat 或一组短序列 heartbeats。
-Examples:
+示例:
-- new assignment pickup
-- long-thread continuation
-- mention-triggered clarification
-- approval-gated hire request
-- manager escalation
-- workspace coding task that must leave a meaningful issue update
+- 新任务分配接收
+- 长线程的持续跟进
+- 由 @提及 触发的澄清
+- 需要审批把关的招聘请求
+- 向上级经理升级
+- 必须留下有意义的 issue 更新的工作区编码任务
-These should evaluate both final state and trace quality.
+这些评估应同时评估最终状态和 trace 质量。
-### Layer 4: Efficiency and regression evals
+### 第四层:效率与回归评估
-These are not “did the answer look good?” evals. They are “did we preserve quality while improving cost/latency?” evals.
+这些不是”答案看起来好不好?”的评估,而是”在改善成本/延迟的同时是否保持了质量?”的评估。
-Examples:
+示例:
-- normalized input tokens per successful heartbeat
-- normalized tokens per completed issue
-- session reuse rate
-- full-thread reload rate
-- wall-clock duration
-- cost per successful scenario
+- 每次成功 heartbeat 的标准化输入 token 数
+- 每个已完成 issue 的标准化 token 数
+- session 复用率
+- 全线程重载率
+- 实际耗时
+- 每个成功场景的成本
-This layer is especially important for token optimization work.
+这一层对于 token 优化工作尤为重要。
-## Core Design
+## 核心设计
-## 1. Canonical object: `EvalCase`
+## 1. 规范对象:`EvalCase`
-Each eval case should define:
+每个评估用例应定义:
-- scenario setup
-- target bundle(s)
-- execution mode
-- expected invariants
-- scoring rubric
-- tags/metadata
+- 场景设置
+- 目标 bundle(s)
+- 执行模式
+- 预期不变量
+- 评分标准(scoring rubric)
+- 标签/元数据
-Suggested shape:
+建议的数据结构:
```ts
type EvalCase = {
@@ -235,11 +235,11 @@ type EvalCase = {
};
```
-The important part is that the case is about a Paperclip scenario, not a standalone prompt string.
+重要的是,用例关于的是一个 Paperclip 场景,而不是一个独立的 prompt 字符串。
-## 2. Canonical object: `EvalBundle`
+## 2. 规范对象:`EvalBundle`
-Suggested shape:
+建议的数据结构:
```ts
type EvalBundle = {
@@ -253,159 +253,159 @@ type EvalBundle = {
};
```
-Every comparison run should say which bundle was tested.
+每次对比运行都应说明测试了哪个 bundle。
-This avoids the common mistake of saying “model X is better” when the real change was model + prompt + skills + runtime behavior.
+这避免了一个常见错误:说”模型 X 更好”,而实际上真正的变化是模型 + prompt + 技能 + 运行时行为的组合。
-## 3. Canonical output: `EvalTrace`
+## 3. 规范输出:`EvalTrace`
-We should capture a normalized trace for scoring:
+我们应捕获用于评分的标准化 trace:
- run ids
-- prompts actually sent
-- session reuse metadata
-- issue mutations
-- comments created
-- approvals requested
-- artifacts created
-- token/cost telemetry
-- timing
-- raw outputs
+- 实际发送的 prompts
+- session 复用元数据
+- issue 变更
+- 已创建的评论
+- 已请求的审批
+- 已创建的 artifacts
+- token/成本遥测
+- 时序
+- 原始输出
-The scorer layer should never need to scrape ad hoc logs.
+评分层不应需要从临时日志中抓取数据。
-## Scoring Framework
+## 评分框架
-## 1. Hard checks first
+## 1. 硬性检查优先
-Every eval should start with pass/fail checks that can invalidate the run immediately.
+每个评估都应首先进行可以立即使运行失效的通过/失败检查。
-Examples:
+示例:
-- touched wrong company
-- skipped required approval
-- no issue update produced
-- returned malformed structured output
-- marked task done without required artifact
+- 访问了错误的 company
+- 跳过了必要的审批
+- 没有产生 issue 更新
+- 返回了格式错误的结构化输出
+- 在没有所需 artifact 的情况下将任务标记为完成
-If a hard check fails, the scenario fails regardless of style or judge score.
+如果硬性检查失败,则无论风格或评判得分如何,场景均视为失败。
-## 2. Rubric scoring second
+## 2. 其次是评分标准(rubric)评分
-Rubric scoring should use narrow criteria, not vague “how good was this?” prompts.
+评分标准应使用具体明确的标准,而不是模糊的”这有多好?”类 prompts。
-Good rubric dimensions:
+良好的评分维度:
-- task understanding
-- governance compliance
-- useful progress communication
-- correct delegation
-- evidence of completion
-- concision / unnecessary verbosity
+- 任务理解
+- 治理合规
+- 有效的进度沟通
+- 正确的委派
+- 完成证据
+- 简洁性 / 不必要的冗长
-Each rubric should be a small 0-1 or 0-2 decision, not a mushy 1-10 scale.
+每个评分标准应是小范围的 0-1 或 0-2 判断,而不是模糊的 1-10 分制。
-## 3. Pairwise judging for candidate vs baseline
+## 3. 候选方案与基线的两两对比评判
-OpenAI’s eval guidance is right that LLMs are better at discrimination than open-ended generation.
+OpenAI 的评估指导是正确的:LLM 在区分判断方面比开放式生成更强。
-So for non-deterministic quality checks, the default pattern should be:
+因此,对于非确定性的质量检查,默认模式应为:
-- run baseline bundle on the case
-- run candidate bundle on the same case
-- ask a judge model which is better on explicit criteria
-- allow `baseline`, `candidate`, or `tie`
+- 在用例上运行基线 bundle
+- 在相同用例上运行候选 bundle
+- 要求评判模型根据明确标准判断哪个更好
+- 允许 `baseline`、`candidate` 或 `tie`
-This is better than asking a judge for an absolute quality score with no anchor.
+这优于要求评判者给出一个没有参照物的绝对质量分数。
-## 4. Efficiency scoring is separate
+## 4. 效率评分单独处理
-Do not bury efficiency inside a single blended quality score.
+不要将效率埋入单一的综合质量分数中。
-Record it separately:
+单独记录:
-- quality score
-- cost score
-- latency score
+- 质量得分
+- 成本得分
+- 延迟得分
-Then compute a summary decision such as:
+然后计算汇总决策,例如:
-- candidate is acceptable only if quality is non-inferior and efficiency is improved
+- 仅当质量不低于基线且效率有所提升时,候选方案才可接受
-That is much easier to reason about than one magic number.
+这比一个神奇的综合数字更容易推理。
-## Suggested Decision Rule
+## 建议的决策规则
-For PR gating:
+用于 PR 门控:
-1. No hard-check regressions.
-2. No significant regression on required scenario pass rate.
-3. No significant regression on key rubric dimensions.
-4. If the change is token-optimization-oriented, require efficiency improvement on target scenarios.
+1. 无硬性检查回归。
+2. 所需场景通过率无显著回归。
+3. 关键评分维度无显著回归。
+4. 如果变更以 token 优化为导向,则要求目标场景的效率有所提升。
-For deeper comparison reports, show:
+对于更深入的对比报告,应展示:
-- pass rate
-- pairwise wins/losses/ties
-- median normalized tokens
-- median wall-clock time
-- cost deltas
+- 通过率
+- 两两对比的胜/负/平
+- 标准化 token 的中位数
+- 实际耗时的中位数
+- 成本增减情况
-## Dataset Strategy
+## 数据集策略
-We should explicitly build the dataset from three sources.
+我们应明确从三个来源构建数据集。
-### 1. Hand-authored seed cases
+### 1. 手工编写的种子用例
-Start here.
+从这里开始。
-These should cover core product invariants:
+这些用例应覆盖核心产品不变量:
-- assignment pickup
-- status update
-- blocked reporting
-- delegation
-- approval request
-- cross-company access denial
-- issue comment follow-up
+- 任务分配接收
+- 状态更新
+- 阻塞上报
+- 委派
+- 审批请求
+- 跨 company 访问拒绝
+- issue 评论跟进
-These are small, clear, and stable.
+这些用例小巧、明确且稳定。
-### 2. Production-derived cases
+### 2. 来自生产的用例
-Per OpenAI’s guidance, we should log everything and mine real usage for eval cases.
+按照 OpenAI 的指导,我们应记录所有内容,并从真实使用情况中挖掘评估用例。
-Paperclip should grow eval coverage by promoting real runs into cases when we see:
+Paperclip 应通过将真实运行提升为用例来扩展评估覆盖范围,当我们发现以下情况时:
-- regressions
-- interesting failures
-- edge cases
-- high-value success patterns worth preserving
+- 回归
+- 有趣的失败
+- 边界情况
+- 值得保留的高价值成功模式
-The initial version can be manual:
+初始版本可以是手动的:
-- take a real run
-- redact/normalize it
-- convert it into an `EvalCase`
+- 获取一次真实运行
+- 对其进行脱敏/标准化
+- 将其转换为 `EvalCase`
-Later we can automate trace-to-case generation.
+之后我们可以自动化 trace 到用例的生成。
-### 3. Adversarial and guardrail cases
+### 3. 对抗性和防护用例
-These should intentionally probe failure modes:
+这些用例应有意探测失败模式:
-- approval bypass attempts
-- wrong-company references
-- stale context traps
-- irrelevant long threads
-- misleading instructions in comments
-- verbosity traps
+- 尝试绕过审批
+- 引用错误的 company
+- 过时上下文陷阱
+- 无关的长线程
+- 评论中的误导性指令
+- 冗长性陷阱
-This is where promptfoo-style red-team ideas can become useful later, but it is not the first slice.
+这是 promptfoo 风格的红队想法之后可以发挥作用的地方,但不是第一个切片。
-## Repo Layout
+## Repo 目录结构
-Recommended initial layout:
+推荐的初始目录结构:
```text
evals/
@@ -443,59 +443,59 @@ evals/
.gitignore
```
-Why top-level `evals/`:
+为什么选择顶层 `evals/` 目录:
-- it makes evals feel first-class
-- it avoids hiding them inside `server/` even though they span adapters and runtime behavior
-- it leaves room for both TS and optional Python helpers later
-- it gives us a clean place for Promptfoo `v0` config plus the later first-party runner
+- 使评估成为第一优先级
+- 避免将其隐藏在 `server/` 内部,尽管它们跨越了 adapters 和运行时行为
+- 为之后的 TS 和可选的 Python 辅助工具留有空间
+- 为 Promptfoo `v0` 配置以及之后的第一方运行器提供一个清晰的位置
-## Execution Model
+## 执行模型
-The harness should support three modes.
+框架应支持三种模式。
-### Mode A: Cheap local smoke
+### 模式 A:低成本本地冒烟测试
-Purpose:
+目的:
-- run on PRs
-- keep cost low
-- catch obvious regressions
+- 在 PR 上运行
+- 控制成本
+- 捕获明显的回归
-Characteristics:
+特点:
-- 5 to 20 cases
-- 1 or 2 bundles
-- mostly hard checks and narrow rubrics
+- 5 到 20 个用例
+- 1 或 2 个 bundles
+- 主要是硬性检查和具体的评分标准
-### Mode B: Candidate vs baseline compare
+### 模式 B:候选方案与基线对比
-Purpose:
+目的:
-- evaluate a prompt/skill/model change before merge
+- 在合并前评估 prompt/技能/模型变更
-Characteristics:
+特点:
-- paired runs
-- pairwise judging enabled
-- quality + efficiency diff report
+- 配对运行
+- 启用两两对比评判
+- 质量 + 效率差异报告
-### Mode C: Nightly broader matrix
+### 模式 C:夜间更广泛的矩阵测试
-Purpose:
+目的:
-- compare multiple models and bundles
-- grow historical benchmark data
+- 对比多个模型和 bundles
+- 积累历史基准数据
-Characteristics:
+特点:
-- larger case set
-- multiple models
-- more expensive rubric/pairwise judging
+- 更大的用例集
+- 多个模型
+- 更高成本的 rubric/两两对比评判
-## CI and Developer Workflow
+## CI 与开发者工作流
-Suggested commands:
+建议的命令:
```sh
pnpm evals:smoke
@@ -503,200 +503,200 @@ pnpm evals:compare --baseline baseline/codex-default --candidate experiments/cod
pnpm evals:nightly
```
-PR behavior:
+PR 行为:
-- run `evals:smoke` on prompt/skill/adapter/runtime changes
-- optionally trigger `evals:compare` for labeled PRs or manual runs
+- 在 prompt/技能/adapter/运行时变更时运行 `evals:smoke`
+- 对于带标签的 PR 或手动运行,可选触发 `evals:compare`
-Nightly behavior:
+夜间行为:
-- run larger matrix
-- save report artifact
-- surface trend lines on pass rate, pairwise wins, and efficiency
+- 运行更大的矩阵
+- 保存报告产物
+- 呈现通过率、两两对比胜出次数和效率的趋势线
-## Framework Comparison
+## 框架对比
## Promptfoo
-Best use for Paperclip:
+对 Paperclip 的最佳用途:
-- prompt-level micro-evals
-- provider/model comparison
-- quick local CI integration
-- custom JS assertions and custom providers
-- bootstrap-layer evals for one skill or one agent workflow
+- prompt 级别的微型评估
+- provider/模型对比
+- 快速的本地 CI 集成
+- 自定义 JS 断言和自定义 providers
+- 针对单个技能或单个 agent 工作流的引导层评估
-What changed in this recommendation:
+本次建议的变化:
-- Promptfoo is now the recommended **starting point**
-- especially for “one skill, a handful of cases, compare across models”
+- Promptfoo 现在是推荐的**起点**
+- 尤其适用于”一个技能、少量用例、跨模型对比”的场景
-Why it still should not be the only long-term system:
+为什么它仍不应该成为唯一的长期系统:
-- its primary abstraction is still prompt/provider/test-case oriented
-- Paperclip needs scenario setup, control-plane state inspection, and multi-step traces as first-class concepts
+- 其主要抽象仍以 prompt/provider/测试用例为导向
+- Paperclip 需要将场景设置、控制面状态检查和多步骤 traces 作为第一优先级概念
-Recommendation:
+建议:
-- use Promptfoo first
-- store Promptfoo config and cases in-repo under `evals/promptfoo/`
-- use custom JS/TS assertions and, if needed later, a custom provider that calls Paperclip scenario runners
-- do not make Promptfoo YAML the only canonical Paperclip eval format once we outgrow prompt-level evals
+- 先使用 Promptfoo
+- 将 Promptfoo 配置和用例存储在 repo 内的 `evals/promptfoo/` 目录下
+- 使用自定义 JS/TS 断言,如有需要,之后使用调用 Paperclip 场景运行器的自定义 provider
+- 一旦超出 prompt 级别评估的范围,不要将 Promptfoo YAML 作为唯一的规范 Paperclip 评估格式
## LangSmith
-What it gets right:
+做得正确的地方:
-- final response evals
-- trajectory evals
-- single-step evals
+- 最终响应评估
+- 轨迹评估
+- 单步评估
-Why not the primary system today:
+为什么今天不作为主要系统:
-- stronger fit for teams already centered on LangChain/LangGraph
-- introduces hosted/external workflow gravity before our own eval model is stable
+- 更适合已经以 LangChain/LangGraph 为中心的团队
+- 在我们自己的评估模型稳定之前引入了托管/外部工作流的依赖
-Recommendation:
+建议:
-- copy the trajectory/final/single-step taxonomy
-- do not adopt the platform as the default requirement
+- 借鉴其轨迹/最终/单步分类体系
+- 不要将该平台作为默认要求
## Braintrust
-What it gets right:
+做得正确的地方:
-- TypeScript support
-- clean dataset/task/scorer model
-- production logging to datasets
-- experiment comparison over time
+- TypeScript 支持
+- 简洁的 dataset/task/scorer 模型
+- 将生产日志写入数据集
+- 随时间推移的实验对比
-Why not the primary system today:
+为什么今天不作为主要系统:
-- still externalizes the canonical dataset and review workflow
-- we are not yet at the maturity where hosted experiment management should define the shape of the system
+- 仍然将规范数据集和审查工作流外部化
+- 我们尚未成熟到应该由托管实验管理来定义系统形态的阶段
-Recommendation:
+建议:
-- borrow its dataset/scorer/experiment mental model
-- revisit once we want hosted review and experiment history at scale
+- 借鉴其 dataset/scorer/experiment 的心智模型
+- 等到我们需要大规模托管审查和实验历史时再重新评估
## OpenAI Evals / Evals API
-What it gets right:
+做得正确的地方:
-- strong eval principles
-- emphasis on task-specific evals
-- continuous evaluation mindset
+- 强有力的评估原则
+- 强调任务特定的评估
+- 持续评估的思维方式
-Why not the primary system:
+为什么不作为主要系统:
-- Paperclip must compare across models/providers
-- we do not want our primary eval runner coupled to one model vendor
+- Paperclip 必须跨模型/provider 进行对比
+- 我们不希望主要评估运行器与单一模型厂商耦合
-Recommendation:
+建议:
-- use the guidance
-- do not use it as the core Paperclip eval runtime
+- 参考其指导原则
+- 不要将其作为 Paperclip 核心评估运行时
-## First Implementation Slice
+## 首批实现切片
-The first version should be intentionally small.
+第一版应有意保持精简。
-## Phase 0: Promptfoo bootstrap
+## 阶段 0:Promptfoo 引导
-Build:
+构建:
- `evals/promptfoo/promptfooconfig.yaml`
-- 5 to 10 focused cases for one skill or one agent workflow
-- model matrix using the providers we care about most
-- mostly deterministic assertions:
+- 针对一个技能或一个 agent 工作流的 5 到 10 个有针对性的用例
+- 使用我们最关心的 providers 的模型矩阵
+- 主要是确定性断言:
- contains
- not-contains
- regex
- custom JS assertions
-Target scope:
+目标范围:
-- one skill, or one narrow workflow such as assignment pickup / first status update
-- compare a small set of bundles across several models
+- 一个技能,或一个狭窄的工作流(如任务分配接收/首次状态更新)
+- 跨几个模型对比一小组 bundles
-Success criteria:
+成功标准:
-- we can run one command and compare outputs across models
-- prompt/skill regressions become visible quickly
-- the team gets signal before building heavier infrastructure
+- 我们可以运行一条命令并跨模型对比输出
+- prompt/技能回归能快速变得可见
+- 团队在构建更重的基础设施之前获得信号
-## Phase 1: Skeleton and core cases
+## 阶段 1:骨架与核心用例
-Build:
+构建:
-- `evals/` scaffold
-- `EvalCase`, `EvalBundle`, `EvalTrace` types
-- scenario runner for seeded local cases
-- 10 hand-authored core cases
-- hard checks only
+- `evals/` 脚手架
+- `EvalCase`、`EvalBundle`、`EvalTrace` 类型定义
+- 用于预置本地用例的场景运行器
+- 10 个手工编写的核心用例
+- 仅含硬性检查
-Target cases:
+目标用例:
-- assigned issue pickup
-- write progress comment
-- ask for approval when required
-- respect company boundary
-- report blocked state
-- avoid marking done without artifact/comment evidence
+- 已分配 issue 的接收
+- 撰写进度评论
+- 在需要时请求审批
+- 遵守 company 边界
+- 上报阻塞状态
+- 避免在没有 artifact/评论证据的情况下标记为完成
-Success criteria:
+成功标准:
-- a developer can run a local smoke suite
-- prompt/skill changes can fail the suite deterministically
-- Promptfoo `v0` cases either migrate into or coexist with this layer cleanly
+- 开发者可以运行本地冒烟测试套件
+- prompt/技能变更可以确定性地使套件失败
+- Promptfoo `v0` 用例可以干净地迁移到或与此层并存
-## Phase 2: Pairwise and rubric layer
+## 阶段 2:两两对比与评分标准层
-Build:
+构建:
-- rubric scorer interface
-- pairwise judge runner
-- candidate vs baseline compare command
-- markdown/html report output
+- rubric 评分器接口
+- 两两对比评判运行器
+- 候选方案与基线对比命令
+- markdown/html 报告输出
-Success criteria:
+成功标准:
-- model/prompt bundle changes produce a readable diff report
-- we can tell “better”, “worse”, or “same” on curated scenarios
+- 模型/prompt bundle 变更产生可读的差异报告
+- 我们能在精心策划的场景上判断”更好”、”更差”或”相同”
-## Phase 3: Efficiency integration
+## 阶段 3:效率集成
-Build:
+构建:
-- normalized token/cost metrics into eval traces
-- cost and latency comparisons
-- efficiency gates for token optimization work
+- 将标准化 token/成本指标纳入评估 traces
+- 成本和延迟对比
+- 针对 token 优化工作的效率门控
-Dependency:
+依赖:
-- this should align with the telemetry normalization work in `2026-03-13-TOKEN-OPTIMIZATION-PLAN.md`
+- 这应与 `2026-03-13-TOKEN-OPTIMIZATION-PLAN.md` 中的遥测标准化工作对齐
-Success criteria:
+成功标准:
-- quality and efficiency can be judged together
-- token-reduction work no longer relies on anecdotal improvements
+- 质量和效率可以一起评判
+- token 削减工作不再依赖零散的改进记录
-## Phase 4: Production-case ingestion
+## 阶段 4:生产用例摄取
-Build:
+构建:
-- tooling to promote real runs into new eval cases
-- metadata tagging
-- failure corpus growth process
+- 将真实运行提升为新评估用例的工具
+- 元数据标记
+- 失败用例库的增长流程
-Success criteria:
+成功标准:
-- the eval suite grows from real product behavior instead of staying synthetic
+- 评估套件从真实产品行为中增长,而不是停留在合成数据上
-## Initial Case Categories
+## 初始用例分类
-We should start with these categories:
+我们应从以下分类开始:
1. `core.assignment_pickup`
2. `core.progress_update`
@@ -707,69 +707,69 @@ We should start with these categories:
7. `threads.long_context_followup`
8. `efficiency.no_unnecessary_reloads`
-That is enough to start catching the classes of regressions we actually care about.
+这足以开始捕获我们真正关心的各类回归。
-## Important Guardrails
+## 重要防护原则
-### 1. Do not rely on judge models alone
+### 1. 不要仅依赖评判模型
-Every important scenario needs deterministic checks first.
+每个重要场景都需要首先进行确定性检查。
-### 2. Do not gate PRs on a single noisy score
+### 2. 不要用单一嘈杂的分数来管控 PR
-Use pass/fail invariants plus a small number of stable rubric or pairwise checks.
+使用通过/失败不变量加上少量稳定的 rubric 或两两对比检查。
-### 3. Do not confuse benchmark score with product quality
+### 3. 不要将基准分数与产品质量混淆
-The suite must keep growing from real runs, otherwise it will become a toy benchmark.
+测试套件必须持续从真实运行中增长,否则它将变成一个玩具基准。
-### 4. Do not evaluate only final output
+### 4. 不要只评估最终输出
-Trajectory matters for agents:
+轨迹对 agents 很重要:
-- did they call the right Paperclip APIs?
-- did they ask for approval?
-- did they communicate progress?
-- did they choose the right issue?
+- 他们是否调用了正确的 Paperclip APIs?
+- 他们是否请求了审批?
+- 他们是否传达了进度?
+- 他们是否选择了正确的 issue?
-### 5. Do not make the framework vendor-shaped
+### 5. 不要让框架由特定厂商定义
-Our eval model should survive changes in:
+我们的评估模型应能承受以下方面的变化:
-- judge provider
-- candidate provider
-- adapter implementation
-- hosted tooling choices
+- 评判 provider
+- 候选 provider
+- adapter 实现
+- 托管工具选择
-## Open Questions
+## 待解决的问题
-1. Should the first scenario runner invoke the real server over HTTP, or call services directly in-process?
- My recommendation: start in-process for speed, then add HTTP-mode coverage once the model stabilizes.
+1. 第一个场景运行器是否应该通过 HTTP 调用真实服务器,还是直接在进程内调用服务?
+ 我的建议:从进程内调用开始以提高速度,等模型稳定后再添加 HTTP 模式覆盖。
-2. Should we support Python scorers in v1?
- My recommendation: no. Keep v1 all-TypeScript.
+2. 是否应该在 v1 中支持 Python 评分器?
+ 我的建议:不。v1 保持全 TypeScript。
-3. Should we commit baseline outputs?
- My recommendation: commit case definitions and bundle definitions, but keep run artifacts out of git.
+3. 是否应该提交基线输出?
+ 我的建议:提交用例定义和 bundle 定义,但将运行产物排除在 git 之外。
-4. Should we add hosted experiment tracking immediately?
- My recommendation: no. Revisit after the local harness proves useful.
+4. 是否应该立即添加托管实验追踪?
+ 我的建议:不。等本地框架证明有用后再重新评估。
-## Final Recommendation
+## 最终建议
-Start with Promptfoo for immediate, narrow model-and-prompt comparisons, then grow into a first-party `evals/` framework in TypeScript that evaluates **Paperclip scenarios and bundles**, not just prompts.
+先使用 Promptfoo 进行即时的、针对性的模型与 prompt 对比,然后发展为 TypeScript 实现的第一方 `evals/` 框架,用于评估 **Paperclip 场景和 bundles**,而不仅仅是 prompts。
-Use this structure:
+采用以下结构:
-- Promptfoo for `v0` bootstrap
-- deterministic hard checks as the foundation
-- rubric and pairwise judging for non-deterministic quality
-- normalized efficiency metrics as a separate axis
-- repo-local datasets that grow from real runs
+- Promptfoo 用于 `v0` 引导
+- 确定性硬性检查作为基础
+- 用于非确定性质量的 rubric 和两两对比评判
+- 作为独立轴的标准化效率指标
+- 从真实运行中增长的、存储在 repo 内的数据集
-Use external tools selectively:
+选择性地使用外部工具:
-- Promptfoo as the initial path for narrow prompt/provider tests
-- Braintrust or LangSmith later if we want hosted experiment management
+- Promptfoo 作为针对性 prompt/provider 测试的初始路径
+- 如果需要托管实验管理,之后引入 Braintrust 或 LangSmith
-But keep the canonical eval model inside the Paperclip repo and aligned to Paperclip’s actual control-plane behaviors.
+但将规范的评估模型保留在 Paperclip repo 内,并与 Paperclip 实际的控制面行为对齐。
diff --git a/doc/plans/2026-03-13-company-import-export-v2.md b/doc/plans/2026-03-13-company-import-export-v2.md
index bd26890c14..41f835189f 100644
--- a/doc/plans/2026-03-13-company-import-export-v2.md
+++ b/doc/plans/2026-03-13-company-import-export-v2.md
@@ -1,118 +1,118 @@
-# 2026-03-13 Company Import / Export V2 Plan
+# 2026-03-13 公司导入/导出 V2 计划
-Status: Proposed implementation plan
-Date: 2026-03-13
-Audience: Product and engineering
-Supersedes for package-format direction:
-- `doc/plans/2026-02-16-module-system.md` sections that describe company templates as JSON-only
-- `docs/specs/cliphub-plan.md` assumptions about blueprint bundle shape where they conflict with the markdown-first package model
+状态:拟议实施方案
+日期:2026-03-13
+受众:产品与工程团队
+在包格式方向上取代以下文档:
+- `doc/plans/2026-02-16-module-system.md` 中将公司模板描述为仅 JSON 的相关章节
+- `docs/specs/cliphub-plan.md` 中与 markdown 优先包模型冲突的蓝图包结构假设
-## 1. Purpose
+## 1. 目的
-This document defines the next-stage plan for Paperclip company import/export.
+本文档定义 Paperclip 公司导入/导出的下一阶段计划。
-The core shift is:
+核心转变包括:
-- move from a Paperclip-specific JSON-first portability package toward a markdown-first package format
-- make GitHub repositories first-class package sources
-- treat the company package model as an extension of the existing Agent Skills ecosystem instead of inventing a separate skill format
-- support company, team, agent, and skill reuse without requiring a central registry
+- 从 Paperclip 专有的 JSON 优先可移植包转向 markdown 优先包格式
+- 将 GitHub 仓库作为一级包来源
+- 将公司包模型视为现有 Agent Skills 生态的扩展,而非另起炉灶创建独立的 skill 格式
+- 支持公司、团队、agent 及 skill 的复用,无需中央注册中心
-The normative package format draft lives in:
+规范性包格式草案位于:
- `docs/companies/companies-spec.md`
-This plan is about implementation and rollout inside Paperclip.
+本计划涉及 Paperclip 内部的实施与推广工作。
-Adapter-wide skill rollout details live in:
+适配器层面的 skill 推广详情请参见:
- `doc/plans/2026-03-14-adapter-skill-sync-rollout.md`
-## 2. Executive Summary
-
-Paperclip already has portability primitives in the repo:
-
-- server import/export/preview APIs
-- CLI import/export commands
-- shared portability types and validators
-
-Those primitives are being cut over to the new package model rather than extended for backward compatibility.
-
-The new direction is:
-
-1. markdown-first package authoring
-2. GitHub repo or local folder as the default source of truth
-3. a vendor-neutral base package spec for agent-company runtimes, not just Paperclip
-4. the company package model is explicitly an extension of Agent Skills
-5. no future dependency on `paperclip.manifest.json`
-6. implicit folder discovery by convention for the common case
-7. an always-emitted `.paperclip.yaml` sidecar for high-fidelity Paperclip-specific details
-8. package graph resolution at import time
-9. entity-level import UI with dependency-aware tree selection
-10. `skills.sh` compatibility is a V1 requirement for skill packages and skill installation flows
-11. adapter-aware skill sync surfaces so Paperclip can read, diff, enable, disable, and reconcile skills where the adapter supports it
-
-## 3. Product Goals
-
-### 3.1 Goals
-
-- A user can point Paperclip at a local folder or GitHub repo and import a company package without any registry.
-- A package is readable and writable by humans with normal git workflows.
-- A package can contain:
- - company definition
- - org subtree / team definition
- - agent definitions
- - optional starter projects and tasks
- - reusable skills
-- V1 skill support is compatible with the existing `skills.sh` / Agent Skills ecosystem.
-- A user can import into:
- - a new company
- - an existing company
-- Import preview shows:
- - what will be created
- - what will be updated
- - what is skipped
- - what is referenced externally
- - what needs secrets or approvals
-- Export preserves attribution, licensing, and pinned upstream references.
-- Export produces a clean vendor-neutral package plus a Paperclip sidecar.
-- `companies.sh` can later act as a discovery/index layer over repos implementing this format.
-
-### 3.2 Non-Goals
-
-- No central registry is required for package validity.
-- This is not full database backup/restore.
-- This does not attempt to export runtime state like:
- - heartbeat runs
- - API keys
- - spend totals
- - run sessions
- - transient workspaces
-- This does not require a first-class runtime `teams` table before team portability ships.
-
-## 4. Current State In Repo
-
-Current implementation exists here:
-
-- shared types: `packages/shared/src/types/company-portability.ts`
-- shared validators: `packages/shared/src/validators/company-portability.ts`
-- server routes: `server/src/routes/companies.ts`
-- server service: `server/src/services/company-portability.ts`
-- CLI commands: `cli/src/commands/client/company.ts`
-
-Current product limitations:
-
-1. Import/export UX still needs deeper tree-selection and skill/package management polish.
-2. Adapter-specific skill sync remains uneven across adapters and must degrade cleanly when unsupported.
-3. Projects and starter tasks should stay opt-in on export rather than default package content.
-4. Import/export still needs stronger coverage around attribution, pin verification, and executable-package warnings.
-5. The current markdown frontmatter parser is intentionally lightweight and should stay constrained to the documented shape.
-
-## 5. Canonical Package Direction
-
-### 5.1 Canonical Authoring Format
-
-The canonical authoring format becomes a markdown-first package rooted in one of:
+## 2. 执行摘要
+
+Paperclip 代码库中已具备可移植性基础原语:
+
+- 服务端导入/导出/预览 API
+- CLI 导入/导出命令
+- 共享可移植性类型与验证器
+
+这些基础原语将被切换到新包模型,而非为向后兼容性进行扩展。
+
+新方向如下:
+
+1. markdown 优先的包编写方式
+2. GitHub 仓库或本地文件夹作为默认的真实来源
+3. 面向 agent-company 运行时(而非仅限 Paperclip)的厂商中立基础包规范
+4. 公司包模型明确作为 Agent Skills 的扩展
+5. 未来不再依赖 `paperclip.manifest.json`
+6. 针对常见场景按约定进行隐式文件夹发现
+7. 始终生成 `.paperclip.yaml` 附加文件,用于存放高保真的 Paperclip 专有详情
+8. 导入时进行包图谱解析
+9. 支持依赖感知树形选择的实体级导入界面
+10. `skills.sh` 兼容性是 V1 阶段对 skill 包及 skill 安装流程的硬性要求
+11. 适配器感知的 skill 同步界面,使 Paperclip 能在适配器支持时读取、对比、启用、禁用并协调 skill
+
+## 3. 产品目标
+
+### 3.1 目标
+
+- 用户可以将 Paperclip 指向本地文件夹或 GitHub 仓库,无需任何注册中心即可导入公司包。
+- 包可由人工通过普通 git 工作流进行读写。
+- 包可包含以下内容:
+ - 公司定义
+ - 组织子树/团队定义
+ - agent 定义
+ - 可选的初始项目和任务
+ - 可复用的 skill
+- V1 阶段的 skill 支持与现有 `skills.sh` / Agent Skills 生态兼容。
+- 用户可以将内容导入:
+ - 新建公司
+ - 已有公司
+- 导入预览展示:
+ - 将会创建的内容
+ - 将会更新的内容
+ - 将被跳过的内容
+ - 外部引用的内容
+ - 需要密钥或审批的内容
+- 导出保留归因、许可证信息及固定的上游引用。
+- 导出产出一个干净的厂商中立包,以及一个 Paperclip 附加文件。
+- `companies.sh` 未来可作为实现此格式的仓库的发现/索引层。
+
+### 3.2 非目标
+
+- 包的有效性不需要中央注册中心。
+- 这不是完整的数据库备份/恢复方案。
+- 不尝试导出以下运行时状态:
+ - heartbeat 运行记录
+ - API 密钥
+ - 消耗总计
+ - 运行会话
+ - 临时工作空间
+- 在团队可移植性发布之前,不需要优先建立运行时 `teams` 表。
+
+## 4. 代码库现状
+
+当前实现位于以下位置:
+
+- 共享类型:`packages/shared/src/types/company-portability.ts`
+- 共享验证器:`packages/shared/src/validators/company-portability.ts`
+- 服务端路由:`server/src/routes/companies.ts`
+- 服务端服务:`server/src/services/company-portability.ts`
+- CLI 命令:`cli/src/commands/client/company.ts`
+
+当前产品局限性:
+
+1. 导入/导出界面仍需深化树形选择及 skill/包管理的精细度。
+2. 适配器专属 skill 同步在各适配器之间仍不一致,在不支持时必须能优雅降级。
+3. 项目和初始任务在导出时应保持为可选项,而非默认包内容。
+4. 导入/导出在归因、固定验证和可执行包警告方面仍需更强的覆盖。
+5. 当前的 markdown frontmatter 解析器有意保持轻量级,应限制在已记录的结构内。
+
+## 5. 规范包方向
+
+### 5.1 规范编写格式
+
+规范编写格式采用以下文件之一为根的 markdown 优先包:
- `COMPANY.md`
- `TEAM.md`
@@ -121,248 +121,248 @@ The canonical authoring format becomes a markdown-first package rooted in one of
- `TASK.md`
- `SKILL.md`
-The normative draft is:
+规范性草案位于:
- `docs/companies/companies-spec.md`
-### 5.2 Relationship To Agent Skills
+### 5.2 与 Agent Skills 的关系
-Paperclip must not redefine `SKILL.md`.
+Paperclip 不得重新定义 `SKILL.md`。
-Rules:
+规则:
-- `SKILL.md` stays Agent Skills compatible
-- the company package model is an extension of Agent Skills
-- the base package is vendor-neutral and intended for any agent-company runtime
-- Paperclip-specific fidelity lives in `.paperclip.yaml`
-- Paperclip may resolve and install `SKILL.md` packages, but it must not require a Paperclip-only skill format
-- `skills.sh` compatibility is a V1 requirement, not a future nice-to-have
+- `SKILL.md` 保持与 Agent Skills 兼容
+- 公司包模型是 Agent Skills 的扩展
+- 基础包为厂商中立,面向任何 agent-company 运行时
+- Paperclip 专有的高保真内容位于 `.paperclip.yaml`
+- Paperclip 可以解析并安装 `SKILL.md` 包,但不得要求 Paperclip 专有的 skill 格式
+- `skills.sh` 兼容性是 V1 阶段的硬性要求,而非未来可选项
-### 5.3 Agent-To-Skill Association
+### 5.3 Agent 与 Skill 的关联
-`AGENTS.md` should associate skills by skill shortname or slug, not by verbose path in the common case.
+`AGENTS.md` 应通过 skill 短名称或 slug 关联 skill,而非在常见场景中使用冗长路径。
-Preferred example:
+首选示例:
- `skills: [review, react-best-practices]`
-Resolution model:
+解析模型:
-- `review` resolves to `skills/review/SKILL.md` by package convention
-- if the skill is external or referenced, the skill package owns that complexity
-- exporters should prefer shortname-based associations in `AGENTS.md`
-- importers should resolve the shortname against local package skills first, then referenced or installed company skills
-### 5.4 Base Package Vs Paperclip Extension
+- `review` 按包约定解析为 `skills/review/SKILL.md`
+- 如果 skill 是外部引用的,由 skill 包自行处理该复杂性
+- 导出器应在 `AGENTS.md` 中优先使用基于短名称的关联
+- 导入器应优先将短名称解析为本地包中的 skill,然后再解析为已引用或已安装的公司 skill
+### 5.4 基础包与 Paperclip 扩展
-The repo format should have two layers:
+仓库格式应分为两层:
-- base package:
- - minimal, readable, social, vendor-neutral
- - implicit folder discovery by convention
- - no Paperclip-only runtime fields by default
-- Paperclip extension:
+- 基础包:
+ - 最小化、可读、社交友好、厂商中立
+ - 按约定进行隐式文件夹发现
+ - 默认不含 Paperclip 专有的运行时字段
+- Paperclip 扩展:
- `.paperclip.yaml`
- - adapter/runtime/permissions/budget/workspace fidelity
- - emitted by Paperclip tools as a sidecar while the base package stays readable
+ - 适配器/运行时/权限/预算/工作空间高保真信息
+ - 由 Paperclip 工具以附加文件形式生成,同时保持基础包可读
-### 5.5 Relationship To Current V1 Manifest
+### 5.5 与当前 V1 清单的关系
-`paperclip.manifest.json` is not part of the future package direction.
+`paperclip.manifest.json` 不属于未来包方向的一部分。
-This should be treated as a hard cutover in product direction.
+这应被视为产品方向上的硬性切换。
-- markdown-first repo layout is the target
-- no new work should deepen investment in the old manifest model
-- future portability APIs and UI should target the markdown-first model only
+- markdown 优先的仓库结构是目标
+- 不应再对旧清单模型进行新的投入
+- 未来的可移植性 API 和界面应仅面向 markdown 优先模型
-## 6. Package Graph Model
+## 6. 包图谱模型
-### 6.1 Entity Kinds
+### 6.1 实体类型
-Paperclip import/export should support these entity kinds:
+Paperclip 导入/导出应支持以下实体类型:
-- company
-- team
+- company(公司)
+- team(团队)
- agent
-- project
-- task
+- project(项目)
+- task(任务)
- skill
-### 6.2 Team Semantics
+### 6.2 团队语义
-`team` is a package concept first, not a database-table requirement.
+`team` 首先是一个包概念,而非数据库表的要求。
-In Paperclip V2 portability:
+在 Paperclip V2 可移植性中:
-- a team is an importable org subtree
-- it is rooted at a manager agent
-- it can be attached under a target manager in an existing company
+- 团队是一个可导入的组织子树
+- 以一个管理者 agent 为根节点
+- 可以挂载在已有公司的目标管理者节点之下
-This avoids blocking portability on a future runtime `teams` model.
+这避免了在未来运行时 `teams` 模型上阻塞可移植性。
-Imported-team tracking should initially be package/provenance-based:
+导入团队的追踪最初应基于包/来源信息:
-- if a team package was imported, the imported agents should carry enough provenance to reconstruct that grouping
-- Paperclip can treat “this set of agents came from team package X” as the imported-team model
-- provenance grouping is the intended near- and medium-term team model for import/export
-- only add a first-class runtime `teams` table later if product needs move beyond what provenance grouping can express
+- 如果某个团队包已被导入,导入的 agent 应携带足够的来源信息以重建该分组
+- Paperclip 可将”这组 agent 来自团队包 X”作为导入团队模型
+- 来源分组是导入/导出近期和中期的预期团队模型
+- 仅当产品需求超出来源分组所能表达的范围时,才添加一流的运行时 `teams` 表
-### 6.3 Dependency Graph
+### 6.3 依赖图谱
-Import should operate on an entity graph, not raw file selection.
+导入应在实体图谱上操作,而非原始文件选择。
-Examples:
+示例:
-- selecting an agent auto-selects its required docs and skill refs
-- selecting a team auto-selects its subtree
-- selecting a company auto-selects all included entities by default
-- selecting a project auto-selects its starter tasks
+- 选择一个 agent 会自动选中其所需的文档和 skill 引用
+- 选择一个团队会自动选中其子树
+- 选择一个公司默认自动选中所有包含的实体
+- 选择一个项目会自动选中其初始任务
-The preview output should reflect graph resolution explicitly.
+预览输出应明确反映图谱解析结果。
-## 7. External References, Pinning, And Attribution
+## 7. 外部引用、版本固定与归因
-### 7.1 Why This Matters
+### 7.1 重要性
-Some packages will:
+某些包将会:
-- reference upstream files we do not want to republish
-- include third-party work where attribution must remain visible
-- need protection from branch hot-swapping
+- 引用我们不希望重新发布的上游文件
+- 包含必须保持可见归因的第三方作品
+- 需要防范分支热替换
-### 7.2 Policy
+### 7.2 策略
-Paperclip should support source references in package metadata with:
+Paperclip 应在包元数据中支持以下来源引用字段:
-- repo
-- path
+- repo(仓库)
+- path(路径)
- commit sha
-- optional blob sha
-- optional sha256
-- attribution
-- license
-- usage mode
+- 可选的 blob sha
+- 可选的 sha256
+- attribution(归因)
+- license(许可证)
+- usage mode(使用模式)
-Usage modes:
+使用模式:
-- `vendored`
-- `referenced`
-- `mirrored`
+- `vendored`(已内嵌)
+- `referenced`(已引用)
+- `mirrored`(已镜像)
-Default exporter behavior for third-party content should be:
+针对第三方内容的默认导出器行为应为:
-- prefer `referenced`
-- preserve attribution
-- do not silently inline third-party content into exports
+- 优先选择 `referenced`
+- 保留归因信息
+- 不得将第三方内容悄无声息地内联到导出包中
-### 7.3 Trust Model
+### 7.3 信任模型
-Imported package content should be classified by trust level:
+导入的包内容应按信任等级分类:
-- markdown-only
-- markdown + assets
-- markdown + scripts/executables
+- 仅 markdown
+- markdown + 资源文件
+- markdown + 脚本/可执行文件
-The UI and CLI should surface this clearly before apply.
+界面和 CLI 应在应用前清晰展示此信息。
-## 8. Import Behavior
+## 8. 导入行为
-### 8.1 Supported Sources
+### 8.1 支持的来源
-- local folder
-- local package root file
-- GitHub repo URL
-- GitHub subtree URL
-- direct URL to markdown/package root
+- 本地文件夹
+- 本地包根文件
+- GitHub 仓库 URL
+- GitHub 子树 URL
+- 直接指向 markdown/包根的 URL
-Registry-based discovery may be added later, but must remain optional.
+基于注册中心的发现功能可在后续添加,但必须保持可选。
-### 8.2 Import Targets
+### 8.2 导入目标
-- new company
-- existing company
+- 新建公司
+- 已有公司
-For existing company imports, the preview must support:
+对于导入到已有公司的情况,预览界面必须支持:
-- collision handling
-- attach-point selection for team imports
-- selective entity import
+- 冲突处理
+- 团队导入的挂载点选择
+- 选择性实体导入
-### 8.3 Collision Strategy
+### 8.3 冲突策略
-Current `rename | skip | replace` support remains, but matching should improve over time.
+当前的 `rename | skip | replace` 支持保留,但匹配逻辑应随时间持续改进。
-Preferred matching order:
+首选匹配顺序:
-1. prior install provenance
-2. stable package entity identity
+1. 先前安装的来源信息
+2. 稳定的包实体标识
3. slug
-4. human name as weak fallback
+4. 人类可读名称作为弱回退
-Slug-only matching is acceptable only as a transitional strategy.
+仅使用 slug 匹配仅作为过渡策略可接受。
-### 8.4 Required Preview Output
+### 8.4 必需的预览输出
-Every import preview should surface:
+每次导入预览应展示:
-- target company action
-- entity-level create/update/skip plan
-- referenced external content
-- missing files
-- hash mismatch or pinning issues
-- env inputs, including required vs optional and default values when present
-- unsupported content types
-- trust/licensing warnings
+- 目标公司操作
+- 实体级创建/更新/跳过计划
+- 引用的外部内容
+- 缺失文件
+- 哈希不匹配或版本固定问题
+- 环境变量输入,包括必填项与可选项,以及存在时的默认值
+- 不支持的内容类型
+- 信任/许可证警告
-### 8.5 Adapter Skill Sync Surface
+### 8.5 适配器 Skill 同步界面
-People want skill management in the UI, but skills are adapter-dependent.
+用户希望在界面中管理 skill,但 skill 依赖于适配器。
-That means portability and UI planning must include an adapter capability model for skills.
+这意味着可移植性和界面规划必须包含适配器能力模型。
-Paperclip should define a new adapter surface area around skills:
+Paperclip 应围绕 skill 定义新的适配器接口范围:
-- list currently enabled skills for an agent
-- report how those skills are represented by the adapter
-- install or enable a skill
-- disable or remove a skill
-- report sync state between desired package config and actual adapter state
+- 列出 agent 当前已启用的 skill
+- 报告适配器如何表示这些 skill
+- 安装或启用某个 skill
+- 禁用或移除某个 skill
+- 报告期望包配置与实际适配器状态之间的同步状态
-Examples:
+示例:
-- Claude Code / Codex style adapters may manage skills as local filesystem packages or adapter-owned skill directories
-- OpenClaw-style adapters may expose currently enabled skills through an API or a reflected config surface
-- some adapters may be read-only and only report what they have
+- Claude Code / Codex 风格的适配器可能将 skill 作为本地文件系统包或适配器自有的 skill 目录进行管理
+- OpenClaw 风格的适配器可能通过 API 或反射配置界面暴露当前已启用的 skill
+- 某些适配器可能是只读的,仅报告其所拥有的内容
-Planned adapter capability shape:
+规划中的适配器能力字段:
- `supportsSkillRead`
- `supportsSkillWrite`
- `supportsSkillRemove`
- `supportsSkillSync`
-- `skillStorageKind` such as `filesystem`, `remote_api`, `inline_config`, or `unknown`
+- `skillStorageKind`,如 `filesystem`、`remote_api`、`inline_config` 或 `unknown`
-Baseline adapter interface:
+基础适配器接口:
- `listSkills(agent)`
- `applySkills(agent, desiredSkills)`
-- `removeSkill(agent, skillId)` optional
-- `getSkillSyncState(agent, desiredSkills)` optional
+- `removeSkill(agent, skillId)` 可选
+- `getSkillSyncState(agent, desiredSkills)` 可选
-Planned Paperclip behavior:
+规划中的 Paperclip 行为:
-- if an adapter supports read, Paperclip should show current skills in the UI
-- if an adapter supports write, Paperclip should let the user enable/disable imported skills
-- if an adapter supports sync, Paperclip should compute desired vs actual state and offer reconcile actions
-- if an adapter does not support these capabilities, the UI should still show the package-level desired skills but mark them unmanaged
+- 如果适配器支持读取,Paperclip 应在界面中展示当前 skill
+- 如果适配器支持写入,Paperclip 应允许用户启用/禁用已导入的 skill
+- 如果适配器支持同步,Paperclip 应计算期望状态与实际状态之间的差异并提供协调操作
+- 如果适配器不支持这些能力,界面仍应展示包级别的期望 skill,但标记为未托管
-## 9. Export Behavior
+## 9. 导出行为
-### 9.1 Default Export Target
+### 9.1 默认导出目标
-Default export target should become a markdown-first folder structure.
+默认导出目标应改为 markdown 优先的文件夹结构。
-Example:
+示例:
```text
my-company/
@@ -372,69 +372,69 @@ my-company/
└── skills/
```
-### 9.2 Export Rules
+### 9.2 导出规则
-Exports should:
+导出应:
-- omit machine-local ids
-- omit timestamps and counters unless explicitly needed
-- omit secret values
-- omit local absolute paths
-- omit duplicated inline prompt content from `.paperclip.yaml` when `AGENTS.md` already carries the instructions
-- preserve references and attribution
-- emit `.paperclip.yaml` alongside the base package
-- express adapter env/secrets as portable env input declarations rather than exported secret binding ids
-- preserve compatible `SKILL.md` content as-is
+- 省略机器本地 ID
+- 省略时间戳和计数器,除非明确需要
+- 省略密钥值
+- 省略本地绝对路径
+- 当 `AGENTS.md` 已包含指令时,省略 `.paperclip.yaml` 中重复的内联提示内容
+- 保留引用和归因信息
+- 在基础包旁生成 `.paperclip.yaml`
+- 将适配器环境变量/密钥表达为可移植的环境变量输入声明,而非导出的密钥绑定 ID
+- 原样保留兼容的 `SKILL.md` 内容
-Projects and issues should not be exported by default.
+项目和议题默认不应导出。
-They should be opt-in through selectors such as:
+应通过如下选择器将其设为可选项:
- `--projects project-shortname-1,project-shortname-2`
- `--issues PAP-1,PAP-3`
- `--project-issues project-shortname-1,project-shortname-2`
-This supports “clean public company package” workflows where a maintainer exports a follower-facing company package without bundling active work items every time.
+这支持”干净的公开公司包”工作流,维护者可以在每次导出面向关注者的公司包时不捆绑当前活跃的工作项。
-### 9.3 Export Units
+### 9.3 导出单元
-Initial export units:
+初始导出单元:
-- company package
-- team package
-- single agent package
+- 公司包
+- 团队包
+- 单个 agent 包
-Later optional units:
+后续可选单元:
-- skill pack export
-- seed projects/tasks bundle
+- skill 包导出
+- 种子项目/任务包
-## 10. Storage Model Inside Paperclip
+## 10. Paperclip 内部存储模型
-### 10.1 Short-Term
+### 10.1 短期方案
-In the first phase, imported entities can continue mapping onto current runtime tables:
+在第一阶段,导入的实体可以继续映射到当前运行时表:
- company -> companies
- agent -> agents
-- team -> imported agent subtree attachment plus package provenance grouping
-- skill -> company-scoped reusable package metadata plus agent-scoped desired-skill attachment state where supported
+- team -> 导入的 agent 子树挂载加包来源分组
+- skill -> 公司级可复用包元数据,加上在支持的情况下的 agent 级期望 skill 挂载状态
-### 10.2 Medium-Term
+### 10.2 中期方案
-Paperclip should add managed package/provenance records so imports are not anonymous one-off copies.
+Paperclip 应添加托管的包/来源记录,使导入不再是匿名的一次性副本。
-Needed capabilities:
+所需能力:
-- remember install origin
-- support re-import / upgrade
-- distinguish local edits from upstream package state
-- preserve external refs and package-level metadata
-- preserve imported team grouping without requiring a runtime `teams` table immediately
-- preserve desired-skill state separately from adapter runtime state
-- support both company-scoped reusable skills and agent-scoped skill attachments
+- 记住安装来源
+- 支持重新导入/升级
+- 区分本地编辑与上游包状态
+- 保留外部引用和包级元数据
+- 在无需立即建立运行时 `teams` 表的情况下保留导入团队分组
+- 将期望 skill 状态与适配器运行时状态分开保存
+- 同时支持公司级可复用 skill 和 agent 级 skill 挂载
-Suggested future tables:
+建议的未来数据表:
- package_installs
- package_install_entities
@@ -442,203 +442,203 @@ Suggested future tables:
- agent_skill_desires
- adapter_skill_snapshots
-This is not required for phase 1 UI, but it is required for a robust long-term system.
+这不是第一阶段界面的必要条件,但对于健壮的长期系统是必需的。
-## 11. API Plan
+## 11. API 计划
-### 11.1 Keep Existing Endpoints Initially
+### 11.1 初期保留现有端点
-Retain:
+保留:
- `POST /api/companies/:companyId/export`
- `POST /api/companies/import/preview`
- `POST /api/companies/import`
-But evolve payloads toward the markdown-first graph model.
+但将请求载荷逐步演进为 markdown 优先的图谱模型。
-### 11.2 New API Capabilities
+### 11.2 新 API 能力
-Add support for:
+新增对以下功能的支持:
-- package root resolution from local/GitHub inputs
-- graph resolution preview
-- source pin and hash verification results
-- entity-level selection
-- team attach target selection
-- provenance-aware collision planning
+- 从本地/GitHub 输入进行包根解析
+- 图谱解析预览
+- 来源固定版本和哈希验证结果
+- 实体级选择
+- 团队挂载目标选择
+- 来源感知的冲突规划
-### 11.3 Parsing Changes
+### 11.3 解析变更
-Replace the current ad hoc markdown frontmatter parser with a real parser that can handle:
+将当前的临时 markdown frontmatter 解析器替换为能处理以下内容的真正解析器:
-- nested YAML
-- arrays/objects reliably
-- consistent round-tripping
+- 嵌套 YAML
+- 可靠的数组/对象处理
+- 一致的往返转换
-This is a prerequisite for the new package model.
+这是新包模型的前置条件。
-## 12. CLI Plan
+## 12. CLI 计划
-The CLI should continue to support direct import/export without a registry.
+CLI 应继续支持无需注册中心的直接导入/导出。
-Target commands:
+目标命令:
- `paperclipai company export --out `
- `paperclipai company import --dry-run`
- `paperclipai company import --target existing -C `
-Planned additions:
+规划中的新增参数:
- `--package-kind company|team|agent`
-- `--attach-under ` for team imports
+- `--attach-under `,用于团队导入
- `--strict-pins`
- `--allow-unpinned`
- `--materialize-references`
- `--sync-skills`
-## 13. UI Plan
+## 13. 界面计划
-### 13.1 Company Settings Import / Export
+### 13.1 公司设置的导入/导出
-Add a real import/export section to Company Settings.
+在公司设置中添加完整的导入/导出区块。
-Export UI:
+导出界面:
-- export package kind selector
-- include options
-- local download/export destination guidance
-- attribution/reference summary
+- 导出包类型选择器
+- 包含选项
+- 本地下载/导出目标位置说明
+- 归因/引用摘要
-Import UI:
+导入界面:
-- source entry:
- - upload/folder where supported
+- 来源输入:
+ - 在支持的情况下上传/选择文件夹
- GitHub URL
- - generic URL
-- preview pane with:
- - resolved package root
- - dependency tree
- - checkboxes by entity
- - trust/licensing warnings
- - secrets requirements
- - collision plan
+ - 通用 URL
+- 预览面板,包含:
+ - 已解析的包根
+ - 依赖树
+ - 按实体的复选框
+ - 信任/许可证警告
+ - 密钥要求
+ - 冲突规划
-### 13.2 Team Import UX
+### 13.2 团队导入体验
-If importing a team into an existing company:
+将团队导入已有公司时:
-- show the subtree structure
-- require the user to choose where to attach it
-- preview manager/reporting updates before apply
-- preserve imported-team provenance so the UI can later say “these agents came from team package X”
+- 展示子树结构
+- 要求用户选择挂载位置
+- 在应用前预览管理者/汇报关系变更
+- 保留导入团队的来源信息,以便界面后续可以显示”这些 agent 来自团队包 X”
-### 13.3 Skills UX
+### 13.3 Skill 体验
-See also:
+另请参见:
- `doc/plans/2026-03-14-skills-ui-product-plan.md`
-If importing skills:
+导入 skill 时:
-- show whether each skill is local, vendored, or referenced
-- show whether it contains scripts/assets
-- preserve Agent Skills compatibility in presentation and export
-- preserve `skills.sh` compatibility in both import and install flows
-- show agent skill attachments by shortname/slug rather than noisy file paths
-- treat agent skills as a dedicated agent tab, not just another subsection of configuration
-- show current adapter-reported skills when supported
-- show desired package skills separately from actual adapter state
-- offer reconcile actions when the adapter supports sync
+- 展示每个 skill 是本地的、已内嵌的还是已引用的
+- 展示是否包含脚本/资源文件
+- 在展示和导出中保持 Agent Skills 兼容性
+- 在导入和安装流程中均保持 `skills.sh` 兼容性
+- 以短名称/slug 而非冗长文件路径展示 agent skill 挂载情况
+- 将 agent skill 视为专属的 agent 标签页,而非配置中的一个子章节
+- 在支持的情况下展示适配器当前报告的 skill
+- 将期望的包 skill 与实际适配器状态分开展示
+- 在适配器支持同步时提供协调操作
-## 14. Rollout Phases
+## 14. 推广阶段
-### Phase 1: Stabilize Current V1 Portability
+### 第一阶段:稳定当前 V1 可移植性
-- add tests for current portability flows
-- replace the frontmatter parser
-- add Company Settings UI for current import/export capabilities
-- start cutover work toward the markdown-first package reader
+- 为当前可移植性流程添加测试
+- 替换 frontmatter 解析器
+- 为当前导入/导出功能添加公司设置界面
+- 启动向 markdown 优先包读取器的切换工作
-### Phase 2: Markdown-First Package Reader
+### 第二阶段:Markdown 优先包读取器
-- support `COMPANY.md` / `TEAM.md` / `AGENTS.md` root detection
-- build internal graph from markdown-first packages
-- support local folder and GitHub repo inputs natively
-- support agent skill references by shortname/slug
-- resolve local `skills//SKILL.md` packages by convention
-- support `skills.sh`-compatible skill repos as V1 package sources
+- 支持 `COMPANY.md` / `TEAM.md` / `AGENTS.md` 根节点检测
+- 从 markdown 优先包构建内部图谱
+- 原生支持本地文件夹和 GitHub 仓库输入
+- 支持通过短名称/slug 引用 agent skill
+- 按约定解析本地 `skills//SKILL.md` 包
+- 支持 `skills.sh` 兼容的 skill 仓库作为 V1 包来源
-### Phase 3: Graph-Based Import UX And Skill Surfaces
+### 第三阶段:基于图谱的导入界面与 Skill 界面
-- entity tree preview
-- checkbox selection
-- team subtree attach flow
-- licensing/trust/reference warnings
-- company skill library groundwork
-- dedicated agent `Skills` tab groundwork
-- adapter skill read/sync UI groundwork
+- 实体树预览
+- 复选框选择
+- 团队子树挂载流程
+- 许可证/信任/引用警告
+- 公司 skill 库基础建设
+- 专属 agent `Skills` 标签页基础建设
+- 适配器 skill 读取/同步界面基础建设
-### Phase 4: New Export Model
+### 第四阶段:新导出模型
-- export markdown-first folder structure by default
+- 默认导出 markdown 优先的文件夹结构
-### Phase 5: Provenance And Upgrades
+### 第五阶段:来源追踪与升级
-- persist install provenance
-- support package-aware re-import and upgrades
-- improve collision matching beyond slug-only
-- add imported-team provenance grouping
-- add desired-vs-actual skill sync state
+- 持久化安装来源信息
+- 支持包感知的重新导入和升级
+- 改进超越纯 slug 匹配的冲突匹配
+- 添加导入团队的来源分组
+- 添加期望状态与实际状态的 skill 同步状态
-### Phase 6: Optional Seed Content
+### 第六阶段:可选种子内容
-- goals
-- projects
-- starter issues/tasks
+- 目标
+- 项目
+- 初始议题/任务
-This phase is intentionally after the structural model is stable.
+此阶段有意安排在结构模型稳定之后。
-## 15. Documentation Plan
+## 15. 文档计划
-Primary docs:
+主要文档:
-- `docs/companies/companies-spec.md` as the package-format draft
-- this implementation plan for rollout sequencing
+- `docs/companies/companies-spec.md`,作为包格式草案
+- 本实施计划,用于推广排期
-Docs to update later as implementation lands:
+待实施落地后更新的文档:
- `doc/SPEC-implementation.md`
- `docs/api/companies.md`
- `docs/cli/control-plane-commands.md`
-- board operator docs for Company Settings import/export
+- 公司设置导入/导出的看板操作员文档
-## 16. Open Questions
+## 16. 待解决问题
-1. Should imported skill packages be stored as managed package files in Paperclip storage, or only referenced at import time?
- Decision: managed package files should support both company-scoped reuse and agent-scoped attachment.
-2. What is the minimum adapter skill interface needed to make the UI useful across Claude Code, Codex, OpenClaw, and future adapters?
- Decision: use the baseline interface in section 8.5.
-3. Should Paperclip support direct local folder selection in the web UI, or keep that CLI-only initially?
-4. Do we want optional generated lock files in phase 2, or defer them until provenance work?
-5. How strict should pinning be by default for GitHub references:
- - warn on unpinned
- - or block in normal mode
-6. Is package-provenance grouping enough for imported teams, or do we expect product requirements soon that would justify a first-class runtime `teams` table?
- Decision: provenance grouping is enough for the import/export product model for now.
+1. 导入的 skill 包应作为托管包文件存储在 Paperclip 存储中,还是仅在导入时引用?
+ 决策:托管包文件应同时支持公司级复用和 agent 级挂载。
+2. 为使界面在 Claude Code、Codex、OpenClaw 及未来适配器中均可用,所需的最小适配器 skill 接口是什么?
+ 决策:使用第 8.5 节中的基础接口。
+3. Paperclip 是否应在 Web 界面中支持直接选择本地文件夹,还是初期仅保留在 CLI 中?
+4. 是否希望在第二阶段生成可选的锁文件,还是推迟到来源追踪工作时再处理?
+5. GitHub 引用默认的固定版本策略应多严格:
+ - 对未固定版本发出警告
+ - 还是在正常模式下阻止
+6. 包来源分组对于导入团队是否已足够,或者预计很快会有产品需求来支撑建立一流的运行时 `teams` 表?
+ 决策:来源分组对于当前的导入/导出产品模型已足够。
-## 17. Recommendation
+## 17. 建议
-Engineering should treat this as the current plan of record for company import/export beyond the existing V1 portability feature.
+工程团队应将本文档视为超越现有 V1 可移植性功能的公司导入/导出当前记录方案。
-Immediate next steps:
+立即可行的后续步骤:
-1. accept `docs/companies/companies-spec.md` as the package-format draft
-2. implement phase 1 stabilization work
-3. build phase 2 markdown-first package reader before expanding ClipHub or `companies.sh`
-4. treat the old manifest-based format as deprecated and not part of the future surface
+1. 接受 `docs/companies/companies-spec.md` 作为包格式草案
+2. 实施第一阶段稳定化工作
+3. 在扩展 ClipHub 或 `companies.sh` 之前构建第二阶段的 markdown 优先包读取器
+4. 将旧的基于清单的格式视为已弃用,不纳入未来方案范围
-This keeps Paperclip aligned with:
+这使 Paperclip 与以下方向保持一致:
-- GitHub-native distribution
-- Agent Skills compatibility
-- a registry-optional ecosystem model
+- GitHub 原生分发
+- Agent Skills 兼容性
+- 注册中心可选的生态系统模型
diff --git a/doc/plans/2026-03-13-features.md b/doc/plans/2026-03-13-features.md
index 80c60a8754..0299641c1f 100644
--- a/doc/plans/2026-03-13-features.md
+++ b/doc/plans/2026-03-13-features.md
@@ -1,30 +1,30 @@
-# Feature specs
+# 功能规格说明
-## 1) Guided onboarding + first-job magic
+## 1) 引导式初始化 + 首次任务魔法
-The repo already has `onboard`, `doctor`, `run`, deployment modes, and even agent-oriented onboarding text/skills endpoints, but there are also current onboarding/auth validation issues and an open “onboard failed” report. That means this is not just polish; it is product-critical. ([GitHub][1])
+代码仓库已有 `onboard`、`doctor`、`run`、部署模式,甚至面向 Agent 的初始化文本和 skills 端点,但当前也存在初始化/认证校验问题及一份未解决的”onboard failed”报告。这意味着此项工作不只是界面打磨,而是产品核心问题。([GitHub][1])
-### Product decision
+### 产品决策
-Replace “configuration-first onboarding” with **interview-first onboarding**.
+将”配置优先的初始化”替换为**问答优先的初始化**。
-### What we want
+### 期望效果
-- Ask 3–4 questions up front, not 20 settings.
-- Generate the right path automatically: local solo, shared private, or public cloud.
-- Detect what agent/runtime environment already exists.
-- Make it normal to have Claude/OpenClaw/Codex help complete setup.
-- End onboarding with a **real first task**, not a blank dashboard.
+- 前置询问 3–4 个问题,而非 20 项配置。
+- 自动生成正确路径:本地单人、私有共享或公共云。
+- 检测已存在的 Agent/运行时环境。
+- 将 Claude/OpenClaw/Codex 协助完成配置视为常态。
+- 初始化结束时提供**真实的第一个任务**,而非空白仪表盘。
-### What we do not want
+### 不希望出现的情况
-- Provider jargon before value.
-- “Go find an API key” as the default first instruction.
-- A successful install that still leaves users unsure what to do next.
+- 在展示价值之前先堆砌服务商术语。
+- 将”去找 API key”作为默认的第一条指引。
+- 安装成功后用户仍不知道下一步该做什么。
-### Proposed UX
+### 建议的用户体验
-On first run, show an interview:
+首次运行时,展示一组问答:
```ts
type OnboardingProfile = {
@@ -36,154 +36,154 @@ type OnboardingProfile = {
};
```
-Questions:
+问题列表:
-1. What are you building?
-2. Is this a new company, an existing company, or a service/agency team?
-3. Are you working solo on one machine, sharing privately with a team, or deploying publicly?
-4. Do you want full auto, hybrid, or tight manual control?
+1. 你在构建什么?
+2. 这是新公司、现有公司,还是服务/代理团队?
+3. 你是在单台机器上独立工作、与团队私有共享,还是公开部署?
+4. 你希望全自动、混合模式,还是严格的手动控制?
-Then Paperclip should:
+然后 Paperclip 应当:
-- detect installed CLIs/providers/subscriptions
-- recommend the matching deployment/auth mode
-- generate a local `onboarding.txt` / LLM handoff prompt
-- offer a button: **“Open this in Claude / copy setup prompt”**
-- create starter objects:
+- 检测已安装的 CLI/服务商/订阅
+- 推荐匹配的部署/认证模式
+- 生成本地 `onboarding.txt` / LLM 移交提示词
+- 提供一个按钮:**”在 Claude 中打开 / 复制配置提示词”**
+- 创建初始对象:
- - company
- - company goal
+ - company(公司)
+ - company goal(公司目标)
- CEO
- - founding engineer or equivalent first report
- - first suggested task
+ - founding engineer 或同等级别的第一位下属
+ - 第一个建议任务
-### Backend / API
+### 后端 / API
-- Add `GET /api/onboarding/recommendation`
-- Add `GET /api/onboarding/llm-handoff.txt`
-- Reuse existing invite/onboarding/skills patterns for local-first bootstrap
-- Persist onboarding answers into instance config for later defaults
+- 添加 `GET /api/onboarding/recommendation`
+- 添加 `GET /api/onboarding/llm-handoff.txt`
+- 复用现有的 invite/onboarding/skills 模式实现本地优先的引导启动
+- 将初始化问答答案持久化到实例配置中,供后续默认值使用
-### Acceptance criteria
+### 验收标准
-- Fresh install with a supported local runtime completes without manual JSON/env editing.
-- User sees first live agent action before leaving onboarding.
-- A blank dashboard is no longer the default post-install state.
-- If a required dependency is missing, the error is prescriptive and fixable from the UI/CLI.
+- 在支持的本地运行时环境中全新安装,无需手动编辑 JSON/env 文件即可完成。
+- 用户在离开初始化流程前能看到第一个 Agent 的实时动作。
+- 安装后默认不再是空白仪表盘。
+- 若缺少必要依赖,错误提示应具体且可通过 UI/CLI 修复。
-### Non-goals
+### 非目标
-- Account creation
-- enterprise SSO
-- perfect provider auto-detection for every runtime
+- 账号注册
+- 企业 SSO
+- 对每种运行时的完美服务商自动检测
---
-## 2) Board command surface, not generic chat
+## 2) 董事会指令界面,而非通用聊天
-There is a real tension here: the transcript says users want “chat with my CEO,” while the public product definition says Paperclip is **not a chatbot** and V1 communication is **tasks + comments only**. At the same time, the repo is already exploring plugin infrastructure and even a chat plugin via plugin SSE streaming. The clean resolution is: **make the core surface conversational, but keep the data model task/thread-centric; reserve full chat as an optional plugin**. ([GitHub][2])
+这里存在真实的张力:记录稿显示用户希望”与 CEO 对话”,而公开的产品定义说 Paperclip **不是聊天机器人**,V1 的沟通方式**仅限任务 + 评论**。与此同时,代码仓库已在探索插件基础设施,甚至通过插件 SSE 流式传输实现聊天插件。清晰的解决方案是:**让核心界面具备对话感,但保持数据模型以任务/线程为中心;将完整聊天功能保留为可选插件**。([GitHub][2])
-### Product decision
+### 产品决策
-Build a **Command Composer** backed by issues/comments/approvals, not a separate chat subsystem.
+构建一个基于 issues/评论/审批的**指令编辑器(Command Composer)**,而非独立的聊天子系统。
-### What we want
+### 期望效果
-- “Talk to the CEO” feeling for the user.
-- Every conversation ends up attached to a real company object.
-- Strategy discussion can produce issues, artifacts, and approvals.
+- 给用户带来”与 CEO 对话”的感觉。
+- 每次对话都关联到真实的公司对象。
+- 战略讨论可以产出 issues、产物和审批。
-### What we do not want
+### 不希望出现的情况
-- A blank “chat with AI” home screen disconnected from the org.
-- Yet another agent-chat product.
+- 与组织架构脱节的空白”与 AI 聊天”首页。
+- 又一个 Agent 聊天产品。
-### Proposed UX
+### 建议的用户体验
-Add a global composer with modes:
+添加一个全局编辑器,支持以下模式:
```ts
type ComposerMode = "ask" | "task" | "decision";
type ThreadScope = "company" | "project" | "issue" | "agent";
```
-Examples:
+示例:
-- On dashboard: “Ask the CEO for a hiring plan” → creates a `strategy` issue/thread scoped to the company.
-- On agent page: “Tell the designer to make this cleaner” → appends an instruction comment to an issue or spawns a new delegated task.
-- On approval page: “Why are you asking to hire?” → appends a board comment to the approval context.
+- 在仪表盘:「向 CEO 请求招聘计划」→ 创建一个以公司为范围的 `strategy` issue/线程。
+- 在 Agent 页面:「告诉设计师让这个更简洁」→ 向 issue 追加一条指令评论,或生成一个新的委派任务。
+- 在审批页面:「你为什么要求招人?」→ 向审批上下文追加一条董事会评论。
-Add issue kinds:
+添加 issue 类型:
```ts
type IssueKind = "task" | "strategy" | "question" | "decision";
```
-### Backend / data model
+### 后端 / 数据模型
-Prefer extending existing `issues` rather than creating `chats`:
+优先扩展现有的 `issues`,而非新建 `chats`:
- `issues.kind`
- `issues.scope`
-- optional `issues.target_agent_id`
-- comment metadata: `comment.intent = hint | correction | board_question | board_decision`
+- 可选的 `issues.target_agent_id`
+- 评论元数据:`comment.intent = hint | correction | board_question | board_decision`
-### Acceptance criteria
+### 验收标准
-- A user can “ask CEO” from the dashboard and receive a response in a company-scoped thread.
-- From that thread, the user can create/approve tasks with one click.
-- No separate chat database is required for v1 of this feature.
+- 用户可以从仪表盘”询问 CEO”,并在公司范围的线程中收到回复。
+- 在该线程中,用户可以一键创建/审批任务。
+- 该功能的 v1 版本无需独立的聊天数据库。
-### Non-goals
+### 非目标
-- consumer chat UX
-- model marketplace
-- general-purpose assistant unrelated to company context
+- 消费者聊天体验
+- 模型市场
+- 与公司上下文无关的通用助手
---
-## 3) Live org visibility + explainability layer
+## 3) 实时组织可见性 + 可解释性层
-The core product promise is already visibility and governance, but right now the transcript makes clear that the UI is still too close to raw agent execution. The repo already has org charts, activity, heartbeat runs, costs, and agent detail surfaces; the missing piece is the explanatory layer above them. ([GitHub][1])
+核心产品承诺已是可见性和治理,但当前记录稿清楚地表明 UI 仍过于贴近原始 Agent 执行层。代码仓库已有组织架构图、活动记录、心跳运行、成本和 Agent 详情页面;缺失的是这些内容之上的解释层。([GitHub][1])
-### Product decision
+### 产品决策
-Default the UI to **human-readable operational summaries**, with raw logs one layer down.
+将 UI 默认展示**人类可读的操作摘要**,原始日志退居第二层。
-### What we want
+### 期望效果
-- At company level: “who is active, what are they doing, what is moving between teams”
-- At agent level: “what is the plan, what step is complete, what outputs were produced”
-- At run level: “summary first, transcript second”
+- 公司层面:”谁在活跃、他们在做什么、什么在团队间流转”
+- Agent 层面:”计划是什么、哪个步骤已完成、产出了什么”
+- 运行层面:”摘要优先,记录稿其次”
-### Proposed UX
+### 建议的用户体验
-Company page:
+公司页面:
-- org chart with live active-state indicators
-- delegation animation between nodes when work moves
-- current open priorities
-- pending approvals
-- burn / budget warning strip
+- 带有实时活动状态指示器的组织架构图
+- 工作流转时节点间的委派动画
+- 当前开放优先级
+- 待处理审批
+- 消耗/预算警告条
-Agent page:
+Agent 页面:
-- status card
-- current issue
-- plan checklist
-- latest artifact(s)
-- summary of last run
-- expandable raw trace/logs
+- 状态卡片
+- 当前 issue
+- 计划清单
+- 最新产物
+- 上次运行摘要
+- 可展开的原始追踪/日志
-Run page:
+运行页面:
-- **Summary**
-- **Steps**
-- **Raw transcript / tool calls**
+- **摘要**
+- **步骤**
+- **原始记录稿 / 工具调用**
-### Backend / API
+### 后端 / API
-Generate a run view model from current run/activity data:
+从当前运行/活动数据生成运行视图模型:
```ts
type RunSummary = {
diff --git a/doc/plans/2026-03-13-paperclip-skill-tightening-plan.md b/doc/plans/2026-03-13-paperclip-skill-tightening-plan.md
index 68d4ad3c85..0e73369996 100644
--- a/doc/plans/2026-03-13-paperclip-skill-tightening-plan.md
+++ b/doc/plans/2026-03-13-paperclip-skill-tightening-plan.md
@@ -1,186 +1,186 @@
-# Paperclip Skill Tightening Plan
+# Paperclip 技能精简计划
-## Status
+## 状态
-Deferred follow-up. Do not include in the current token-optimization PR beyond documenting the plan.
+延期跟进。除记录本计划外,不要将其纳入当前的 token 优化 PR。
-## Why This Is Deferred
+## 延期原因
-The `paperclip` skill is part of the critical control-plane safety surface. Tightening it may reduce fresh-session token use, but it also carries prompt-regression risk. We do not yet have evals that would let us safely prove behavior preservation across assignment handling, checkout rules, comment etiquette, approval workflows, and escalation paths.
+`paperclip` 技能属于关键控制平面安全层。精简该技能可能减少新会话的 token 消耗,但也存在提示词回归风险。我们目前尚无评估手段来安全地验证任务分配处理、检出规则、评论礼仪、审批流程和升级路径的行为一致性。
-The current PR should ship the lower-risk infrastructure wins first:
+当前 PR 应优先交付风险较低的基础设施改进:
-- telemetry normalization
-- safe session reuse
-- incremental issue/comment context
-- bootstrap versus heartbeat prompt separation
-- Codex worktree isolation
+- 遥测标准化
+- 安全会话复用
+- 增量式 issue/评论上下文
+- 启动提示词与心跳提示词分离
+- Codex 工作树隔离
-## Current Problem
+## 当前问题
-Fresh runs still spend substantial input tokens even after the context-path fixes. The remaining large startup cost appears to come from loading the full `paperclip` skill and related instruction surface into context at run start.
+即使在上下文路径修复之后,全新运行仍然消耗大量输入 token。剩余的较大启动开销似乎来自运行开始时将完整的 `paperclip` 技能及相关指令内容加载到上下文中。
-The skill currently mixes three kinds of content in one file:
+该技能目前在一个文件中混合了三类内容:
-- hot-path heartbeat procedure used on nearly every run
-- critical policy and safety invariants
-- rare workflow/reference material that most runs do not need
+- 几乎每次运行都会使用的热路径心跳流程
+- 关键策略和安全不变量
+- 大多数运行不需要的低频工作流/参考资料
-That structure is safe but expensive.
+这种结构是安全的,但代价昂贵。
-## Goals
+## 目标
-- reduce first-run instruction tokens without weakening agent safety
-- preserve all current Paperclip control-plane capabilities
-- keep common heartbeat behavior explicit and easy for agents to follow
-- move rare workflows and reference material out of the hot path
-- create a structure that can later be evaluated systematically
+- 在不削弱代理安全性的前提下减少首次运行的指令 token
+- 保留所有现有的 Paperclip 控制平面能力
+- 保持常见心跳行为明确且易于代理遵循
+- 将低频工作流和参考资料移出热路径
+- 创建一个后续可以系统性评估的结构
-## Non-Goals
+## 非目标
-- changing Paperclip API semantics
-- removing required governance rules
-- deleting rare workflows
-- changing agent defaults in the current PR
+- 更改 Paperclip API 语义
+- 移除必要的治理规则
+- 删除低频工作流
+- 在当前 PR 中更改代理默认行为
-## Recommended Direction
+## 建议方向
-### 1. Split Hot Path From Lookup Material
+### 1. 将热路径与查阅资料分离
-Restructure the skill into:
+将技能重构为:
-- an always-loaded core section for the common heartbeat loop
-- on-demand material for infrequent workflows and deep reference
+- 一个始终加载的核心部分,用于常见心跳循环
+- 按需加载的资料,用于低频工作流和深度参考
-The core should cover only what is needed on nearly every wake:
+核心部分应仅覆盖几乎每次唤醒都需要的内容:
-- auth and required headers
-- inbox-first assignment retrieval
-- mandatory checkout behavior
-- `heartbeat-context` first
-- incremental comment retrieval rules
-- mention/self-assign exception
-- blocked-task dedup
-- status/comment/release expectations before exit
+- 认证和必需的请求头
+- 收件箱优先的任务获取
+- 强制检出行为
+- `heartbeat-context` 优先
+- 增量评论获取规则
+- 提及/自我分配例外
+- 阻塞任务去重
+- 退出前的状态/评论/发布预期
-### 2. Normalize The Skill Around One Canonical Procedure
+### 2. 围绕一个规范流程标准化技能
-The same rules are currently expressed multiple times across:
+相同的规则目前在多处重复表达:
-- heartbeat steps
-- critical rules
-- endpoint reference
-- workflow examples
+- 心跳步骤
+- 关键规则
+- 端点参考
+- 工作流示例
-Refactor so each operational fact has one primary home:
+重构使每个操作事实只有一个主要归属位置:
-- procedure
-- invariant list
-- appendix/reference
+- 流程
+- 不变量列表
+- 附录/参考
-This reduces prompt weight and lowers the chance of internal instruction drift.
+这可以降低提示词权重,并减少内部指令漂移的可能性。
-### 3. Compress Prose Into High-Signal Instruction Forms
+### 3. 将描述性文本压缩为高信号指令形式
-Rewrite the hot path using compact operational forms:
+使用紧凑的操作形式重写热路径:
-- short ordered checklist
-- flat invariant list
-- minimal examples only where ambiguity would be risky
+- 简短的有序检查清单
+- 扁平的不变量列表
+- 仅在可能产生歧义风险时提供最少的示例
-Reduce:
+减少以下内容:
-- narrative explanation
-- repeated warnings already covered elsewhere
-- large example payloads for common operations
-- long endpoint matrices in the main body
+- 叙述性说明
+- 已在其他地方涵盖的重复警告
+- 常见操作的大型示例载荷
+- 正文中的长端点矩阵
-### 4. Move Rare Workflows Behind Explicit Triggers
+### 4. 将低频工作流移至显式触发器后
-These workflows should remain available but should not dominate fresh-run context:
+以下工作流应保持可用,但不应在全新运行时占据上下文:
-- OpenClaw invite flow
-- project setup flow
-- planning ` ` writeback flow
-- instructions-path update flow
-- detailed link-formatting examples
+- OpenClaw 邀请流程
+- 项目设置流程
+- 规划 ` ` 回写流程
+- 指令路径更新流程
+- 详细的链接格式化示例
-Recommended approach:
+建议方法:
-- keep a short pointer in the main skill
-- move detailed procedures into sibling skills or referenced docs that agents read only when needed
+- 在主技能中保留简短的指引
+- 将详细流程移入兄弟技能或引用文档中,代理仅在需要时读取
-### 5. Separate Policy From Reference
+### 5. 将策略与参考分离
-The skill should distinguish:
+技能应区分:
-- mandatory operating rules
-- endpoint lookup/reference
-- business-process playbooks
+- 强制性操作规则
+- 端点查阅/参考
+- 业务流程手册
-That separation makes it easier to evaluate prompt changes later and lets adapters or orchestration choose what must always be loaded.
+这种分离使后续评估提示词变更更加容易,并允许适配器或编排层选择哪些内容必须始终加载。
-## Proposed Target Structure
+## 建议的目标结构
-1. Purpose and authentication
-2. Compact heartbeat procedure
-3. Hard invariants
-4. Required comment/update style
-5. Triggered workflow index
-6. Appendix/reference
+1. 目的和认证
+2. 紧凑的心跳流程
+3. 硬性不变量
+4. 必需的评论/更新风格
+5. 触发式工作流索引
+6. 附录/参考
-## Rollout Plan
+## 发布计划
-### Phase 1. Inventory And Measure
+### 阶段 1. 盘点与度量
-- annotate the current skill by section and estimate token weight
-- identify which sections are truly hot-path versus rare
-- capture representative runs to compare before/after prompt size and behavior
+- 按章节标注当前技能并估算 token 权重
+- 识别哪些章节真正属于热路径,哪些属于低频
+- 采集代表性运行数据以比较前后的提示词大小和行为
-### Phase 2. Structural Refactor Without Semantic Changes
+### 阶段 2. 不改变语义的结构性重构
-- rewrite the main skill into the target structure
-- preserve all existing rules and capabilities
-- move rare workflow details into referenced companion material
-- keep wording changes conservative
+- 按目标结构重写主技能
+- 保留所有现有规则和能力
+- 将低频工作流细节移入引用的配套资料
+- 保持措辞变更保守
-### Phase 3. Validate Against Real Scenarios
+### 阶段 3. 针对真实场景验证
-Run scenario checks for:
+运行以下场景检查:
-- normal assigned heartbeat
-- comment-triggered wake
-- blocked-task dedup behavior
-- approval-resolution wake
-- delegation/subtask creation
-- board handoff back to user
-- plan-request handling
+- 正常的已分配心跳
+- 评论触发的唤醒
+- 阻塞任务去重行为
+- 审批解决后的唤醒
+- 委派/子任务创建
+- 看板移交回用户
+- 规划请求处理
-### Phase 4. Decide Default Loading Strategy
+### 阶段 4. 决定默认加载策略
-After validation, decide whether:
+验证完成后,决定:
-- the entire main skill still loads by default, or
-- only the compact core loads by default and rare sections are fetched on demand
+- 整个主技能是否仍默认加载,还是
+- 仅默认加载紧凑核心,低频部分按需获取
-Do not change this loading policy without validation.
+在未经验证前不要更改此加载策略。
-## Risks
+## 风险
-- prompt degradation on control-plane safety rules
-- agents forgetting rare but important workflows
-- accidental removal of repeated wording that was carrying useful behavior
-- introducing ambiguous instruction precedence between the core skill and companion materials
+- 控制平面安全规则的提示词退化
+- 代理遗忘低频但重要的工作流
+- 意外删除了实际承载有用行为的重复措辞
+- 在核心技能与配套资料之间引入模糊的指令优先级
-## Preconditions Before Implementation
+## 实施前的先决条件
-- define acceptance scenarios for control-plane correctness
-- add at least lightweight eval or scripted scenario coverage for key Paperclip flows
-- confirm how adapter/bootstrap layering should load skill content versus references
+- 定义控制平面正确性的验收场景
+- 至少为关键 Paperclip 流程添加轻量级评估或脚本化场景覆盖
+- 确认适配器/启动层应如何加载技能内容与参考资料
-## Success Criteria
+## 成功标准
-- materially lower first-run input tokens for Paperclip-coordinated agents
-- no regression in checkout discipline, issue updates, blocked handling, or delegation
-- no increase in malformed API usage or ownership mistakes
-- agents still complete rare workflows correctly when explicitly asked
+- Paperclip 协调的代理首次运行输入 token 显著降低
+- 检出纪律、issue 更新、阻塞处理或委派无回归
+- 格式错误的 API 使用或所有权错误不增加
+- 当被明确要求时,代理仍能正确完成低频工作流
diff --git a/doc/plans/2026-03-13-plugin-kitchen-sink-example.md b/doc/plans/2026-03-13-plugin-kitchen-sink-example.md
index 6a81c5cd5c..3fab1fc233 100644
--- a/doc/plans/2026-03-13-plugin-kitchen-sink-example.md
+++ b/doc/plans/2026-03-13-plugin-kitchen-sink-example.md
@@ -1,61 +1,61 @@
-# Kitchen Sink Plugin Plan
+# Kitchen Sink 插件计划
-## Goal
+## 目标
-Add a new first-party example plugin, `Kitchen Sink (Example)`, that demonstrates every currently implemented Paperclip plugin API surface in one place.
+新增一个官方示例插件 `Kitchen Sink (Example)`,在一个地方集中演示当前已实现的所有 Paperclip 插件 API 表面。
-This plugin is meant to be:
+该插件的定位是:
-- a living reference implementation for contributors
-- a manual test harness for the plugin runtime
-- a discoverable demo of what plugins can actually do today
+- 为贡献者提供持续维护的参考实现
+- 作为插件运行时的手动测试工具
+- 直观地展示插件目前能做到的所有功能
-It is not meant to be a polished end-user product plugin.
+它并非面向最终用户的成熟产品插件。
-## Why
+## 背景
-The current plugin system has a real API surface, but it is spread across:
+当前插件系统已有真实的 API 表面,但这些内容分散在:
-- SDK docs
-- SDK types
-- plugin spec prose
-- two example plugins that each show only a narrow slice
+- SDK 文档
+- SDK 类型定义
+- 插件规范文档
+- 两个示例插件(各自只展示了一小部分功能)
-That makes it hard to answer basic questions like:
+这使得以下基本问题难以得到解答:
-- what can plugins render?
-- what can plugin workers actually do?
-- which surfaces are real versus aspirational?
-- how should a new plugin be structured in this repo?
+- 插件能渲染什么?
+- 插件 worker 实际上能做什么?
+- 哪些表面是真实可用的,哪些仅是规划中的?
+- 新插件在本仓库中应如何组织结构?
-The kitchen-sink plugin should answer those questions by example.
+kitchen-sink 插件应通过实例来回答这些问题。
-## Success Criteria
+## 成功标准
-The plugin is successful if a contributor can install it and, without reading the SDK first, discover and exercise the current plugin runtime surface area from inside Paperclip.
+如果贡献者无需事先阅读 SDK,就能在 Paperclip 内安装插件并探索、体验当前插件运行时的完整功能范围,则视为成功。
-Concretely:
+具体而言:
-- it installs from the bundled examples list
-- it exposes at least one demo for every implemented worker API surface
-- it exposes at least one demo for every host-mounted UI surface
-- it clearly labels local-only / trusted-only demos
-- it is safe enough for local development by default
-- it doubles as a regression harness for plugin runtime changes
+- 可从内置示例列表安装
+- 针对每个已实现的 worker API 表面至少提供一个演示
+- 针对每个宿主挂载的 UI 表面至少提供一个演示
+- 清晰标注仅限本地 / 仅限受信任环境的演示
+- 默认情况下对本地开发足够安全
+- 同时兼作插件运行时变更的回归测试工具
-## Constraints
+## 约束条件
-- Keep it instance-installed, not company-installed.
-- Treat this as a trusted/local example plugin.
-- Do not rely on cloud-safe runtime assumptions.
-- Avoid destructive defaults.
-- Avoid irreversible mutations unless they are clearly labeled and easy to undo.
+- 保持实例级安装,而非公司级安装。
+- 将其视为受信任的本地示例插件。
+- 不依赖云安全运行时假设。
+- 避免破坏性的默认行为。
+- 避免不可逆的数据变更,除非已清晰标注且易于撤销。
-## Source Of Truth For This Plan
+## 本计划的依据来源
-This plan is based on the currently implemented SDK/types/runtime, not only the long-horizon spec.
+本计划基于当前已实现的 SDK/类型/运行时,而非仅参考长期规划文档。
-Primary references:
+主要参考文件:
- `packages/plugins/sdk/README.md`
- `packages/plugins/sdk/src/types.ts`
@@ -63,11 +63,11 @@ Primary references:
- `packages/shared/src/constants.ts`
- `packages/shared/src/types/plugin.ts`
-## Current Surface Inventory
+## 当前表面功能清单
-### Worker/runtime APIs to demonstrate
+### 需要演示的 Worker/运行时 API
-These are the concrete `ctx` clients currently exposed by the SDK:
+以下是 SDK 当前暴露的具体 `ctx` 客户端:
- `ctx.config`
- `ctx.events`
@@ -91,9 +91,9 @@ These are the concrete `ctx` clients currently exposed by the SDK:
- `ctx.metrics`
- `ctx.logger`
-### UI surfaces to demonstrate
+### 需要演示的 UI 表面
-Surfaces defined in the SDK:
+SDK 中定义的表面:
- `page`
- `settingsPage`
@@ -108,367 +108,367 @@ Surfaces defined in the SDK:
- `commentAnnotation`
- `commentContextMenuItem`
-### Current host confidence
+### 当前宿主可信度
-Confirmed or strongly indicated as mounted in the current app:
+已确认或强烈指示在当前应用中已挂载:
- `page`
- `settingsPage`
- `dashboardWidget`
- `detailTab`
- `projectSidebarItem`
-- comment surfaces
-- launcher infrastructure
+- 评论相关表面
+- launcher 基础设施
-Need explicit validation before claiming full demo coverage:
+在声称完整演示覆盖之前,需要明确验证:
- `sidebar`
- `sidebarPanel`
- `taskDetailView`
-- `toolbarButton` as direct slot, distinct from launcher placement
-- `contextMenuItem` as direct slot, distinct from comment menu and launcher placement
+- `toolbarButton` 作为直接插槽,有别于 launcher 位置
+- `contextMenuItem` 作为直接插槽,有别于评论菜单和 launcher 位置
-The implementation should keep a small validation checklist for these before we call the plugin "complete".
+在宣布插件"完成"之前,实现中应保留一个针对上述项的小型验证清单。
-## Plugin Concept
+## 插件概念
-The plugin should be named:
+插件命名:
-- display name: `Kitchen Sink (Example)`
-- package: `@paperclipai/plugin-kitchen-sink-example`
-- plugin id: `paperclip.kitchen-sink-example` or `paperclip-kitchen-sink-example`
+- 显示名称:`Kitchen Sink (Example)`
+- 包名:`@paperclipai/plugin-kitchen-sink-example`
+- 插件 ID:`paperclip.kitchen-sink-example` 或 `paperclip-kitchen-sink-example`
-Recommendation: use `paperclip-kitchen-sink-example` to match current in-repo example naming style.
+建议:使用 `paperclip-kitchen-sink-example`,以匹配当前仓库中示例插件的命名风格。
-Category mix:
+分类组合:
- `ui`
- `automation`
- `workspace`
- `connector`
-That is intentionally broad because the point is coverage.
+覆盖范围有意设置较宽,因为重点在于全面覆盖。
-## UX Shape
+## 用户体验形态
-The plugin should have one main full-page demo console plus smaller satellites on other surfaces.
+插件应有一个主要的全页演示控制台,以及在其他表面上的若干小型附属组件。
-### 1. Plugin page
+### 1. 插件页面
-Primary route: the plugin `page` surface should be the central dashboard for all demos.
+主路由:插件的 `page` 表面应作为所有演示的中央控制台。
-Recommended page sections:
+建议的页面分区:
-- `Overview`
- - what this plugin demonstrates
- - current capabilities granted
- - current host context
-- `UI Surfaces`
- - links explaining where each other surface should appear
-- `Data + Actions`
- - buttons and forms for bridge-driven worker demos
-- `Events + Streams`
- - emit event
- - watch event log
- - stream demo output
-- `Paperclip Domain APIs`
- - companies
- - projects/workspaces
- - issues
- - goals
- - agents
-- `Local Workspace + Process`
- - file listing
- - file read/write scratch area
- - child process demo
-- `Jobs + Webhooks + Tools`
- - job status
- - webhook URL and recent deliveries
- - declared tools
-- `State + Entities + Assets`
- - scoped state editor
- - plugin entity inspector
- - upload/generated asset demo
-- `Observability`
- - metrics written
- - activity log samples
- - latest worker logs
+- `Overview`(概览)
+ - 本插件演示的功能
+ - 当前已授予的能力
+ - 当前宿主上下文
+- `UI Surfaces`(UI 表面)
+ - 说明每个其他表面应出现位置的链接
+- `Data + Actions`(数据与操作)
+ - 用于桥接驱动 worker 演示的按钮和表单
+- `Events + Streams`(事件与流)
+ - 发送事件
+ - 查看事件日志
+ - 流式演示输出
+- `Paperclip Domain APIs`(Paperclip 领域 API)
+ - companies(公司)
+ - projects/workspaces(项目/工作区)
+ - issues(工单)
+ - goals(目标)
+ - agents(智能体)
+- `Local Workspace + Process`(本地工作区与进程)
+ - 文件列表
+ - 文件读/写草稿区
+ - 子进程演示
+- `Jobs + Webhooks + Tools`(任务、Webhook 与工具)
+ - 任务状态
+ - Webhook URL 及最近推送记录
+ - 已声明的工具
+- `State + Entities + Assets`(状态、实体与资产)
+ - 作用域状态编辑器
+ - 插件实体检查器
+ - 上传/生成资产演示
+- `Observability`(可观测性)
+ - 已写入的指标
+ - 活动日志样本
+ - 最新 worker 日志
-### 2. Dashboard widget
+### 2. 仪表盘组件
-A compact widget on the main dashboard should show:
+主仪表盘上的紧凑型组件应展示:
-- plugin health
-- count of demos exercised
-- recent event/stream activity
-- shortcut to the full plugin page
+- 插件健康状态
+- 已执行的演示数量
+- 最近的事件/流活动
+- 跳转至完整插件页面的快捷方式
-### 3. Project sidebar item
+### 3. 项目侧边栏条目
-Add a `Kitchen Sink` link under each project that deep-links into a project-scoped plugin tab.
+在每个项目下添加一个 `Kitchen Sink` 链接,深链接到项目作用域的插件标签页。
-### 4. Detail tabs
+### 4. 详情标签页
-Use detail tabs to demonstrate entity-context rendering on:
+使用详情标签页演示在以下实体上的上下文渲染:
-- `project`
-- `issue`
-- `agent`
-- `goal`
+- `project`(项目)
+- `issue`(工单)
+- `agent`(智能体)
+- `goal`(目标)
-Each tab should show:
+每个标签页应展示:
-- the host context it received
-- the relevant entity fetch via worker bridge
-- one small action scoped to that entity
+- 收到的宿主上下文
+- 通过 worker 桥接获取的相关实体
+- 一个作用于该实体的小型操作
-### 5. Comment surfaces
+### 5. 评论表面
-Use issue comment demos to prove comment-specific extension points:
+使用工单评论演示来验证评论专属扩展点:
- `commentAnnotation`
- - render parsed metadata below each comment
- - show comment id, issue id, and a small derived status
+ - 在每条评论下方渲染解析后的元数据
+ - 显示评论 ID、工单 ID 以及一个小型派生状态
- `commentContextMenuItem`
- - add a menu action like `Copy Context To Kitchen Sink`
- - action writes a plugin entity or state record for later inspection
+ - 添加一个菜单操作,如 `Copy Context To Kitchen Sink`
+ - 该操作写入一条插件实体或状态记录,以供后续检查
-### 6. Settings page
+### 6. 设置页面
-Custom `settingsPage` should be intentionally simple and operational:
+自定义 `settingsPage` 应保持简洁且实用:
-- `About`
-- `Danger / Trust Model`
-- demo toggles
-- local process defaults
-- workspace scratch-path behavior
-- secret reference inputs
-- event/job/webhook sample config
+- `About`(关于)
+- `Danger / Trust Model`(危险操作/信任模型)
+- 演示开关
+- 本地进程默认配置
+- 工作区草稿路径行为
+- 密钥引用输入项
+- 事件/任务/webhook 示例配置
-This plugin should also keep the generic plugin settings `Status` tab useful by writing health, logs, and metrics.
+该插件还应通过写入健康状态、日志和指标,使通用插件设置中的 `Status` 标签页保持有价值的展示内容。
-## Feature Matrix
+## 功能矩阵
-Each implemented worker API should have a visible demo.
+每个已实现的 worker API 都应有一个可见的演示。
### `ctx.config`
-Demo:
+演示内容:
-- read live config
-- show config JSON
-- react to config changes without restart where possible
+- 读取实时配置
+- 显示配置 JSON
+- 在可能的情况下,无需重启即可响应配置变更
### `ctx.events`
-Demos:
+演示内容:
-- emit a plugin event
-- subscribe to plugin events
-- subscribe to a core Paperclip event such as `issue.created`
-- show recent received events in a timeline
+- 发送插件事件
+- 订阅插件事件
+- 订阅核心 Paperclip 事件,例如 `issue.created`
+- 以时间线形式展示最近收到的事件
### `ctx.jobs`
-Demos:
+演示内容:
-- one scheduled heartbeat-style demo job
-- one manual run button from the UI if host supports manual job trigger
-- show last run result and timestamps
+- 一个定时的心跳式演示任务
+- 如果宿主支持手动触发任务,则在 UI 上提供一个手动运行按钮
+- 显示最近一次的运行结果和时间戳
### `ctx.launchers`
-Demos:
+演示内容:
-- declare launchers in manifest
-- optionally register one runtime launcher from the worker
-- show launcher metadata on the plugin page
+- 在 manifest 中声明 launcher
+- 可选:从 worker 中注册一个运行时 launcher
+- 在插件页面显示 launcher 元数据
### `ctx.http`
-Demo:
+演示内容:
-- make a simple outbound GET request to a safe endpoint
-- show status code, latency, and JSON result
+- 向安全端点发出一个简单的出站 GET 请求
+- 显示状态码、延迟和 JSON 结果
-Recommendation: default to a Paperclip-local endpoint or a stable public echo endpoint to avoid flaky docs.
+建议:默认使用 Paperclip 本地端点或稳定的公共 echo 端点,以避免不稳定的文档示例。
### `ctx.secrets`
-Demo:
+演示内容:
-- operator enters a secret reference in config
-- plugin resolves it on demand
-- UI only shows masked result length / success status, never raw secret
+- 操作员在配置中输入一个密钥引用
+- 插件按需解析该密钥
+- UI 仅显示掩码后的结果长度/成功状态,绝不显示原始密钥
### `ctx.assets`
-Demos:
+演示内容:
-- generate a text asset from the UI
-- optionally upload a tiny JSON blob or screenshot-like text file
-- show returned asset URL
+- 从 UI 生成一个文本资产
+- 可选:上传一个小型 JSON blob 或类截图的文本文件
+- 显示返回的资产 URL
### `ctx.activity`
-Demo:
+演示内容:
-- button to write a plugin activity log entry against current company/entity
+- 一个按钮,用于针对当前公司/实体写入一条插件活动日志记录
### `ctx.state`
-Demos:
+演示内容:
-- instance-scoped state
-- company-scoped state
-- project-scoped state
-- issue-scoped state
-- delete/reset controls
+- 实例作用域状态
+- 公司作用域状态
+- 项目作用域状态
+- 工单作用域状态
+- 删除/重置控件
-Use a small state inspector/editor on the plugin page.
+在插件页面使用一个小型状态检查器/编辑器。
### `ctx.entities`
-Demos:
+演示内容:
-- create plugin-owned sample records
-- list/filter them
-- show one realistic use case such as "copied comments" or "demo sync records"
+- 创建插件自有的示例记录
+- 列表/过滤这些记录
+- 展示一个实际用例,例如"复制的评论"或"演示同步记录"
### `ctx.projects`
-Demos:
+演示内容:
-- list projects
-- list project workspaces
-- resolve primary workspace
-- resolve workspace for issue
+- 列出项目
+- 列出项目工作区
+- 解析主工作区
+- 解析工单对应的工作区
### `ctx.companies`
-Demo:
+演示内容:
-- list companies and show current selected company
+- 列出公司并显示当前选中的公司
### `ctx.issues`
-Demos:
+演示内容:
-- list issues in current company
-- create issue
-- update issue status/title
-- list comments
-- create comment
+- 列出当前公司的工单
+- 创建工单
+- 更新工单状态/标题
+- 列出评论
+- 创建评论
### `ctx.agents`
-Demos:
+演示内容:
-- list agents
-- invoke one agent with a test prompt
-- pause/resume where safe
+- 列出智能体
+- 使用测试提示调用一个智能体
+- 在安全的情况下执行暂停/恢复操作
-Agent mutation controls should be behind an explicit warning.
+智能体变更控件应置于明确的警告提示之后。
### `ctx.agents.sessions`
-Demos:
+演示内容:
-- create agent chat session
-- send message
-- stream events back to the UI
-- close session
+- 创建智能体聊天会话
+- 发送消息
+- 将事件流式传回 UI
+- 关闭会话
-This is a strong candidate for the best "wow" demo on the plugin page.
+这是插件页面上"震撼"演示效果的最佳候选。
### `ctx.goals`
-Demos:
+演示内容:
-- list goals
-- create goal
-- update status/title
+- 列出目标
+- 创建目标
+- 更新状态/标题
### `ctx.data`
-Use throughout the plugin for all read-side bridge demos.
+在整个插件中用于所有读取侧桥接演示。
### `ctx.actions`
-Use throughout the plugin for all mutation-side bridge demos.
+在整个插件中用于所有变更侧桥接演示。
### `ctx.streams`
-Demos:
+演示内容:
-- live event log stream
-- token-style stream from an agent session relay
-- fake progress stream for a long-running action
+- 实时事件日志流
+- 来自智能体会话中继的 token 风格流
+- 用于长时间运行操作的模拟进度流
### `ctx.tools`
-Demos:
+演示内容:
-- declare 2-3 simple agent tools
-- tool 1: echo/diagnostics
-- tool 2: project/workspace summary
-- tool 3: create issue or write plugin state
+- 声明 2-3 个简单的智能体工具
+- 工具 1:echo/诊断
+- 工具 2:项目/工作区摘要
+- 工具 3:创建工单或写入插件状态
-The plugin page should list declared tools and show example input payloads.
+插件页面应列出已声明的工具,并显示示例输入载荷。
### `ctx.metrics`
-Demo:
+演示内容:
-- write a sample metric on each major demo action
-- surface a small recent metrics table in the plugin page
+- 在每个主要演示操作时写入一条示例指标
+- 在插件页面展示一个小型近期指标表格
### `ctx.logger`
-Demo:
+演示内容:
-- every action logs structured entries
-- plugin settings `Status` page then doubles as the log viewer
+- 每个操作均记录结构化日志条目
+- 插件设置中的 `Status` 页面同时作为日志查看器
-## Local Workspace And Process Demos
+## 本地工作区与进程演示
-The plugin SDK intentionally leaves file/process operations to the plugin itself once it has workspace metadata.
+插件 SDK 有意将文件/进程操作留给插件自身处理,前提是插件已获取工作区元数据。
-The kitchen-sink plugin should demonstrate that explicitly.
+kitchen-sink 插件应明确演示这一点。
-### Workspace demos
+### 工作区演示
-- list files from a selected workspace
-- read a file
-- write to a plugin-owned scratch file
-- optionally search files with `rg` if available
+- 列出所选工作区的文件
+- 读取一个文件
+- 向插件自有的草稿文件写入内容
+- 可选:如果 `rg` 可用,则演示文件搜索
-### Process demos
+### 进程演示
-- run a short-lived command like `pwd`, `ls`, or `git status`
-- stream stdout/stderr back to UI
-- show exit code and timing
+- 运行一个短生命周期命令,如 `pwd`、`ls` 或 `git status`
+- 将 stdout/stderr 流式传回 UI
+- 显示退出码和耗时
-Important safeguards:
+重要的安全保障措施:
-- default commands must be read-only
-- no shell interpolation from arbitrary free-form input in v1
-- provide a curated command list or a strongly validated command form
-- clearly label this area as local-only and trusted-only
+- 默认命令必须是只读的
+- v1 中不支持来自任意自由输入的 shell 插值
+- 提供一个精选命令列表或经过强验证的命令表单
+- 明确将此区域标注为仅限本地和仅限受信任环境
-## Proposed Manifest Coverage
+## 建议的 Manifest 覆盖范围
-The plugin should aim to declare:
+插件应声明以下内容:
- `page`
- `settingsPage`
- `dashboardWidget`
-- `detailTab` for `project`, `issue`, `agent`, `goal`
+- `detailTab`,用于 `project`、`issue`、`agent`、`goal`
- `projectSidebarItem`
- `commentAnnotation`
- `commentContextMenuItem`
-Then, after host validation, add if supported:
+在宿主验证通过后,若支持则添加:
- `sidebar`
- `sidebarPanel`
@@ -476,15 +476,15 @@ Then, after host validation, add if supported:
- `toolbarButton`
- `contextMenuItem`
-It should also declare one or more `ui.launchers` entries to exercise launcher behavior independently of slot rendering.
+此外,还应声明一个或多个 `ui.launchers` 条目,以独立于插槽渲染来验证 launcher 行为。
-## Proposed Package Layout
+## 建议的包目录结构
-New package:
+新建包路径:
- `packages/plugins/examples/plugin-kitchen-sink-example/`
-Expected files:
+预期文件:
- `package.json`
- `README.md`
@@ -496,37 +496,37 @@ Expected files:
- `src/ui/components/...`
- `src/ui/hooks/...`
- `src/lib/...`
-- optional `scripts/build-ui.mjs` if UI bundling needs esbuild
+- 可选:`scripts/build-ui.mjs`(如果 UI 打包需要 esbuild)
-## Proposed Internal Architecture
+## 建议的内部架构
-### Worker modules
+### Worker 模块
-Recommended split:
+建议拆分如下:
- `src/worker.ts`
- - plugin definition and wiring
+ - 插件定义与连接
- `src/worker/data.ts`
- `ctx.data.register(...)`
- `src/worker/actions.ts`
- `ctx.actions.register(...)`
- `src/worker/events.ts`
- - event subscriptions and event log buffer
+ - 事件订阅和事件日志缓冲区
- `src/worker/jobs.ts`
- - scheduled job handlers
+ - 定时任务处理器
- `src/worker/tools.ts`
- - tool declarations and handlers
+ - 工具声明和处理器
- `src/worker/local-runtime.ts`
- - file/process demos
+ - 文件/进程演示
- `src/worker/demo-store.ts`
- - helpers for state/entities/assets/metrics
+ - state/entities/assets/metrics 的辅助工具
-### UI modules
+### UI 模块
-Recommended split:
+建议拆分如下:
- `src/ui/index.tsx`
- - exported slot components
+ - 导出的插槽组件
- `src/ui/page/KitchenSinkPage.tsx`
- `src/ui/settings/KitchenSinkSettingsPage.tsx`
- `src/ui/widgets/KitchenSinkDashboardWidget.tsx`
@@ -538,11 +538,11 @@ Recommended split:
- `src/ui/comments/KitchenSinkCommentMenuItem.tsx`
- `src/ui/shared/...`
-## Configuration Schema
+## 配置 Schema
-The plugin should have a substantial but understandable `instanceConfigSchema`.
+插件应有一个内容充实但易于理解的 `instanceConfigSchema`。
-Recommended config fields:
+建议的配置字段:
- `enableDangerousDemos`
- `enableWorkspaceDemos`
@@ -553,147 +553,147 @@ Recommended config fields:
- `showCommentAnnotation`
- `showCommentContextMenuItem`
- `showToolbarLauncher`
-- `defaultDemoCompanyId` optional
+- `defaultDemoCompanyId`(可选)
- `secretRefExample`
- `httpDemoUrl`
- `processAllowedCommands`
- `workspaceScratchSubdir`
-Defaults should keep risky behavior off.
+默认值应关闭所有高风险行为。
-## Safety Defaults
+## 安全默认值
-Default posture:
+默认策略:
-- UI and read-only demos on
-- mutating domain demos on but explicitly labeled
-- process demos off by default
-- no arbitrary shell input by default
-- no raw secret rendering ever
+- UI 和只读演示默认开启
+- 数据变更类演示默认开启,但需明确标注
+- 进程演示默认关闭
+- 默认不允许任意 shell 输入
+- 永远不渲染原始密钥
-## Phased Build Plan
+## 分阶段构建计划
-### Phase 1: Core plugin skeleton
+### 第一阶段:核心插件骨架
-- scaffold package
-- add manifest, worker, UI entrypoints
-- add README
-- make it appear in bundled examples list
+- 脚手架搭建包结构
+- 添加 manifest、worker、UI 入口点
+- 添加 README
+- 使其出现在内置示例列表中
-### Phase 2: Core, confirmed UI surfaces
+### 第二阶段:核心已确认 UI 表面
-- plugin page
-- settings page
-- dashboard widget
-- project sidebar item
-- detail tabs
+- 插件页面
+- 设置页面
+- 仪表盘组件
+- 项目侧边栏条目
+- 详情标签页
-### Phase 3: Core worker APIs
+### 第三阶段:核心 Worker API
-- config
-- state
-- entities
-- companies/projects/issues/goals
-- data/actions
-- metrics/logger/activity
+- config(配置)
+- state(状态)
+- entities(实体)
+- companies/projects/issues/goals(公司/项目/工单/目标)
+- data/actions(数据/操作)
+- metrics/logger/activity(指标/日志/活动)
-### Phase 4: Real-time and automation APIs
+### 第四阶段:实时与自动化 API
-- streams
-- events
-- jobs
+- streams(流)
+- events(事件)
+- jobs(任务)
- webhooks
-- agent sessions
-- tools
+- agent sessions(智能体会话)
+- tools(工具)
-### Phase 5: Local trusted runtime demos
+### 第五阶段:本地受信任运行时演示
-- workspace file demos
-- child process demos
-- guarded by config
+- 工作区文件演示
+- 子进程演示
+- 由配置项控制开关
-### Phase 6: Secondary UI surfaces
+### 第六阶段:次要 UI 表面
-- comment annotation
-- comment context menu item
-- launchers
+- comment annotation(评论注释)
+- comment context menu item(评论上下文菜单项)
+- launcher
-### Phase 7: Validation-only surfaces
+### 第七阶段:仅需验证的表面
-Validate whether the current host truly mounts:
+验证当前宿主是否真正挂载:
- `sidebar`
- `sidebarPanel`
- `taskDetailView`
-- direct-slot `toolbarButton`
-- direct-slot `contextMenuItem`
+- 直接插槽 `toolbarButton`
+- 直接插槽 `contextMenuItem`
-If mounted, add demos.
-If not mounted, document them as SDK-defined but host-pending.
+若已挂载,则添加演示。
+若未挂载,则将其记录为 SDK 已定义但宿主侧待实现。
-## Documentation Deliverables
+## 文档交付物
-The plugin should ship with a README that includes:
+插件应附带一份 README,内容包括:
-- what it demonstrates
-- which surfaces are local-only
-- how to install it
-- where each UI surface should appear
-- a mapping from demo card to SDK API
+- 本插件演示的功能
+- 哪些表面仅限本地环境
+- 安装方式
+- 每个 UI 表面应出现的位置
+- 演示卡片与 SDK API 的对应映射
-It should also be referenced from plugin docs as the "reference everything plugin".
+此外,还应在插件文档中将其作为"覆盖所有功能的参考插件"加以引用。
-## Testing And Verification
+## 测试与验证
-Minimum verification:
+最低验证要求:
-- package typecheck/build
-- install from bundled example list
-- page loads
-- widget appears
-- project tab appears
-- comment surfaces render
-- settings page loads
-- key actions succeed
+- 包类型检查/构建
+- 从内置示例列表安装
+- 页面可正常加载
+- 组件正常显示
+- 项目标签页正常显示
+- 评论表面正常渲染
+- 设置页面可正常加载
+- 关键操作执行成功
-Recommended manual checklist:
+建议的手动核查清单:
-- create issue from plugin
-- create goal from plugin
-- emit and receive plugin event
-- stream action output
-- open agent session and receive streamed reply
-- upload an asset
-- write plugin activity log
-- run a safe local process demo
+- 从插件创建工单
+- 从插件创建目标
+- 发送并接收插件事件
+- 流式输出操作结果
+- 打开智能体会话并接收流式回复
+- 上传一个资产
+- 写入插件活动日志
+- 运行一个安全的本地进程演示
-## Open Questions
+## 待解决问题
-1. Should the process demo remain curated-command-only in the first pass?
- Recommendation: yes.
+1. 进程演示在第一版中是否应仅限精选命令?
+ 建议:是。
-2. Should the plugin create throwaway "kitchen sink demo" issues/goals automatically?
- Recommendation: no. Make creation explicit.
+2. 插件是否应自动创建一次性的"kitchen sink demo"工单/目标?
+ 建议:否。创建操作应显式触发。
-3. Should we expose unsupported-but-typed surfaces in the UI even if host mounting is not wired?
- Recommendation: yes, but label them as `SDK-defined / host validation pending`.
+3. 即使宿主挂载尚未接通,是否也应在 UI 中暴露已有类型定义但尚不支持的表面?
+ 建议:是,但应标注为 `SDK-defined / host validation pending`(SDK 已定义/宿主验证待完成)。
-4. Should agent mutation demos include pause/resume by default?
- Recommendation: probably yes, but behind a warning block.
+4. 智能体变更演示是否应默认包含暂停/恢复操作?
+ 建议:大概率是,但应置于警告提示块之后。
-5. Should this plugin be treated as a supported regression harness in CI later?
- Recommendation: yes. Long term, this should be the plugin-runtime smoke test package.
+5. 该插件后续是否应作为 CI 中受支持的回归测试工具?
+ 建议:是。从长远来看,这应当成为插件运行时的冒烟测试包。
-## Recommended Next Step
+## 建议的下一步
-If this plan looks right, the next implementation pass should start by building only:
+如果本计划方向正确,下一轮实现应仅从以下内容开始:
-- package skeleton
-- page
-- settings page
-- dashboard widget
-- one project detail tab
-- one issue detail tab
-- the basic worker/action/data/state/event scaffolding
+- 包骨架
+- 插件页面
+- 设置页面
+- 仪表盘组件
+- 一个项目详情标签页
+- 一个工单详情标签页
+- 基础的 worker/action/data/state/event 脚手架
-That is enough to lock the architecture before filling in every demo surface.
+这已足够在填充所有演示表面之前锁定整体架构。
diff --git a/doc/plans/2026-03-13-workspace-product-model-and-work-product.md b/doc/plans/2026-03-13-workspace-product-model-and-work-product.md
index ae5b8e793d..d87b18f02e 100644
--- a/doc/plans/2026-03-13-workspace-product-model-and-work-product.md
+++ b/doc/plans/2026-03-13-workspace-product-model-and-work-product.md
@@ -1,191 +1,191 @@
-# Workspace Product Model, Work Product, and PR Flow
+# 工作区产品模型、工作成果与 PR 流程
-## Context
+## 背景
-Paperclip needs to support two very different but equally valid ways of working:
+Paperclip 需要支持两种截然不同但同样合理的工作方式:
-- a solo developer working directly on `master`, or in a folder that is not even a git repo
-- a larger engineering workflow with isolated branches, previews, pull requests, and cleanup automation
+- 独立开发者直接在 `master` 上工作,或在一个甚至不是 git 仓库的文件夹中工作
+- 具有隔离分支、预览、Pull Request 及清理自动化的大型工程工作流
-Today, Paperclip already has the beginnings of this model:
+目前,Paperclip 已具备该模型的雏形:
-- `projects` can carry execution workspace policy
-- `project_workspaces` already exist as a durable project-scoped object
-- issues can carry execution workspace settings
-- runtime services can be attached to a workspace or issue
+- `projects` 可携带执行工作区策略
+- `project_workspaces` 已作为持久化项目级对象存在
+- issue 可携带执行工作区设置
+- 运行时服务可附加到工作区或 issue
-What is missing is a clear product model and UI that make these capabilities understandable and operable.
+缺少的是清晰的产品模型和 UI,使这些能力易于理解和操作。
-The main product risk is overloading one concept to do too much:
+主要的产品风险在于将一个概念过载以承担过多职责:
-- making subissues do the job of branches or PRs
-- making projects too infrastructure-heavy
-- making workspaces so hidden that users cannot form a mental model
-- making Paperclip feel like a code review tool instead of a control plane
+- 让子 issue 承担分支或 PR 的职责
+- 让项目变得过于基础设施繁重
+- 让工作区过于隐蔽,导致用户无法形成心智模型
+- 让 Paperclip 看起来像代码审查工具,而非控制平面
-## Goals
+## 目标
-1. Keep `project` lightweight enough to remain a planning container.
-2. Make workspace behavior understandable for both git and non-git projects.
-3. Support three real workflows without forcing one:
- - shared workspace / direct-edit workflows
- - isolated issue workspace workflows
- - long-lived branch or operator integration workflows
-4. Provide a first-class place to see the outputs of work:
- - previews
- - PRs
- - branches
- - commits
- - documents and artifacts
-5. Keep the main navigation and task board simple.
-6. Seamlessly upgrade existing Paperclip users to the new model without forcing disruptive reconfiguration.
-7. Support cloud-hosted Paperclip deployments where execution happens in remote or adapter-managed environments rather than local workers.
+1. 保持 `project` 足够轻量,以继续作为规划容器。
+2. 使工作区行为对 git 和非 git 项目都易于理解。
+3. 支持三种真实工作流,而不强制使用某一种:
+ - 共享工作区 / 直接编辑工作流
+ - 隔离 issue 工作区工作流
+ - 长期存在的分支或运营者集成工作流
+4. 提供一个一等公民的位置来查看工作成果:
+ - 预览
+ - PR
+ - 分支
+ - 提交
+ - 文档和制品
+5. 保持主导航和任务看板简洁。
+6. 无缝升级现有 Paperclip 用户到新模型,无需强制进行破坏性重新配置。
+7. 支持云托管的 Paperclip 部署,其中执行发生在远程或适配器管理的环境中,而非本地工作节点。
-## Non-Goals
+## 非目标
-- Turning Paperclip into a full code review product
-- Requiring every issue to have its own branch or PR
-- Requiring every project to configure code/workspace automation
-- Making workspaces a top-level global navigation primitive in V1
-- Requiring a local filesystem path or local git checkout to use workspace-aware execution
+- 将 Paperclip 变成完整的代码审查产品
+- 要求每个 issue 都有自己的分支或 PR
+- 要求每个项目都配置代码/工作区自动化
+- 在 V1 中将工作区作为顶级全局导航元素
+- 要求使用本地文件系统路径或本地 git 检出来使用工作区感知执行
-## Core Product Decisions
+## 核心产品决策
-### 1. Project stays the planning object
+### 1. 项目保持为规划对象
-A `project` remains the thing that groups work around a deliverable or initiative.
+`project` 继续作为围绕可交付成果或计划将工作分组的对象。
-It may have:
+它可以有:
-- no code at all
-- one default codebase/workspace
-- several codebases/workspaces
+- 完全没有代码
+- 一个默认代码库/工作区
+- 多个代码库/工作区
-Projects are not required to become heavyweight.
+项目不需要变得繁重。
-### 2. Project workspace is a first-class object, but scoped under project
+### 2. 项目工作区是一等公民对象,但作用域在项目下
-A `project workspace` is the durable codebase or root environment for a project.
+`project workspace`(项目工作区)是项目的持久化代码库或根环境。
-Examples:
+示例:
-- a local folder on disk
-- a git repo checkout
-- a monorepo package root
-- a non-git design/doc folder
-- a remote adapter-managed codebase reference
+- 磁盘上的本地文件夹
+- git 仓库检出
+- monorepo 包根目录
+- 非 git 的设计/文档文件夹
+- 远程适配器管理的代码库引用
-This is the stable anchor that operators configure once.
+这是运营者一次性配置的稳定锚点。
-It should not be a top-level sidebar item in the main app. It should live under the project experience.
+它不应该作为主应用中的顶级侧边栏项目,而应位于项目体验之下。
-### 3. Execution workspace is a first-class runtime object
+### 3. 执行工作区是一等公民运行时对象
-An `execution workspace` is where a specific run or issue actually executes.
+`execution workspace`(执行工作区)是特定运行或 issue 实际执行的地方。
-Examples:
+示例:
-- the shared project workspace itself
-- an isolated git worktree
-- a long-lived operator branch checkout
-- an adapter-managed remote sandbox
-- a cloud agent provider's isolated branch/session environment
+- 共享的项目工作区本身
+- 隔离的 git worktree
+- 长期存在的运营者分支检出
+- 适配器管理的远程沙箱
+- 云代理提供商的隔离分支/会话环境
-This object must be recorded explicitly so that Paperclip can:
+该对象必须被明确记录,以便 Paperclip 能够:
-- show where work happened
-- attach previews and runtime services
-- link PRs and branches
-- decide cleanup behavior
-- support reuse across multiple related issues
+- 显示工作发生的位置
+- 附加预览和运行时服务
+- 链接 PR 和分支
+- 决定清理行为
+- 支持跨多个相关 issue 的复用
-### 4. PRs are work product, not the core issue model
+### 4. PR 是工作成果,而非核心 issue 模型
-A PR is an output of work, not the planning unit.
+PR 是工作的输出,而非规划单元。
-Paperclip should treat PRs as a type of work product linked back to:
+Paperclip 应将 PR 视为一种工作成果,并链接回:
-- the issue
-- the execution workspace
-- optionally the project workspace
+- issue
+- 执行工作区
+- 可选地链接到项目工作区
-Git-specific automation should live under workspace policy, not under the core issue abstraction.
+特定于 git 的自动化应位于工作区策略下,而非核心 issue 抽象之下。
-### 5. Existing users must upgrade automatically
+### 5. 现有用户必须自动升级
-Paperclip already has users and existing project/task data. Any new model must preserve continuity.
+Paperclip 已有用户和现有项目/任务数据。任何新模型都必须保持连续性。
-The product should default existing installs into a sensible compatibility mode:
+产品应将现有安装默认置于合理的兼容模式:
-- existing projects without workspace configuration continue to work unchanged
-- existing `project_workspaces` become the durable `project workspace` objects
-- existing project execution workspace policy is mapped forward rather than discarded
-- issues without explicit workspace fields continue to inherit current behavior
+- 没有工作区配置的现有项目继续无变化地工作
+- 现有 `project_workspaces` 成为持久化的 `project workspace` 对象
+- 现有项目执行工作区策略被映射到新版本,而非丢弃
+- 没有明确工作区字段的 issue 继续继承当前行为
-This migration should feel additive, not like a mandatory re-onboarding flow.
+此迁移应感觉是附加性的,而非强制性的重新入驻流程。
-### 6. Cloud-hosted Paperclip must be a first-class deployment mode
+### 6. 云托管的 Paperclip 必须是一等公民部署模式
-Paperclip cannot assume that it is running on the same machine as the code.
+Paperclip 不能假设它与代码运行在同一台机器上。
-In cloud deployments, Paperclip may:
+在云部署中,Paperclip 可能:
-- run on Vercel or another serverless host
-- have no long-lived local worker process
-- delegate execution to a remote coding agent or provider-managed sandbox
-- receive back a branch, PR, preview URL, or artifact from that remote environment
+- 在 Vercel 或其他无服务器主机上运行
+- 没有长期存在的本地工作节点进程
+- 将执行委托给远程编码代理或提供商管理的沙箱
+- 从该远程环境接收回分支、PR、预览 URL 或制品
-The model therefore must be portable:
+因此模型必须是可移植的:
-- `project workspace` may be remote-managed, not local
-- `execution workspace` may have no local `cwd`
-- `runtime services` may be tracked by provider reference and URL rather than a host process
-- work product harvesting must handle externally owned previews and PRs
+- `project workspace` 可能是远程管理的,而非本地的
+- `execution workspace` 可能没有本地 `cwd`
+- `runtime services` 可能通过提供商引用和 URL 来跟踪,而非主机进程
+- 工作成果收集必须处理外部拥有的预览和 PR
-### 7. Subissues remain planning and ownership structure
+### 7. 子 issue 保持为规划和所有权结构
-Subissues are for decomposition and parallel ownership.
+子 issue 用于分解和并行所有权。
-They are not the same thing as:
+它们与以下概念不同:
-- a branch
-- a worktree
-- a PR
-- a preview
+- 分支
+- worktree
+- PR
+- 预览
-They may correlate with those things, but they should not be overloaded to mean them.
+它们可能与这些概念相关,但不应被过载为意味着它们。
-## Terminology
+## 术语
-Use these terms consistently in product copy:
+在产品文案中一致使用以下术语:
-- `Project`: planning container
-- `Project workspace`: durable configured codebase/root
-- `Execution workspace`: actual runtime workspace used for issue execution
-- `Isolated issue workspace`: user-facing term for an issue-specific derived workspace
-- `Work product`: previews, PRs, branches, commits, artifacts, docs
-- `Runtime service`: a process or service Paperclip owns or tracks for a workspace
+- `Project`:规划容器
+- `Project workspace`:持久化配置的代码库/根目录
+- `Execution workspace`:用于 issue 执行的实际运行时工作区
+- `Isolated issue workspace`:面向用户的术语,指特定 issue 的派生工作区
+- `Work product`:预览、PR、分支、提交、制品、文档
+- `Runtime service`:Paperclip 为工作区拥有或跟踪的进程或服务
-Use these terms consistently in migration and deployment messaging:
+在迁移和部署消息中一致使用以下术语:
-- `Compatible mode`: existing behavior preserved without new workspace automation
-- `Adapter-managed workspace`: workspace realized by a remote or cloud execution provider
+- `Compatible mode`:在没有新工作区自动化的情况下保留现有行为
+- `Adapter-managed workspace`:由远程或云执行提供商实现的工作区
-Avoid teaching users that "workspace" always means "git worktree on my machine".
+避免让用户认为"工作区"总是意味着"我机器上的 git worktree"。
-## Product Object Model
+## 产品对象模型
-## 1. Project
+## 1. 项目(Project)
-Existing object. No fundamental change in role.
+现有对象。角色无根本变化。
-### Required behavior
+### 必要行为
-- can exist without code/workspace configuration
-- can have zero or more project workspaces
-- can define execution defaults that new issues inherit
+- 可以在没有代码/工作区配置的情况下存在
+- 可以有零个或多个项目工作区
+- 可以定义新 issue 继承的执行默认值
-### Proposed fields
+### 提议字段
- `id`
- `companyId`
@@ -199,26 +199,26 @@ Existing object. No fundamental change in role.
- `workspaces[]`
- `primaryWorkspace`
-## 2. Project Workspace
+## 2. 项目工作区(Project Workspace)
-Durable, configured, project-scoped codebase/root object.
+持久化的、已配置的、项目范围的代码库/根目录对象。
-This should evolve from the current `project_workspaces` table into a more explicit product object.
+这应该从当前的 `project_workspaces` 表演变为更明确的产品对象。
-### Motivation
+### 动机
-This separates:
+这将以下两个概念分离:
-- "what codebase/root does this project use?"
+- "该项目使用哪个代码库/根目录?"
-from:
+与:
-- "what temporary execution environment did this issue run in?"
+- "此 issue 在哪个临时执行环境中运行?"
-That keeps the model simple for solo users while still supporting advanced automation.
-It also lets cloud-hosted Paperclip deployments point at codebases and remotes without pretending the Paperclip host has direct filesystem access.
+这使模型对独立用户保持简单,同时仍支持高级自动化。
+它还允许云托管的 Paperclip 部署指向代码库和远程端,而无需假装 Paperclip 主机具有直接文件系统访问权限。
-### Proposed fields
+### 提议字段
- `id`
- `companyId`
@@ -242,31 +242,31 @@ It also lets cloud-hosted Paperclip deployments point at codebases and remotes w
- `createdAt`
- `updatedAt`
-### Notes
+### 说明
-- `sourceType=non_git_path` is important so non-git projects are first-class.
-- `setupCommand` and `cleanupCommand` should be allowed here for workspace-root bootstrap, even when isolated execution is not used.
-- For a monorepo, multiple project workspaces may point at different roots or packages under one repo.
-- `sourceType=remote_managed` is important for cloud deployments where the durable codebase is defined by provider/repo metadata rather than a local checkout path.
+- `sourceType=non_git_path` 很重要,使非 git 项目成为一等公民。
+- `setupCommand` 和 `cleanupCommand` 应在此处允许用于工作区根目录的引导,即使未使用隔离执行。
+- 对于 monorepo,多个项目工作区可以指向同一仓库下的不同根目录或包。
+- `sourceType=remote_managed` 对于云部署很重要,其中持久化代码库由提供商/仓库元数据定义,而非本地检出路径。
-## 3. Project Execution Workspace Policy
+## 3. 项目执行工作区策略(Project Execution Workspace Policy)
-Project-level defaults for how issues execute.
+issue 如何执行的项目级默认值。
-This is the main operator-facing configuration surface.
+这是面向运营者的主要配置界面。
-### Motivation
+### 动机
-This lets Paperclip support:
+这使 Paperclip 能够支持:
-- direct editing in a shared workspace
-- isolated workspaces for issue parallelism
-- long-lived integration branch workflows
-- remote cloud-agent execution that returns a branch or PR
+- 在共享工作区中直接编辑
+- 用于 issue 并行性的隔离工作区
+- 长期存在的集成分支工作流
+- 返回分支或 PR 的远程云代理执行
-without forcing every issue or agent to expose low-level runtime configuration.
+而无需强制每个 issue 或代理暴露低级运行时配置。
-### Proposed fields
+### 提议字段
- `enabled: boolean`
- `defaultMode`
@@ -314,23 +314,23 @@ without forcing every issue or agent to expose low-level runtime configuration.
- `keepWhilePreviewHealthy`
- `keepWhileOpenPrExists`
-## 4. Issue Workspace Binding
+## 4. Issue 工作区绑定(Issue Workspace Binding)
-Issue-level selection of execution behavior.
+issue 级别的执行行为选择。
-This should remain lightweight in the normal case and only surface richer controls when relevant.
+在正常情况下应保持轻量,仅在相关时才呈现更丰富的控件。
-### Motivation
+### 动机
-Not every issue in a code project should create a new derived workspace.
+代码项目中并非每个 issue 都应创建新的派生工作区。
-Examples:
+示例:
-- a tiny fix can run in the shared workspace
-- three related issues may intentionally share one integration branch
-- a solo operator may be working directly on `master`
+- 微小修复可以在共享工作区中运行
+- 三个相关 issue 可以有意共享一个集成分支
+- 独立运营者可能直接在 `master` 上工作
-### Proposed fields on `issues`
+### `issues` 上的提议字段
- `projectWorkspaceId: uuid | null`
- `executionWorkspacePreference`
@@ -343,35 +343,35 @@ Examples:
- `executionWorkspaceSettings`
- keep advanced per-issue override fields here
-### Rules
+### 规则
-- if the project has no workspace automation, these fields may all be null
-- if the project has one primary workspace, issue creation should default to it silently
-- `reuse_existing` is advanced-only and should target active execution workspaces, not the whole workspace universe
-- existing issues without these fields should behave as `inherit` during migration
+- 如果项目没有工作区自动化,这些字段可以都为 null
+- 如果项目有一个主工作区,issue 创建应默认静默使用它
+- `reuse_existing` 仅限高级用户,应针对活跃的执行工作区,而非整个工作区宇宙
+- 没有这些字段的现有 issue 在迁移期间应表现为 `inherit`
-## 5. Execution Workspace
+## 5. 执行工作区(Execution Workspace)
-A durable record for a shared or derived runtime workspace.
+共享或派生运行时工作区的持久化记录。
-This is the missing object that makes cleanup, previews, PRs, and branch reuse tractable.
+这是使清理、预览、PR 和分支复用变得可处理的缺失对象。
-### Motivation
+### 动机
-Without an explicit `execution workspace` record, Paperclip has nowhere stable to attach:
+没有明确的 `execution workspace` 记录,Paperclip 就没有稳定的地方来附加:
-- derived branch/worktree identity
-- active preview ownership
-- PR linkage
-- cleanup state
-- "reuse this existing integration branch" behavior
-- remote provider session identity
+- 派生分支/worktree 身份
+- 活跃预览所有权
+- PR 链接
+- 清理状态
+- "复用此现有集成分支"行为
+- 远程提供商会话身份
-### Proposed new object
+### 提议的新对象
`execution_workspaces`
-### Proposed fields
+### 提议字段
- `id`
- `companyId`
@@ -414,27 +414,27 @@ Without an explicit `execution workspace` record, Paperclip has nowhere stable t
- `createdAt`
- `updatedAt`
-### Notes
+### 说明
-- `sourceIssueId` is the issue that originally caused the workspace to be created, not necessarily the only issue linked to it later.
-- multiple issues may link to the same execution workspace in a long-lived branch workflow.
-- `cwd` may be null for remote execution workspaces; provider identity and work product links still make the object useful.
+- `sourceIssueId` 是最初导致工作区被创建的 issue,不一定是后来链接到它的唯一 issue。
+- 在长期存在的分支工作流中,多个 issue 可以链接到同一执行工作区。
+- 对于远程执行工作区,`cwd` 可以为 null;提供商身份和工作成果链接仍然使该对象有用。
-## 6. Issue-to-Execution Workspace Link
+## 6. Issue 到执行工作区的链接(Issue-to-Execution Workspace Link)
-An issue may need to link to one or more execution workspaces over time.
+随着时间推移,一个 issue 可能需要链接到一个或多个执行工作区。
-Examples:
+示例:
-- an issue begins in a shared workspace and later moves to an isolated one
-- a failed attempt is archived and a new workspace is created
-- several issues intentionally share one operator branch workspace
+- issue 开始于共享工作区,后来移至隔离的工作区
+- 失败的尝试被归档,并创建了新的工作区
+- 多个 issue 有意共享一个运营者分支工作区
-### Proposed object
+### 提议的对象
`issue_execution_workspaces`
-### Proposed fields
+### 提议字段
- `issueId`
- `executionWorkspaceId`
@@ -445,31 +445,31 @@ Examples:
- `createdAt`
- `updatedAt`
-### UI simplification
+### UI 简化
-Most issues should only show one current workspace in the main UI. Historical links belong in advanced/history views.
+大多数 issue 在主 UI 中只应显示一个当前工作区。历史链接属于高级/历史视图。
-## 7. Work Product
+## 7. 工作成果(Work Product)
-User-facing umbrella concept for outputs of work.
+面向用户的工作输出统一概念。
-### Motivation
+### 动机
-Paperclip needs a single place to show:
+Paperclip 需要一个统一的地方来显示:
-- "here is the preview"
-- "here is the PR"
-- "here is the branch"
-- "here is the commit"
-- "here is the artifact/report/doc"
+- "这是预览"
+- "这是 PR"
+- "这是分支"
+- "这是提交"
+- "这是制品/报告/文档"
-without turning issues into a raw dump of adapter details.
+而不是将 issue 变成适配器详细信息的原始转储。
-### Proposed new object
+### 提议的新对象
`issue_work_products`
-### Proposed fields
+### 提议字段
- `id`
- `companyId`
@@ -518,25 +518,25 @@ without turning issues into a raw dump of adapter details.
- `createdAt`
- `updatedAt`
-### Behavior
+### 行为
-- PRs are stored here as `type=pull_request`
-- previews are stored here as `type=preview_url` or `runtime_service`
-- Paperclip-owned processes should update health/status automatically
-- external providers should at least store link, provider, external id, and latest known state
-- cloud agents should be able to create work product records without Paperclip owning the execution host
+- PR 以 `type=pull_request` 存储在此处
+- 预览以 `type=preview_url` 或 `runtime_service` 存储在此处
+- Paperclip 拥有的进程应自动更新健康状态/状态
+- 外部提供商至少应存储链接、提供商、外部 ID 和最新已知状态
+- 云代理应能够在 Paperclip 不拥有执行主机的情况下创建工作成果记录
-## Page and UI Model
+## 页面和 UI 模型
-## 1. Global Navigation
+## 1. 全局导航
-Do not add `Workspaces` as a top-level sidebar item in V1.
+不要在 V1 中将 `Workspaces` 添加为顶级侧边栏项。
-### Motivation
+### 动机
-That would make the whole product feel infra-heavy, even for companies that do not use code automation.
+这会让整个产品感觉基础设施繁重,即使对于不使用代码自动化的公司也是如此。
-### Global nav remains
+### 全局导航保持不变
- Dashboard
- Inbox
@@ -547,73 +547,73 @@ That would make the whole product feel infra-heavy, even for companies that do n
- Issues
- Approvals
-Workspaces and work product should be surfaced through project and issue detail views.
+工作区和工作成果应通过项目和 issue 详情视图呈现。
-## 2. Project Detail
+## 2. 项目详情
-Add a project sub-navigation that keeps planning first and code second.
+添加项目子导航,将规划置于首位,代码置于其次。
-### Tabs
+### 标签页
- `Overview`
- `Issues`
- `Code`
- `Activity`
-Optional future:
+可选的未来扩展:
- `Outputs`
-### `Overview` tab
+### `Overview` 标签页
-Planning-first summary:
+以规划为主的摘要:
-- project status
-- goals
-- lead
-- issue counts
-- top-level progress
-- latest major work product summaries
+- 项目状态
+- 目标
+- 负责人
+- issue 数量
+- 顶层进度
+- 最新主要工作成果摘要
-### `Issues` tab
+### `Issues` 标签页
-- default to top-level issues only
-- show parent issue rollups:
- - child count
- - `x/y` done
- - active preview/PR badges
-- optional toggle: `Show subissues`
+- 默认只显示顶层 issue
+- 显示父 issue 汇总:
+ - 子 issue 数量
+ - `x/y` 已完成
+ - 活跃预览/PR 标记
+- 可选切换:`Show subissues`
-### `Code` tab
+### `Code` 标签页
-This is the main workspace configuration and visibility surface.
+这是主要的工作区配置和可见性界面。
-#### Section: `Project Workspaces`
+#### 区域:`Project Workspaces`
-List durable project workspaces for the project.
+列出项目的持久化项目工作区。
-Card/list columns:
+卡片/列表列:
-- workspace name
-- source type
-- path or repo
-- default ref
-- primary/default badge
-- active execution workspaces count
-- active issue count
-- active preview count
-- hosting type / provider when remote-managed
+- 工作区名称
+- 来源类型
+- 路径或仓库
+- 默认引用
+- 主要/默认标记
+- 活跃执行工作区数量
+- 活跃 issue 数量
+- 活跃预览数量
+- 远程管理时的托管类型/提供商
-Actions:
+操作:
- `Add workspace`
- `Edit`
- `Set default`
- `Archive`
-#### Section: `Execution Defaults`
+#### 区域:`Execution Defaults`
-Fields:
+字段:
- `Enable workspace automation`
- `Default issue execution mode`
@@ -624,9 +624,9 @@ Fields:
- `Default codebase`
- `Allow issue override`
-#### Section: `Provisioning`
+#### 区域:`Provisioning`
-Fields:
+字段:
- `Setup command`
- `Cleanup command`
@@ -638,12 +638,12 @@ Fields:
- `Branch naming template`
- `Derived workspace parent directory`
-Hide git-specific fields when the selected workspace is not git-backed.
-Hide local-path-specific fields when the selected workspace is remote-managed.
+当所选工作区不是 git 支持时,隐藏特定于 git 的字段。
+当所选工作区是远程管理时,隐藏特定于本地路径的字段。
-#### Section: `Pull Requests`
+#### 区域:`Pull Requests`
-Fields:
+字段:
- `PR workflow`
- `Disabled`
@@ -655,18 +655,18 @@ Fields:
- `PR title template`
- `PR body template`
-#### Section: `Previews and Runtime`
+#### 区域:`Previews and Runtime`
-Fields:
+字段:
- `Allow workspace runtime services`
- `Default services profile`
- `Harvest owned preview URLs`
- `Track external preview URLs`
-#### Section: `Cleanup`
+#### 区域:`Cleanup`
-Fields:
+字段:
- `Cleanup mode`
- `Manual`
@@ -677,11 +677,11 @@ Fields:
- `Keep while preview is active`
- `Keep while PR is open`
-## 3. Add Project Workspace Flow
+## 3. 添加项目工作区流程
-Entry point: `Project > Code > Add workspace`
+入口点:`Project > Code > Add workspace`
-### Form fields
+### 表单字段
- `Name`
- `Source type`
@@ -698,71 +698,71 @@ Entry point: `Project > Code > Add workspace`
- `Setup command`
- `Cleanup command`
-### Behavior
+### 行为
-- if source type is non-git, hide branch/PR-specific setup
-- if source type is git, show ref and optional advanced branch fields
-- if source type is remote-managed, show provider/reference fields and hide local-path-only configuration
-- for simple solo users, this can be one path field and one save button
+- 如果来源类型是非 git,隐藏特定于分支/PR 的设置
+- 如果来源类型是 git,显示引用和可选的高级分支字段
+- 如果来源类型是远程管理,显示提供商/引用字段并隐藏仅限本地路径的配置
+- 对于简单的独立用户,这可以是一个路径字段和一个保存按钮
-## 4. Issue Create Flow
+## 4. Issue 创建流程
-Issue creation should stay simple by default.
+Issue 创建默认应保持简单。
-### Default behavior
+### 默认行为
-If the selected project:
+如果选定的项目:
-- has no workspace automation: show no workspace UI
-- has one default project workspace and default execution mode: inherit silently
+- 没有工作区自动化:不显示工作区 UI
+- 有一个默认项目工作区和默认执行模式:静默继承
-### Show a `Workspace` section only when relevant
+### 仅在相关时显示 `Workspace` 区域
-#### Basic fields
+#### 基本字段
- `Codebase`
- - default selected project workspace
+ - 默认选定的项目工作区
- `Execution mode`
- `Project default`
- `Shared workspace`
- `Isolated workspace`
- `Operator branch`
-#### Advanced-only field
+#### 仅限高级用户的字段
- `Reuse existing execution workspace`
-This dropdown should show only active execution workspaces for the selected project workspace, with labels like:
+此下拉菜单应仅显示所选项目工作区的活跃执行工作区,标签如:
- `dotta/integration-branch`
- `PAP-447-add-worktree-support`
- `shared primary workspace`
-### Important rule
+### 重要规则
-Do not show a picker containing every possible workspace object by default.
+默认不要显示包含所有可能工作区对象的选择器。
-The normal flow should feel like:
+正常流程应感觉像:
-- choose project
-- optionally choose codebase
-- optionally choose execution mode
+- 选择项目
+- 可选择代码库
+- 可选择执行模式
-not:
+而非:
-- choose from a long mixed list of roots, derived worktrees, previews, and branch names
+- 从根目录、派生 worktree、预览和分支名称的长混合列表中选择
-### Migration rule
+### 迁移规则
-For existing users, issue creation should continue to look the same until a project explicitly enables richer workspace behavior.
+对于现有用户,issue 创建应继续看起来相同,直到项目明确启用更丰富的工作区行为。
-## 5. Issue Detail
+## 5. Issue 详情
-Issue detail should expose workspace and work product clearly, but without becoming a code host UI.
+Issue 详情应清晰地暴露工作区和工作成果,但不应成为代码托管 UI。
-### Header chips
+### 标题标签
-Show compact summary chips near the title/status area:
+在标题/状态区域附近显示紧凑的摘要标签:
- `Codebase: Web App`
- `Workspace: Shared`
@@ -770,16 +770,16 @@ Show compact summary chips near the title/status area:
- `PR: Open`
- `Preview: Healthy`
-### Tabs
+### 标签页
- `Comments`
- `Subissues`
- `Work Product`
- `Activity`
-### `Work Product` tab
+### `Work Product` 标签页
-Sections:
+区域:
- `Current workspace`
- `Previews`
@@ -787,114 +787,114 @@ Sections:
- `Branches and commits`
- `Artifacts and documents`
-#### Current workspace panel
+#### 当前工作区面板
-Fields:
+字段:
-- workspace name
-- mode
-- branch
-- base ref
-- last used
-- linked issues count
-- cleanup status
+- 工作区名称
+- 模式
+- 分支
+- 基础引用
+- 最后使用时间
+- 链接的 issue 数量
+- 清理状态
-Actions:
+操作:
- `Open workspace details`
- `Mark in review`
- `Request cleanup`
-#### Pull request cards
+#### Pull request 卡片
-Fields:
+字段:
-- title
-- provider
-- status
-- review state
-- linked branch
-- open/ready/merged timestamps
+- 标题
+- 提供商
+- 状态
+- 审查状态
+- 链接的分支
+- 开启/就绪/合并时间戳
-Actions:
+操作:
- `Open PR`
- `Refresh status`
- `Request board review`
-#### Preview cards
+#### 预览卡片
-Fields:
+字段:
-- title
+- 标题
- URL
-- provider
-- health
-- ownership
-- updated at
+- 提供商
+- 健康状态
+- 所有权
+- 更新时间
-Actions:
+操作:
- `Open preview`
- `Refresh`
- `Archive`
-## 6. Execution Workspace Detail
+## 6. 执行工作区详情
-This can be reached from a project code tab or an issue work product tab.
+可从项目代码标签页或 issue 工作成果标签页访问。
-It does not need to be in the main sidebar.
+不需要在主侧边栏中。
-### Sections
+### 区域
-- identity
-- source issue
-- linked issues
-- branch/ref
-- provider/session identity
-- active runtime services
-- previews
-- PRs
-- cleanup state
-- event/activity history
+- 身份标识
+- 来源 issue
+- 链接的 issue
+- 分支/引用
+- 提供商/会话身份
+- 活跃运行时服务
+- 预览
+- PR
+- 清理状态
+- 事件/活动历史
-### Motivation
+### 动机
-This is where advanced users go when they need to inspect the mechanics. Most users should not need it in normal flow.
+这是高级用户在需要检查机制时去的地方。大多数用户在正常流程中不需要它。
-## 7. Inbox Behavior
+## 7. 收件箱行为
-Inbox should surface actionable work product events, not every implementation detail.
+收件箱应呈现可操作的工作成果事件,而非每个实现细节。
-### Show inbox items for
+### 显示收件箱条目的情况
-- issue assigned or updated
-- PR needs board review
-- PR opened or marked ready
-- preview unhealthy
-- workspace cleanup failed
-- runtime service failed
-- remote cloud-agent run returned PR or preview that needs review
+- issue 被分配或更新
+- PR 需要看板审查
+- PR 被打开或标记为就绪
+- 预览不健康
+- 工作区清理失败
+- 运行时服务失败
+- 远程云代理运行返回了需要审查的 PR 或预览
-### Do not show by default
+### 默认不显示
-- every workspace heartbeat
-- every branch update
-- every derived workspace creation
+- 每次工作区心跳
+- 每次分支更新
+- 每次派生工作区创建
-### Display style
+### 显示样式
-If the inbox item is about a preview or PR, show issue context with it:
+如果收件箱条目是关于预览或 PR 的,随之显示 issue 上下文:
-- issue identifier and title
-- parent issue if this is a subissue
-- workspace name if relevant
+- issue 标识符和标题
+- 如果这是子 issue,显示父 issue
+- 如果相关,显示工作区名称
-## 8. Issues List and Kanban
+## 8. Issue 列表和看板
-Keep list and board planning-first.
+保持列表和看板以规划为主。
-### Default behavior
+### 默认行为
- show top-level issues by default
- show parent rollups for subissues
diff --git a/doc/plans/2026-03-14-adapter-skill-sync-rollout.md b/doc/plans/2026-03-14-adapter-skill-sync-rollout.md
index e062b7dde8..65446b9b6f 100644
--- a/doc/plans/2026-03-14-adapter-skill-sync-rollout.md
+++ b/doc/plans/2026-03-14-adapter-skill-sync-rollout.md
@@ -1,27 +1,27 @@
-# 2026-03-14 Adapter Skill Sync Rollout
+# 2026-03-14 适配器技能同步上线计划
-Status: Proposed
-Date: 2026-03-14
-Audience: Product and engineering
-Related:
+状态:提议中
+日期:2026-03-14
+受众:产品和工程团队
+相关文档:
- `doc/plans/2026-03-14-skills-ui-product-plan.md`
- `doc/plans/2026-03-13-company-import-export-v2.md`
- `docs/companies/companies-spec.md`
-## 1. Purpose
+## 1. 目的
-This document defines the rollout plan for adapter-wide skill support in Paperclip.
+本文档定义了 Paperclip 全适配器技能支持的上线计划。
-The goal is not just “show a skills tab.” The goal is:
+目标不仅仅是"显示一个技能标签页"。真正的目标是:
-- every adapter has a deliberate skill-sync truth model
-- the UI tells the truth for that adapter
-- Paperclip stores desired skill state consistently even when the adapter cannot fully reconcile it
-- unsupported adapters degrade clearly and safely
+- 每个适配器都有一个经过深思熟虑的技能同步真相模型
+- UI 如实反映该适配器的状态
+- 即使适配器无法完全协调,Paperclip 也能一致地存储期望的技能状态
+- 不受支持的适配器能够清晰、安全地降级
-## 2. Current Adapter Matrix
+## 2. 当前适配器矩阵
-Paperclip currently has these adapters:
+Paperclip 目前拥有以下适配器:
- `claude_local`
- `codex_local`
@@ -31,369 +31,369 @@ Paperclip currently has these adapters:
- `pi_local`
- `openclaw_gateway`
-The current skill API supports:
+当前技能 API 支持的模式:
- `unsupported`
- `persistent`
- `ephemeral`
-Current implementation state:
+当前实现状态:
-- `codex_local`: implemented, `persistent`
-- `claude_local`: implemented, `ephemeral`
-- `cursor_local`: not yet implemented, but technically suited to `persistent`
-- `gemini_local`: not yet implemented, but technically suited to `persistent`
-- `pi_local`: not yet implemented, but technically suited to `persistent`
-- `opencode_local`: not yet implemented; likely `persistent`, but with special handling because it currently injects into Claude’s shared skills home
-- `openclaw_gateway`: not yet implemented; blocked on gateway protocol support, so `unsupported` for now
+- `codex_local`:已实现,`persistent`
+- `claude_local`:已实现,`ephemeral`
+- `cursor_local`:尚未实现,但技术上适合 `persistent`
+- `gemini_local`:尚未实现,但技术上适合 `persistent`
+- `pi_local`:尚未实现,但技术上适合 `persistent`
+- `opencode_local`:尚未实现;可能适合 `persistent`,但需要特殊处理,因为它目前注入到 Claude 的共享技能主目录中
+- `openclaw_gateway`:尚未实现;受网关协议支持阻塞,暂时为 `unsupported`
-## 3. Product Principles
+## 3. 产品原则
-1. Desired skills live in Paperclip for every adapter.
-2. Adapters may expose different truth models, and the UI must reflect that honestly.
-3. Persistent adapters should read and reconcile actual installed state.
-4. Ephemeral adapters should report effective runtime state, not pretend they own a persistent install.
-5. Shared-home adapters need stronger safeguards than isolated-home adapters.
-6. Gateway or cloud adapters must not fake local filesystem sync.
+1. 期望的技能对每个适配器都存储在 Paperclip 中。
+2. 适配器可能暴露不同的真相模型,UI 必须如实反映。
+3. 持久化适配器应该读取并协调实际安装状态。
+4. 临时适配器应该报告有效的运行时状态,而不是假装拥有持久化安装。
+5. 共享主目录的适配器比隔离主目录的适配器需要更强的安全措施。
+6. 网关或云适配器不得伪造本地文件系统同步。
-## 4. Adapter Classification
+## 4. 适配器分类
-### 4.1 Persistent local-home adapters
+### 4.1 持久化本地主目录适配器
-These adapters have a stable local skills directory that Paperclip can read and manage.
+这些适配器具有稳定的本地技能目录,Paperclip 可以读取和管理。
-Candidates:
+候选适配器:
- `codex_local`
- `cursor_local`
- `gemini_local`
- `pi_local`
-- `opencode_local` with caveats
+- `opencode_local`(有注意事项)
-Expected UX:
+预期用户体验:
-- show actual installed skills
-- show managed vs external skills
-- support `sync`
-- support stale removal
-- preserve unknown external skills
+- 显示实际已安装的技能
+- 显示受管理与外部技能
+- 支持 `sync`(同步)
+- 支持清除过期技能
+- 保留未知的外部技能
-### 4.2 Ephemeral mount adapters
+### 4.2 临时挂载适配器
-These adapters do not have a meaningful Paperclip-owned persistent install state.
+这些适配器没有由 Paperclip 拥有的有意义的持久化安装状态。
-Current adapter:
+当前适配器:
- `claude_local`
-Expected UX:
+预期用户体验:
-- show desired Paperclip skills
-- show any discoverable external dirs if available
-- say “mounted on next run” instead of “installed”
-- do not imply a persistent adapter-owned install state
+- 显示 Paperclip 期望的技能
+- 如果可用,显示可发现的外部目录
+- 显示"下次运行时挂载"而非"已安装"
+- 不暗示存在由适配器拥有的持久化安装状态
-### 4.3 Unsupported / remote adapters
+### 4.3 不支持/远程适配器
-These adapters cannot support skill sync without new external capabilities.
+这些适配器在没有新的外部能力的情况下无法支持技能同步。
-Current adapter:
+当前适配器:
- `openclaw_gateway`
-Expected UX:
+预期用户体验:
-- company skill library still works
-- agent attachment UI still works at the desired-state level
-- actual adapter state is `unsupported`
-- sync button is disabled or replaced with explanatory text
+- 公司技能库仍然可用
+- 代理附加 UI 仍然在期望状态层面工作
+- 实际适配器状态为 `unsupported`
+- 同步按钮被禁用或替换为说明文字
-## 5. Per-Adapter Plan
+## 5. 各适配器计划
### 5.1 Codex Local
-Target mode:
+目标模式:
- `persistent`
-Current state:
+当前状态:
-- already implemented
+- 已实现
-Requirements to finish:
+完成所需工作:
-- keep as reference implementation
-- tighten tests around external custom skills and stale removal
-- ensure imported company skills can be attached and synced without manual path work
+- 保持作为参考实现
+- 加强外部自定义技能和过期清除的测试
+- 确保导入的公司技能可以被附加和同步,无需手动路径操作
-Success criteria:
+成功标准:
-- list installed managed and external skills
-- sync desired skills into `CODEX_HOME/skills`
-- preserve external user-managed skills
+- 列出已安装的受管理和外部技能
+- 将期望的技能同步到 `CODEX_HOME/skills`
+- 保留外部用户管理的技能
### 5.2 Claude Local
-Target mode:
+目标模式:
- `ephemeral`
-Current state:
+当前状态:
-- already implemented
+- 已实现
-Requirements to finish:
+完成所需工作:
-- polish status language in UI
-- clearly distinguish “desired” from “mounted on next run”
-- optionally surface configured external skill dirs if Claude exposes them
+- 优化 UI 中的状态语言
+- 清晰区分"期望"和"下次运行时挂载"
+- 可选地展示已配置的外部技能目录(如果 Claude 公开了这些信息)
-Success criteria:
+成功标准:
-- desired skills stored in Paperclip
-- selected skills mounted per run
-- no misleading “installed” language
+- 期望的技能存储在 Paperclip 中
+- 选中的技能按次运行时挂载
+- 没有误导性的"已安装"用语
### 5.3 Cursor Local
-Target mode:
+目标模式:
- `persistent`
-Technical basis:
+技术基础:
-- runtime already injects Paperclip skills into `~/.cursor/skills`
+- 运行时已将 Paperclip 技能注入到 `~/.cursor/skills`
-Implementation work:
+实现工作:
-1. Add `listSkills` for Cursor.
-2. Add `syncSkills` for Cursor.
-3. Reuse the same managed-symlink pattern as Codex.
-4. Distinguish:
- - managed Paperclip skills
- - external skills already present
- - missing desired skills
- - stale managed skills
+1. 为 Cursor 添加 `listSkills`。
+2. 为 Cursor 添加 `syncSkills`。
+3. 复用与 Codex 相同的受管理符号链接模式。
+4. 区分:
+ - 受管理的 Paperclip 技能
+ - 已存在的外部技能
+ - 缺失的期望技能
+ - 过期的受管理技能
-Testing:
+测试:
-- unit tests for discovery
-- unit tests for sync and stale removal
-- verify shared auth/session setup is not disturbed
+- 发现功能的单元测试
+- 同步和过期清除的单元测试
+- 验证共享的认证/会话设置不受干扰
-Success criteria:
+成功标准:
-- Cursor agents show real installed state
-- syncing from the agent Skills tab works
+- Cursor 代理显示真实的安装状态
+- 从代理技能标签页进行同步可以正常工作
### 5.4 Gemini Local
-Target mode:
+目标模式:
- `persistent`
-Technical basis:
+技术基础:
-- runtime already injects Paperclip skills into `~/.gemini/skills`
+- 运行时已将 Paperclip 技能注入到 `~/.gemini/skills`
-Implementation work:
+实现工作:
-1. Add `listSkills` for Gemini.
-2. Add `syncSkills` for Gemini.
-3. Reuse managed-symlink conventions from Codex/Cursor.
-4. Verify auth remains untouched while skills are reconciled.
+1. 为 Gemini 添加 `listSkills`。
+2. 为 Gemini 添加 `syncSkills`。
+3. 复用 Codex/Cursor 的受管理符号链接约定。
+4. 验证在协调技能时认证保持不变。
-Potential caveat:
+潜在注意事项:
-- if Gemini treats that skills directory as shared user state, the UI should warn before removing stale managed skills
+- 如果 Gemini 将该技能目录视为共享用户状态,UI 应在删除过期受管理技能前发出警告
-Success criteria:
+成功标准:
-- Gemini agents can reconcile desired vs actual skill state
+- Gemini 代理可以协调期望状态与实际技能状态
### 5.5 Pi Local
-Target mode:
+目标模式:
- `persistent`
-Technical basis:
+技术基础:
-- runtime already injects Paperclip skills into `~/.pi/agent/skills`
+- 运行时已将 Paperclip 技能注入到 `~/.pi/agent/skills`
-Implementation work:
+实现工作:
-1. Add `listSkills` for Pi.
-2. Add `syncSkills` for Pi.
-3. Reuse managed-symlink helpers.
-4. Verify session-file behavior remains independent from skill sync.
+1. 为 Pi 添加 `listSkills`。
+2. 为 Pi 添加 `syncSkills`。
+3. 复用受管理符号链接辅助工具。
+4. 验证会话文件行为与技能同步保持独立。
-Success criteria:
+成功标准:
-- Pi agents expose actual installed skill state
-- Paperclip can sync desired skills into Pi’s persistent home
+- Pi 代理暴露实际已安装的技能状态
+- Paperclip 可以将期望的技能同步到 Pi 的持久化主目录
### 5.6 OpenCode Local
-Target mode:
+目标模式:
- `persistent`
-Special case:
+特殊情况:
-- OpenCode currently injects Paperclip skills into `~/.claude/skills`
+- OpenCode 目前将 Paperclip 技能注入到 `~/.claude/skills`
-This is product-risky because:
+这在产品层面存在风险,因为:
-- it shares state with Claude
-- Paperclip may accidentally imply the skills belong only to OpenCode when the home is shared
+- 它与 Claude 共享状态
+- 当主目录是共享的时,Paperclip 可能会意外暗示这些技能仅属于 OpenCode
-Plan:
+计划:
-Phase 1:
+第一阶段:
-- implement `listSkills` and `syncSkills`
-- treat it as `persistent`
-- explicitly label the home as shared in UI copy
-- only remove stale managed Paperclip skills that are clearly marked as Paperclip-managed
+- 实现 `listSkills` 和 `syncSkills`
+- 将其视为 `persistent`
+- 在 UI 文案中明确标注该主目录为共享
+- 仅删除明确标记为 Paperclip 管理的过期受管理技能
-Phase 2:
+第二阶段:
-- investigate whether OpenCode supports its own isolated skills home
-- if yes, migrate to an adapter-specific home and remove the shared-home caveat
+- 调查 OpenCode 是否支持其自己的隔离技能主目录
+- 如果支持,迁移到适配器专属主目录并消除共享主目录的注意事项
-Success criteria:
+成功标准:
-- OpenCode agents show real state
-- shared-home risk is visible and bounded
+- OpenCode 代理显示真实状态
+- 共享主目录风险可见且受控
### 5.7 OpenClaw Gateway
-Target mode:
+目标模式:
-- `unsupported` until gateway protocol support exists
+- 在网关协议支持可用之前为 `unsupported`
-Required external work:
+所需的外部工作:
-- gateway API to list installed/available skills
-- gateway API to install/remove or otherwise reconcile skills
-- gateway metadata for whether state is persistent or ephemeral
+- 列出已安装/可用技能的网关 API
+- 安装/删除或以其他方式协调技能的网关 API
+- 状态是持久化还是临时的网关元数据
-Until then:
+在此之前:
-- Paperclip stores desired skills only
-- UI shows unsupported actual state
-- no fake sync implementation
+- Paperclip 仅存储期望的技能
+- UI 显示不支持的实际状态
+- 不提供伪造的同步实现
-Future target:
+未来目标:
-- likely a fourth truth model eventually, such as remote-managed persistent state
-- for now, keep the current API and treat gateway as unsupported
+- 最终可能出现第四种真相模型,例如远程管理的持久化状态
+- 目前保持当前 API,将网关视为不支持
-## 6. API Plan
+## 6. API 计划
-## 6.1 Keep the current minimal adapter API
+## 6.1 保持当前最小化的适配器 API
-Near-term adapter contract remains:
+近期适配器契约保持不变:
- `listSkills(ctx)`
- `syncSkills(ctx, desiredSkills)`
-This is enough for all local adapters.
+这对所有本地适配器已经足够。
-## 6.2 Optional extension points
+## 6.2 可选扩展点
-Add only if needed after the first broad rollout:
+仅在首次广泛上线后根据需要添加:
- `skillHomeLabel`
- `sharedHome: boolean`
- `supportsExternalDiscovery: boolean`
- `supportsDestructiveSync: boolean`
-These should be optional metadata additions to the snapshot, not required new adapter methods.
+这些应该是快照的可选元数据补充,而不是必需的新适配器方法。
-## 7. UI Plan
+## 7. UI 计划
-The company-level skill library can stay adapter-neutral.
+公司级技能库可以保持适配器无关。
-The agent-level Skills tab must become adapter-aware by copy and status:
+代理级技能标签页必须通过文案和状态变得适配器感知:
-- `persistent`: installed / missing / stale / external
-- `ephemeral`: mounted on next run / external / desired only
-- `unsupported`: desired only, adapter cannot report actual state
+- `persistent`:已安装 / 缺失 / 过期 / 外部
+- `ephemeral`:下次运行时挂载 / 外部 / 仅期望
+- `unsupported`:仅期望,适配器无法报告实际状态
-Additional UI requirement for shared-home adapters:
+共享主目录适配器的额外 UI 要求:
-- show a small warning that the adapter uses a shared user skills home
-- avoid destructive wording unless Paperclip can prove a skill is Paperclip-managed
+- 显示一个小警告,说明该适配器使用共享的用户技能主目录
+- 除非 Paperclip 能证明某个技能是 Paperclip 管理的,否则避免使用破坏性措辞
-## 8. Rollout Phases
+## 8. 上线阶段
-### Phase 1: Finish the local filesystem family
+### 第一阶段:完成本地文件系统家族
-Ship:
+发布:
- `cursor_local`
- `gemini_local`
- `pi_local`
-Rationale:
+理由:
-- these are the closest to Codex in architecture
-- they already inject into stable local skill homes
+- 这些在架构上最接近 Codex
+- 它们已经注入到稳定的本地技能主目录
-### Phase 2: OpenCode shared-home support
+### 第二阶段:OpenCode 共享主目录支持
-Ship:
+发布:
- `opencode_local`
-Rationale:
+理由:
-- technically feasible now
-- needs slightly more careful product language because of the shared Claude skills home
+- 技术上现在就可以实现
+- 由于共享 Claude 技能主目录,需要稍微更谨慎的产品用语
-### Phase 3: Gateway support decision
+### 第三阶段:网关支持决策
-Decide:
+决定:
-- keep `openclaw_gateway` unsupported for V1
-- or extend the gateway protocol for remote skill management
+- V1 保持 `openclaw_gateway` 不支持
+- 或扩展网关协议以支持远程技能管理
-My recommendation:
+我的建议:
-- do not block V1 on gateway support
-- keep it explicitly unsupported until the remote protocol exists
+- 不要因为网关支持而阻塞 V1
+- 在远程协议存在之前明确保持不支持状态
-## 9. Definition Of Done
+## 9. 完成定义
-Adapter-wide skill support is ready when all are true:
+全适配器技能支持在以下条件全部满足时视为就绪:
-1. Every adapter has an explicit truth model:
+1. 每个适配器都有明确的真相模型:
- `persistent`
- `ephemeral`
- `unsupported`
-2. The UI copy matches that truth model.
-3. All local persistent adapters implement:
+2. UI 文案与该真相模型匹配。
+3. 所有本地持久化适配器都实现了:
- `listSkills`
- `syncSkills`
-4. Tests cover:
- - desired-state storage
- - actual-state discovery
- - managed vs external distinctions
- - stale managed-skill cleanup where supported
-5. `openclaw_gateway` is either:
- - explicitly unsupported with clean UX
- - or backed by a real remote skill API
+4. 测试覆盖:
+ - 期望状态存储
+ - 实际状态发现
+ - 受管理与外部的区分
+ - 支持的场景下的过期受管理技能清理
+5. `openclaw_gateway` 要么:
+ - 明确不支持并具有清晰的用户体验
+ - 要么由真实的远程技能 API 支撑
-## 10. Recommendation
+## 10. 建议
-The recommended immediate order is:
+推荐的即时执行顺序为:
1. `cursor_local`
2. `gemini_local`
3. `pi_local`
4. `opencode_local`
-5. defer `openclaw_gateway`
+5. 推迟 `openclaw_gateway`
-That gets Paperclip from “skills work for Codex and Claude” to “skills work for the whole local-adapter family,” which is the meaningful V1 milestone.
+这将使 Paperclip 从"技能仅对 Codex 和 Claude 有效"升级到"技能对整个本地适配器家族有效",这才是有意义的 V1 里程碑。
diff --git a/doc/plans/2026-03-14-billing-ledger-and-reporting.md b/doc/plans/2026-03-14-billing-ledger-and-reporting.md
index 3c0b210c64..9c79ccfe9e 100644
--- a/doc/plans/2026-03-14-billing-ledger-and-reporting.md
+++ b/doc/plans/2026-03-14-billing-ledger-and-reporting.md
@@ -1,190 +1,190 @@
-# Billing Ledger and Reporting
+# 计费账本与报告
-## Context
+## 背景
-Paperclip currently stores model spend in `cost_events` and operational run state in `heartbeat_runs`.
-That split is fine, but the current reporting code tries to infer billing semantics by mixing both tables:
+Paperclip 目前将模型费用存储在 `cost_events` 中,将运行操作状态存储在 `heartbeat_runs` 中。
+这种拆分本身没有问题,但当前的报告代码试图通过混合使用这两张表来推断计费语义:
-- `cost_events` knows provider, model, tokens, and dollars
-- `heartbeat_runs.usage_json` knows some per-run billing metadata
-- `heartbeat_runs.usage_json` does **not** currently carry enough normalized billing dimensions to support honest provider-level reporting
+- `cost_events` 包含提供商、模型、token 数量和金额信息
+- `heartbeat_runs.usage_json` 包含部分每次运行的计费元数据
+- `heartbeat_runs.usage_json` 目前**不**包含足够规范化的计费维度,无法支持准确的提供商级报告
-This becomes incorrect as soon as a company uses more than one provider, more than one billing channel, or more than one billing mode.
+一旦某家公司使用了多个提供商、多个计费渠道或多种计费模式,现有系统就会出现错误。
-Examples:
+示例:
-- direct OpenAI API usage
-- Claude subscription usage with zero marginal dollars
-- subscription overage with dollars and tokens
-- OpenRouter billing where the biller is OpenRouter but the upstream provider is Anthropic or OpenAI
+- 直接使用 OpenAI API
+- Claude 订阅用量,边际费用为零
+- 订阅超额使用,含金额和 token
+- OpenRouter 计费,其中计费方为 OpenRouter,但上游提供商是 Anthropic 或 OpenAI
-The system needs to support:
+系统需要支持:
-- dollar reporting
-- token reporting
-- subscription-included usage
-- subscription overage
-- direct metered API usage
-- future aggregator billing such as OpenRouter
+- 金额报告
+- token 报告
+- 订阅内含用量
+- 订阅超额用量
+- 直接计量 API 用量
+- 未来的聚合商计费(如 OpenRouter)
-## Product Decision
+## 产品决策
-`cost_events` becomes the canonical billing and usage ledger for reporting.
+`cost_events` 成为报告所用的权威计费与用量账本。
-`heartbeat_runs` remains an operational execution log. It may keep mirrored billing metadata for debugging and transcripts, but reporting must not reconstruct billing semantics from `heartbeat_runs.usage_json`.
+`heartbeat_runs` 保持为运行操作日志。它可以保留镜像的计费元数据用于调试和记录,但报告不得从 `heartbeat_runs.usage_json` 中重建计费语义。
-## Decision: One Ledger Or Two
+## 决策:单一账本还是两张表
-We do **not** need two tables to solve the current PR's problem.
-For request-level inference reporting, `cost_events` is enough if it carries the right dimensions:
+解决当前 PR 的问题**不需要**两张表。
+对于请求级推理报告,只要 `cost_events` 携带了正确的维度即可满足需求:
-- upstream provider
-- biller
-- billing type
-- model
-- token fields
-- billed amount
+- 上游提供商
+- 计费方
+- 计费类型
+- 模型
+- token 字段
+- 计费金额
-That is why the first implementation pass extends `cost_events` instead of introducing a second table immediately.
+这就是为什么第一阶段实现选择扩展 `cost_events`,而不是立即引入第二张表。
-However, if Paperclip needs to account for the full billing surface of aggregators and managed AI platforms, then `cost_events` alone is not enough.
-Some charges are not cleanly representable as a single model inference event:
+但是,如果 Paperclip 需要覆盖聚合商和托管 AI 平台的完整计费面,则 `cost_events` 单独是不够的。
+某些费用无法简洁地表示为单次模型推理事件:
-- account top-ups and credit purchases
-- platform fees charged at purchase time
-- BYOK platform fees that are account-level or threshold-based
-- prepaid credit expirations, refunds, and adjustments
-- provisioned throughput commitments
-- fine-tuning, training, model import, and storage charges
-- gateway logging or other platform overhead that is not attributable to one prompt/response pair
+- 账户充值和积分购买
+- 购买时收取的平台费用
+- 账户级或基于阈值的 BYOK 平台费用
+- 预付积分到期、退款和调整
+- 预留吞吐量承诺
+- 微调、训练、模型导入和存储费用
+- 网关日志记录或其他无法归因于单次提示/响应对的平台开销
-So the decision is:
+因此,决策如下:
-- near term: keep `cost_events` as the inference and usage ledger
-- next phase: add `finance_events` for non-inference financial events
+- 近期:保留 `cost_events` 作为推理和用量账本
+- 下一阶段:添加 `finance_events` 用于非推理类财务事件
-This is a deliberate split between:
+这是有意为之的拆分,区分了:
-- usage and inference accounting
-- account-level and platform-level financial accounting
+- 用量与推理会计
+- 账户级和平台级财务会计
-That separation keeps request reporting honest without forcing us to fake invoice semantics onto rows that were never request-scoped.
+这种分离确保请求报告的准确性,避免将从未属于请求范围的行强行套入发票语义。
-## External Motivation And Sources
+## 外部动因与来源
-The need for this model is not theoretical.
-It follows directly from the billing systems of providers and aggregators Paperclip needs to support.
+对此模型的需求并非纯粹理论性的。
+它直接来源于 Paperclip 需要支持的各提供商和聚合商的计费系统。
### OpenRouter
-Source URLs:
+来源 URL:
- https://openrouter.ai/docs/faq#credit-and-billing-systems
- https://openrouter.ai/pricing
-Relevant billing behavior as of March 14, 2026:
+截至 2026 年 3 月 14 日的相关计费行为:
-- OpenRouter passes through underlying inference pricing and deducts request cost from purchased credits.
-- OpenRouter charges a 5.5% fee with a $0.80 minimum when purchasing credits.
-- Crypto payments are charged a 5% fee.
-- BYOK has its own fee model after a free request threshold.
-- OpenRouter billing is aggregated at the OpenRouter account level even when the upstream provider is Anthropic, OpenAI, Google, or another provider.
+- OpenRouter 转发底层推理定价,并从已购买的积分中扣除请求费用。
+- 购买积分时,OpenRouter 收取 5.5% 的手续费,最低 0.80 美元。
+- 加密货币支付收取 5% 的手续费。
+- BYOK 在超出免费请求阈值后采用其自有收费模式。
+- 即使上游提供商是 Anthropic、OpenAI、Google 或其他提供商,OpenRouter 的计费也在 OpenRouter 账户层面进行汇总。
-Implication for Paperclip:
+对 Paperclip 的影响:
-- request usage belongs in `cost_events`
-- credit purchases, purchase fees, BYOK fees, refunds, and expirations belong in `finance_events`
-- `biller=openrouter` must remain distinct from `provider=anthropic|openai|google|...`
+- 请求用量归入 `cost_events`
+- 积分购买、购买手续费、BYOK 费用、退款和到期归入 `finance_events`
+- `biller=openrouter` 必须与 `provider=anthropic|openai|google|...` 保持明确区分
-### Cloudflare AI Gateway Unified Billing
+### Cloudflare AI Gateway 统一计费
-Source URL:
+来源 URL:
- https://developers.cloudflare.com/ai-gateway/features/unified-billing/
-Relevant billing behavior as of March 14, 2026:
+截至 2026 年 3 月 14 日的相关计费行为:
-- Unified Billing lets users call multiple upstream providers while receiving a single Cloudflare bill.
-- Usage is paid from Cloudflare-loaded credits.
-- Cloudflare supports manual top-ups and auto top-up thresholds.
-- Spend limits can stop request processing on daily, weekly, or monthly boundaries.
-- Unified Billing traffic can use Cloudflare-managed credentials rather than the user's direct provider key.
+- 统一计费允许用户调用多个上游提供商,同时只收到一张 Cloudflare 账单。
+- 用量从 Cloudflare 充值的积分中支付。
+- Cloudflare 支持手动充值和自动充值阈值。
+- 消费限额可按日、周或月边界停止请求处理。
+- 统一计费流量可使用 Cloudflare 管理的凭证,而非用户的直接提供商密钥。
-Implication for Paperclip:
+对 Paperclip 的影响:
-- request usage needs `biller=cloudflare`
-- upstream provider still needs to be preserved separately
-- Cloudflare credit loads and related account-level events are not inference rows and should not be forced into `cost_events`
-- quota and limits reporting must support biller-level controls, not just upstream provider limits
+- 请求用量需要设置 `biller=cloudflare`
+- 上游提供商仍需单独保留
+- Cloudflare 积分充值及相关账户级事件不属于推理行,不应强行写入 `cost_events`
+- 配额和限额报告必须支持计费方级别的控制,而不仅仅是上游提供商的限制
### Amazon Bedrock
-Source URL:
+来源 URL:
- https://aws.amazon.com/bedrock/pricing/
-Relevant billing behavior as of March 14, 2026:
+截至 2026 年 3 月 14 日的相关计费行为:
-- Bedrock supports on-demand and batch pricing.
-- Bedrock pricing varies by region.
-- some pricing tiers add premiums or discounts relative to standard pricing
-- provisioned throughput is commitment-based rather than request-based
-- custom model import uses Custom Model Units billed per minute, with monthly storage charges
-- imported model copies are billed in 5-minute windows once active
-- customization and fine-tuning introduce training and hosted-model charges beyond normal inference
+- Bedrock 支持按需定价和批量定价。
+- Bedrock 定价因区域而异。
+- 部分定价层级相对标准定价有溢价或折扣
+- 预留吞吐量基于承诺而非按请求计费
+- 自定义模型导入使用自定义模型单元(Custom Model Units),按分钟计费,并收取月度存储费
+- 导入的模型副本激活后以 5 分钟为窗口进行计费
+- 自定义和微调会在正常推理之外引入训练和托管模型费用
-Implication for Paperclip:
+对 Paperclip 的影响:
-- normal tokenized inference fits in `cost_events`
-- provisioned throughput, custom model unit charges, training, and storage charges require `finance_events`
-- region and pricing tier need to be first-class dimensions in the financial model
+- 普通 token 化推理适合放入 `cost_events`
+- 预留吞吐量、自定义模型单元费用、训练和存储费用需要使用 `finance_events`
+- 区域和定价层级需要作为财务模型中的一级维度
-## Ledger Boundary
+## 账本边界
-To keep the system coherent, the table boundary should be explicit.
+为保持系统的一致性,表的边界应当明确定义。
### `cost_events`
-Use `cost_events` for request-scoped usage and inference charges:
+将 `cost_events` 用于请求范围内的用量和推理费用:
-- one row per billable or usage-bearing run event
+- 每个可计费或产生用量的运行事件对应一行
- provider/model/biller/billingType/tokens/cost
-- optionally tied to `heartbeat_run_id`
-- supports direct APIs, subscriptions, overage, OpenRouter-routed inference, Cloudflare-routed inference, and Bedrock on-demand inference
+- 可选关联 `heartbeat_run_id`
+- 支持直接 API、订阅、超额用量、OpenRouter 路由推理、Cloudflare 路由推理和 Bedrock 按需推理
### `finance_events`
-Use `finance_events` for account-scoped or platform-scoped financial events:
+将 `finance_events` 用于账户范围或平台范围内的财务事件:
-- credit purchase
-- top-up
-- refund
-- fee
-- expiry
-- provisioned capacity
-- training
-- model import
-- storage
-- invoice adjustment
+- 积分购买
+- 充值
+- 退款
+- 手续费
+- 到期
+- 预留容量
+- 训练
+- 模型导入
+- 存储
+- 发票调整
-These rows may or may not have a related model, provider, or run id.
-Trying to force them into `cost_events` would either create fake request rows or create null-heavy rows that mean something fundamentally different from inference usage.
+这些行可能包含或不包含关联的模型、提供商或运行 ID。
+若强行将它们写入 `cost_events`,要么会产生虚假的请求行,要么会产生大量空字段的行,其含义与推理用量有根本性的不同。
-## Canonical Billing Dimensions
+## 标准计费维度
-Every persisted billing event should model four separate axes:
+每个持久化的计费事件应对四个独立轴进行建模:
-1. Usage provider
- The upstream provider whose model performed the work.
- Examples: `openai`, `anthropic`, `google`.
+1. 用量提供商
+ 执行工作的上游提供商模型所属方。
+ 示例:`openai`、`anthropic`、`google`。
-2. Biller
- The system that charged for the usage.
- Examples: `openai`, `anthropic`, `openrouter`, `cursor`, `chatgpt`.
+2. 计费方
+ 对用量进行收费的系统。
+ 示例:`openai`、`anthropic`、`openrouter`、`cursor`、`chatgpt`。
-3. Billing type
- The pricing mode applied to the event.
- Initial canonical values:
+3. 计费类型
+ 应用于该事件的定价模式。
+ 初始标准值:
- `metered_api`
- `subscription_included`
- `subscription_overage`
@@ -192,43 +192,43 @@ Every persisted billing event should model four separate axes:
- `fixed`
- `unknown`
-4. Measures
- Usage and billing must both be storable:
+4. 度量指标
+ 用量和计费数据都必须可存储:
- `input_tokens`
- `output_tokens`
- `cached_input_tokens`
- `cost_cents`
-These dimensions are independent.
-For example, an event may be:
+这些维度彼此独立。
+例如,一个事件可以是:
- provider: `anthropic`
- biller: `openrouter`
- billing type: `metered_api`
-- tokens: non-zero
-- cost cents: non-zero
+- tokens: 非零
+- cost cents: 非零
-Or:
+或者:
- provider: `anthropic`
- biller: `anthropic`
- billing type: `subscription_included`
-- tokens: non-zero
+- tokens: 非零
- cost cents: `0`
-## Schema Changes
+## Schema 变更
-Extend `cost_events` with:
+扩展 `cost_events`,添加以下字段:
- `heartbeat_run_id uuid null references heartbeat_runs.id`
- `biller text not null default 'unknown'`
- `billing_type text not null default 'unknown'`
- `cached_input_tokens int not null default 0`
-Keep `provider` as the upstream usage provider.
-Do not overload `provider` to mean biller.
+保留 `provider` 作为上游用量提供商字段。
+不要将 `provider` 重载为计费方的含义。
-Add a future `finance_events` table for account-level financial events with fields along these lines:
+为账户级财务事件添加未来的 `finance_events` 表,字段大致如下:
- `company_id`
- `occurred_at`
@@ -250,219 +250,219 @@ Add a future `finance_events` table for account-level financial events with fiel
- `external_invoice_id nullable`
- `metadata_json nullable`
-Add indexes:
+添加索引:
- `(company_id, biller, occurred_at)`
- `(company_id, provider, occurred_at)`
-- `(company_id, heartbeat_run_id)` if distinct-run reporting remains common
+- `(company_id, heartbeat_run_id)`(如果不同运行的报告仍然常见)
-## Shared Contract Changes
+## 共享契约变更
-### Shared types
+### 共享类型
-Add a shared billing type union and enrich cost types with:
+添加共享计费类型联合,并在 cost 类型中补充:
- `heartbeatRunId`
- `biller`
- `billingType`
- `cachedInputTokens`
-Update reporting response types so the provider breakdown reflects the ledger directly rather than inferred run metadata.
+更新报告响应类型,使提供商分解直接反映账本数据,而非通过推断运行元数据得出。
-### Validators
+### 验证器
-Extend `createCostEventSchema` to accept:
+扩展 `createCostEventSchema` 以接受:
- `heartbeatRunId`
- `biller`
- `billingType`
- `cachedInputTokens`
-Defaults:
+默认值:
-- `biller` defaults to `provider`
-- `billingType` defaults to `unknown`
-- `cachedInputTokens` defaults to `0`
+- `biller` 默认为 `provider`
+- `billingType` 默认为 `unknown`
+- `cachedInputTokens` 默认为 `0`
-## Adapter Contract Changes
+## 适配器契约变更
-Extend adapter execution results so they can report:
+扩展适配器执行结果,使其能够报告:
- `biller`
-- richer billing type values
+- 更丰富的计费类型值
-Backwards compatibility:
+向后兼容性:
-- existing adapter values `api` and `subscription` are treated as legacy aliases
-- map `api -> metered_api`
-- map `subscription -> subscription_included`
+- 现有适配器值 `api` 和 `subscription` 被视为遗留别名
+- 映射 `api -> metered_api`
+- 映射 `subscription -> subscription_included`
-Future adapters may emit the canonical values directly.
+未来的适配器可以直接发出标准值。
-OpenRouter support will use:
+OpenRouter 支持将使用:
-- `provider` = upstream provider when known
+- `provider` = 已知时为上游提供商
- `biller` = `openrouter`
-- `billingType` = `metered_api` unless OpenRouter later exposes another billing mode
+- `billingType` = `metered_api`,除非 OpenRouter 日后公开其他计费模式
-Cloudflare Unified Billing support will use:
+Cloudflare 统一计费支持将使用:
-- `provider` = upstream provider when known
+- `provider` = 已知时为上游提供商
- `biller` = `cloudflare`
-- `billingType` = `credits` or `metered_api` depending on the normalized request billing contract
+- `billingType` = `credits` 或 `metered_api`,取决于规范化的请求计费契约
-Bedrock support will use:
+Bedrock 支持将使用:
-- `provider` = upstream provider or `aws_bedrock` depending on adapter shape
+- `provider` = 上游提供商或 `aws_bedrock`,取决于适配器形态
- `biller` = `aws_bedrock`
-- `billingType` = request-scoped mode for inference rows
-- `finance_events` for provisioned, training, import, and storage charges
+- `billingType` = 推理行的请求范围模式
+- `finance_events` 用于预留、训练、导入和存储费用
-## Write Path Changes
+## 写入路径变更
-### Heartbeat-created events
+### 心跳创建的事件
-When a heartbeat run produces usage or spend:
+当心跳运行产生用量或费用时:
-1. normalize adapter billing metadata
-2. write a ledger row to `cost_events`
-3. attach `heartbeat_run_id`
-4. set `provider`, `biller`, `billing_type`, token fields, and `cost_cents`
+1. 规范化适配器计费元数据
+2. 向 `cost_events` 写入一条账本记录
+3. 附加 `heartbeat_run_id`
+4. 设置 `provider`、`biller`、`billing_type`、token 字段和 `cost_cents`
-The write path should no longer depend on later inference from `heartbeat_runs`.
+写入路径不应再依赖后续从 `heartbeat_runs` 推断数据。
-### Manual API-created events
+### 手动 API 创建的事件
-Manual cost event creation remains supported.
-These events may have `heartbeatRunId = null`.
+手动创建 cost 事件的功能仍然受支持。
+这些事件的 `heartbeatRunId` 可以为 `null`。
-Rules:
+规则:
-- `provider` remains required
-- `biller` defaults to `provider`
-- `billingType` defaults to `unknown`
+- `provider` 仍为必填项
+- `biller` 默认为 `provider`
+- `billingType` 默认为 `unknown`
-## Reporting Changes
+## 报告变更
-### Server
+### 服务端
-Refactor reporting queries to use `cost_events` only.
+重构报告查询,仅使用 `cost_events`。
#### `summary`
-- sum `cost_cents`
+- 对 `cost_cents` 求和
#### `by-agent`
-- sum costs and token fields from `cost_events`
-- use `count(distinct heartbeat_run_id)` filtered by billing type for run counts
-- use token sums filtered by billing type for subscription usage
+- 从 `cost_events` 汇总费用和 token 字段
+- 按计费类型过滤后使用 `count(distinct heartbeat_run_id)` 统计运行次数
+- 按计费类型过滤后使用 token 总量统计订阅用量
#### `by-provider`
-- group by `provider`, `model`
-- sum costs and token fields directly from the ledger
-- derive billing-type slices from `cost_events.billing_type`
-- never pro-rate from unrelated `heartbeat_runs`
+- 按 `provider`、`model` 分组
+- 直接从账本汇总费用和 token 字段
+- 从 `cost_events.billing_type` 派生计费类型切片
+- 绝不从无关的 `heartbeat_runs` 中按比例分配
-#### future `by-biller`
+#### 未来的 `by-biller`
-- group by `biller`
-- this is the right view for invoice and subscription accountability
+- 按 `biller` 分组
+- 这是发票和订阅核查的正确视图
#### `window-spend`
-- continue to use `cost_events`
+- 继续使用 `cost_events`
-#### project attribution
+#### 项目归因
-Keep current project attribution logic for now, but prefer `cost_events.heartbeat_run_id` as the join anchor whenever possible.
+暂时保留当前的项目归因逻辑,但尽可能优先使用 `cost_events.heartbeat_run_id` 作为联接锚点。
-## UI Changes
+## UI 变更
-### Principles
+### 原则
-- Spend, usage, and quota are related but distinct
-- a missing quota fetch is not the same as “no quota”
-- provider and biller are different dimensions
+- 消费、用量和配额相互关联,但各有区别
+- 配额获取失败不等同于”无配额”
+- 提供商和计费方是不同的维度
-### Immediate UI changes
+### 即时 UI 变更
-1. Keep the current costs page structure.
-2. Make the provider cards accurate by reading only ledger-backed values.
-3. Show provider quota fetch errors explicitly instead of dropping them.
+1. 保留当前费用页面结构。
+2. 通过仅读取账本支撑的值,使提供商卡片显示准确数据。
+3. 明确显示提供商配额获取错误,而不是直接丢弃。
-### Follow-up UI direction
+### 后续 UI 方向
-The long-term board UI should expose:
+长期的 board UI 应展示:
-- Spend
- Dollars by biller, provider, model, agent, project
-- Usage
- Tokens by provider, model, agent, project
-- Quotas
- Live provider or biller limits, credits, and reset windows
-- Financial events
- Credit purchases, top-ups, fees, refunds, commitments, storage, and other non-inference charges
+- 消费
+ 按计费方、提供商、模型、代理、项目划分的金额
+- 用量
+ 按提供商、模型、代理、项目划分的 token 数量
+- 配额
+ 实时提供商或计费方限额、积分和重置窗口
+- 财务事件
+ 积分购买、充值、手续费、退款、承诺、存储及其他非推理费用
-## Migration Plan
+## 迁移计划
-Migration behavior:
+迁移行为:
-- add new non-destructive columns with defaults
-- backfill existing rows:
+- 添加带有默认值的新非破坏性字段
+- 回填现有记录:
- `biller = provider`
- `billing_type = 'unknown'`
- `cached_input_tokens = 0`
- `heartbeat_run_id = null`
-Do **not** attempt to backfill historical provider-level subscription attribution from `heartbeat_runs`.
-That data was never stored with the required dimensions.
+**不要**尝试从 `heartbeat_runs` 回填历史提供商级订阅归因数据。
+这些数据从未以所需的维度存储过。
-## Testing Plan
+## 测试计划
-Add or update tests for:
+添加或更新以下测试:
-1. heartbeat-created ledger rows persist `heartbeatRunId`, `biller`, `billingType`, and cached tokens
-2. legacy adapter billing values map correctly
-3. provider reporting uses ledger data only
-4. mixed-provider companies do not cross-attribute subscription usage
-5. zero-dollar subscription usage still appears in token reporting
-6. quota fetch failures render explicit UI state
-7. manual cost events still validate and write correctly
-8. biller reporting keeps upstream provider breakdowns separate
-9. OpenRouter-style rows can show `biller=openrouter` with non-OpenRouter upstream providers
-10. Cloudflare-style rows can show `biller=cloudflare` with preserved upstream provider identity
-11. future `finance_events` aggregation handles non-request charges without requiring a model or run id
+1. 心跳创建的账本行持久化 `heartbeatRunId`、`biller`、`billingType` 和缓存 token
+2. 遗留适配器计费值正确映射
+3. 提供商报告仅使用账本数据
+4. 混合提供商的公司不发生订阅用量的交叉归因
+5. 零美元订阅用量仍显示在 token 报告中
+6. 配额获取失败渲染明确的 UI 状态
+7. 手动 cost 事件仍能正确验证和写入
+8. 计费方报告保持上游提供商分解独立
+9. OpenRouter 风格的记录能够在非 OpenRouter 上游提供商下显示 `biller=openrouter`
+10. Cloudflare 风格的记录能够在保留上游提供商身份的情况下显示 `biller=cloudflare`
+11. 未来的 `finance_events` 聚合能够处理无需模型或运行 ID 的非请求费用
-## Delivery Plan
+## 交付计划
-### Step 1
+### 第一步
-- land the ledger contract and query rewrite
-- make the current costs page correct
+- 落地账本契约和查询重写
+- 使当前费用页面数据准确
-### Step 2
+### 第二步
-- add biller-oriented reporting endpoints and UI
+- 添加以计费方为导向的报告端点和 UI
-### Step 3
+### 第三步
-- wire OpenRouter and any future aggregator adapters to the same contract
+- 将 OpenRouter 及未来的聚合商适配器接入同一契约
-### Step 4
+### 第四步
-- add `executionAdapterType` to persisted cost reporting if adapter-level grouping becomes a product requirement
+- 如果适配器级分组成为产品需求,则将 `executionAdapterType` 添加到持久化的费用报告中
-### Step 5
+### 第五步
-- introduce `finance_events`
-- add non-inference accounting endpoints
-- add UI for platform/account charges alongside inference spend and usage
+- 引入 `finance_events`
+- 添加非推理会计端点
+- 在推理消费和用量旁边添加平台/账户费用的 UI
-## Non-Goals For This Change
+## 本次变更的非目标
-- multi-currency support
-- invoice reconciliation
-- provider-specific cost estimation beyond persisted billed cost
-- replacing `heartbeat_runs` as the operational run record
+- 多币种支持
+- 发票对账
+- 超出持久化计费成本范围的提供商特定成本估算
+- 替换 `heartbeat_runs` 作为运行操作记录
diff --git a/doc/plans/2026-03-14-budget-policies-and-enforcement.md b/doc/plans/2026-03-14-budget-policies-and-enforcement.md
index 5079ced967..e2d8e303de 100644
--- a/doc/plans/2026-03-14-budget-policies-and-enforcement.md
+++ b/doc/plans/2026-03-14-budget-policies-and-enforcement.md
@@ -1,180 +1,180 @@
-# Budget Policies and Enforcement
+# 预算策略与执行
-## Context
+## 背景
-Paperclip already treats budgets as a core control-plane responsibility:
+Paperclip 已将预算视为核心控制面职责:
-- `doc/SPEC.md` gives the Board authority to set budgets, pause agents, pause work, and override any budget.
-- `doc/SPEC-implementation.md` says V1 must support monthly UTC budget windows, soft alerts, and hard auto-pause.
-- the current code only partially implements that intent.
+- `doc/SPEC.md` 授权 Board 设置预算、暂停代理、暂停工作并覆盖任何预算。
+- `doc/SPEC-implementation.md` 规定 V1 必须支持 UTC 月度预算窗口、软警告和硬自动暂停。
+- 当前代码仅部分实现了上述意图。
-Today the system has narrow money-budget behavior:
+目前系统仅具备有限的金额预算行为:
-- companies track `budgetMonthlyCents` and `spentMonthlyCents`
-- agents track `budgetMonthlyCents` and `spentMonthlyCents`
-- `cost_events` ingestion increments those counters
-- when an agent exceeds its monthly budget, the agent is paused
+- 公司跟踪 `budgetMonthlyCents` 和 `spentMonthlyCents`
+- 代理跟踪 `budgetMonthlyCents` 和 `spentMonthlyCents`
+- `cost_events` 摄入时递增上述计数器
+- 当代理超出月度预算时,代理被暂停
-That leaves major product gaps:
+这留下了重大的产品空白:
-- no project budget model
-- no approval generated when budget is hit
-- no generic budget policy system
-- no project pause semantics tied to budget
-- no durable incident tracking to prevent duplicate alerts
-- no separation between enforceable spend budgets and advisory usage quotas
+- 没有项目预算模型
+- 触及预算时不生成审批
+- 没有通用预算策略系统
+- 没有与预算挂钩的项目暂停语义
+- 没有持久化事件跟踪以防止重复警告
+- 没有将可执行消费预算与咨询性用量配额区分开来
-This plan defines the concrete budgeting model Paperclip should implement next.
+本计划定义了 Paperclip 接下来应实现的具体预算模型。
-## Product Goals
+## 产品目标
-Paperclip should let operators:
+Paperclip 应允许运营人员:
-1. Set budgets on agents and projects.
-2. Understand whether a budget is based on money or usage.
-3. Be warned before a budget is exhausted.
-4. Automatically pause work when a hard budget is hit.
-5. Approve, raise, or resume from a budget stop using obvious UI.
-6. See budget state on the dashboard, `/costs`, and scope detail pages.
+1. 为代理和项目设置预算。
+2. 了解预算是基于金额还是用量。
+3. 在预算耗尽前收到警告。
+4. 触及硬预算时自动暂停工作。
+5. 通过清晰的 UI 批准、提高或从预算停止中恢复。
+6. 在仪表盘、`/costs` 和范围详情页查看预算状态。
-The system should make one thing very clear:
+系统应将一件事说清楚:
-- budgets are policy controls
-- quotas are usage visibility
+- 预算是策略控制
+- 配额是用量可见性
-They are related, but they are not the same concept.
+两者相关,但不是同一概念。
-## Product Decisions
+## 产品决策
-### V1 Budget Defaults
+### V1 预算默认值
-For the next implementation pass, Paperclip should enforce these defaults:
+在下一轮实现中,Paperclip 应执行以下默认设置:
-- agent budgets are recurring monthly budgets
-- project budgets are lifetime total budgets
-- hard-stop enforcement uses billed dollars, not tokens
-- monthly windows use UTC calendar months
-- project total budgets do not reset automatically
+- 代理预算为周期性月度预算
+- 项目预算为生命周期总额预算
+- 硬停止执行使用计费金额,而非 token
+- 月度窗口使用 UTC 自然月
+- 项目总额预算不自动重置
-This gives a clean mental model:
+这提供了清晰的心智模型:
-- agents are ongoing workers, so monthly recurring budget is natural
-- projects are bounded workstreams, so lifetime cap is natural
+- 代理是持续工作的,因此月度循环预算是自然的选择
+- 项目是有边界的工作流,因此生命周期上限是自然的选择
-### Metric To Enforce First
+### 首先执行的指标
-The first enforceable metric should be `billed_cents`.
+第一个可执行指标应为 `billed_cents`。
-Reasoning:
+理由:
-- it works across providers, billers, and models
-- it maps directly to real financial risk
-- it handles overage and metered usage consistently
-- it avoids cross-provider token normalization problems
-- it applies cleanly even when future finance events are not token-based
+- 适用于所有提供商、计费方和模型
+- 直接映射到真实的财务风险
+- 一致地处理超额用量和计量用量
+- 避免跨提供商的 token 规范化问题
+- 即使未来的财务事件不基于 token,仍可干净地应用
-Token budgets should not be the first hard-stop policy.
-They should come later as advisory usage controls once the money-based system is solid.
+Token 预算不应作为第一个硬停止策略。
+等基于金额的系统稳固后,它们应作为咨询性用量控制稍后加入。
-### Subscription Usage Decision
+### 订阅用量决策
-Paperclip should separate subscription-included usage from billed spend:
+Paperclip 应将订阅内含用量与计费消费区分开来:
- `subscription_included`
- - visible in reporting
- - visible in usage summaries
- - does not count against money budget
+ - 在报告中可见
+ - 在用量摘要中可见
+ - 不计入金额预算
- `subscription_overage`
- - visible in reporting
- - counts against money budget
+ - 在报告中可见
+ - 计入金额预算
- `metered_api`
- - visible in reporting
- - counts against money budget
+ - 在报告中可见
+ - 计入金额预算
-This keeps the budget system honest:
+这确保了预算系统的诚实性:
-- users should not see "spend" rise for usage that did not incur marginal billed cost
-- users should still see the token usage and provider quota state
+- 用户不应看到"消费"因未产生边际计费成本的用量而增加
+- 用户仍应看到 token 用量和提供商配额状态
-### Soft Alert Versus Hard Stop
+### 软警告与硬停止
-Paperclip should have two threshold classes:
+Paperclip 应有两个阈值等级:
-- soft alert
- - creates visible notification state
- - does not create an approval
- - does not pause work
-- hard stop
- - pauses the affected scope automatically
- - creates an approval requiring human resolution
- - prevents additional heartbeats or task pickup in that scope
+- 软警告
+ - 创建可见的通知状态
+ - 不创建审批
+ - 不暂停工作
+- 硬停止
+ - 自动暂停受影响的范围
+ - 创建需要人工处理的审批
+ - 阻止该范围内的额外心跳或任务接取
-Default thresholds:
+默认阈值:
-- soft alert at `80%`
-- hard stop at `100%`
+- 软警告在 `80%`
+- 硬停止在 `100%`
-These should be configurable per policy later, but they are good defaults now.
+这些应在后续可按策略配置,但目前作为默认值是合适的。
-## Scope Model
+## 范围模型
-### Supported Scope Types
+### 支持的范围类型
-Budget policies should support:
+预算策略应支持:
- `company`
- `agent`
- `project`
-This plan focuses on finishing `agent` and `project` first while preserving the existing company budget behavior.
+本计划优先完成 `agent` 和 `project`,同时保留现有的公司预算行为。
-### Recommended V1.5 Policy Presets
+### 推荐的 V1.5 策略预设
-- Company
+- 公司
- metric: `billed_cents`
- window: `calendar_month_utc`
-- Agent
+- 代理
- metric: `billed_cents`
- window: `calendar_month_utc`
-- Project
+- 项目
- metric: `billed_cents`
- window: `lifetime`
-Future extensions can add:
+未来扩展可以添加:
-- token advisory policies
-- daily or weekly spend windows
-- provider- or biller-scoped budgets
-- inherited delegated budgets down the org tree
+- token 咨询策略
+- 每日或每周消费窗口
+- 提供商或计费方范围的预算
+- 沿组织树向下继承的委托预算
-## Current Implementation Baseline
+## 当前实现基准
-The current codebase is not starting from zero, but the existing shape is too ad hoc to extend safely.
+当前代码库并非从零开始,但现有结构过于临时性,无法安全地扩展。
-### What Exists Today
+### 现有内容
-- company and agent monthly cents counters
-- cost ingestion that updates those counters
-- agent hard-stop pause on monthly budget overrun
+- 公司和代理的月度金额计数器
+- 更新这些计数器的费用摄入逻辑
+- 代理在超出月度预算时的硬停止暂停
-### What Is Missing
+### 缺失内容
-- project budgets
-- generic budget policy persistence
-- generic threshold crossing detection
-- incident deduplication per scope/window
-- approval creation on hard-stop
-- project execution blocking
-- budget timeline and incident UI
-- distinction between advisory quota and enforceable budget
+- 项目预算
+- 通用预算策略持久化
+- 通用阈值越过检测
+- 按范围/窗口的事件去重
+- 硬停止时创建审批
+- 项目执行阻止
+- 预算时间线和事件 UI
+- 咨询性配额与可执行预算的区分
-## Proposed Data Model
+## 提议的数据模型
### 1. `budget_policies`
-Create a new table for canonical budget definitions.
+创建新表以存储标准预算定义。
-Suggested fields:
+建议字段:
- `id`
- `company_id`
@@ -192,19 +192,19 @@ Suggested fields:
- `created_at`
- `updated_at`
-Notes:
+说明:
-- `scope_type` is one of `company | agent | project`
-- `scope_id` is nullable only for company-level policy if company is implied; otherwise keep it explicit
-- `metric` should start with `billed_cents`
-- `window_kind` starts with `calendar_month_utc | lifetime`
-- `amount` is stored in the natural unit of the metric
+- `scope_type` 为 `company | agent | project` 之一
+- 仅在公司级策略中隐含公司时,`scope_id` 才可为空;否则保持显式
+- `metric` 应从 `billed_cents` 开始
+- `window_kind` 从 `calendar_month_utc | lifetime` 开始
+- `amount` 以该指标的自然单位存储
### 2. `budget_incidents`
-Create a durable record of threshold crossings.
+创建阈值越过的持久化记录。
-Suggested fields:
+建议字段:
- `id`
- `company_id`
@@ -225,46 +225,46 @@ Suggested fields:
- `created_at`
- `updated_at`
-Notes:
+说明:
-- `threshold_type`: `soft | hard`
-- `status`: `open | acknowledged | resolved | dismissed`
-- one open incident per policy per threshold per window prevents duplicate approvals and alert spam
+- `threshold_type`:`soft | hard`
+- `status`:`open | acknowledged | resolved | dismissed`
+- 每个策略每个阈值每个窗口只保留一个 open 事件,防止重复审批和警告泛滥
-### 3. Project Pause State
+### 3. 项目暂停状态
-Projects need explicit pause semantics.
+项目需要明确的暂停语义。
-Recommended approach:
+推荐方式:
-- extend project status or add a pause field so a project can be blocked by budget
-- preserve whether the project is paused due to budget versus manually paused
+- 扩展项目状态或添加暂停字段,使项目可被预算阻止
+- 保留项目是因预算暂停还是手动暂停的区分
-Preferred shape:
+首选形态:
-- keep project workflow status as-is
-- add execution-state fields:
- - `execution_status`: `active | paused | archived`
- - `pause_reason`: `manual | budget | system | null`
+- 保持项目工作流状态不变
+- 添加执行状态字段:
+ - `execution_status`:`active | paused | archived`
+ - `pause_reason`:`manual | budget | system | null`
-If that is too large for the immediate pass, a smaller version is:
+如果当前阶段范围太大,可采用较小版本:
-- add `paused_at`
-- add `pause_reason`
+- 添加 `paused_at`
+- 添加 `pause_reason`
-The key requirement is behavioral, not cosmetic:
-Paperclip must know that a project is budget-paused and enforce it.
+关键要求是行为层面,而非表面层面:
+Paperclip 必须知道项目处于预算暂停状态并加以执行。
-### 4. Compatibility With Existing Budget Columns
+### 4. 与现有预算字段的兼容性
-Existing company and agent monthly budget columns should remain temporarily for compatibility.
+现有公司和代理月度预算字段应暂时保留以保持兼容性。
-Migration plan:
+迁移计划:
-1. keep reading existing columns during transition
-2. create equivalent `budget_policies` rows
-3. switch enforcement and UI to policies
-4. later remove or deprecate legacy columns
+1. 过渡期间继续读取现有字段
+2. 创建等效的 `budget_policies` 行
+3. 将执行和 UI 切换到策略
+4. 后续移除或弃用遗留字段
## Budget Engine
diff --git a/doc/plans/2026-03-14-skills-ui-product-plan.md b/doc/plans/2026-03-14-skills-ui-product-plan.md
index 6df9eb053e..0e9e4dfe92 100644
--- a/doc/plans/2026-03-14-skills-ui-product-plan.md
+++ b/doc/plans/2026-03-14-skills-ui-product-plan.md
@@ -1,175 +1,175 @@
-# 2026-03-14 Skills UI Product Plan
+# 2026-03-14 技能 UI 产品计划
Status: Proposed
Date: 2026-03-14
-Audience: Product and engineering
+Audience: 产品与工程
Related:
- `doc/plans/2026-03-13-company-import-export-v2.md`
- `doc/plans/2026-03-14-adapter-skill-sync-rollout.md`
- `docs/companies/companies-spec.md`
- `ui/src/pages/AgentDetail.tsx`
-## 1. Purpose
+## 1. 目的
-This document defines the product and UI plan for skill management in Paperclip.
+本文档定义了 Paperclip 中技能管理的产品与 UI 计划。
-The goal is to make skills understandable and manageable in the website without pretending that all adapters behave the same way.
+目标是让技能在网站上易于理解和管理,而不是假装所有适配器的行为都相同。
-This plan assumes:
+本计划的前提假设:
-- `SKILL.md` remains Agent Skills compatible
-- `skills.sh` compatibility is a V1 requirement
-- Paperclip company import/export can include skills as package content
-- adapters may support persistent skill sync, ephemeral skill mounting, read-only skill discovery, or no skill integration at all
+- `SKILL.md` 保持与 Agent Skills 兼容
+- `skills.sh` 兼容性是 V1 的必要条件
+- Paperclip 公司导入/导出可以将技能作为软件包内容包含在内
+- 适配器可能支持持久技能同步、临时技能挂载、只读技能发现,或完全不集成技能
-## 2. Current State
+## 2. 现状
-There is already a first-pass agent-level skill sync UI on `AgentDetail`.
+`AgentDetail` 上已经有一个初步的 Agent 级技能同步 UI。
-Today it supports:
+目前支持:
-- loading adapter skill sync state
-- showing unsupported adapters clearly
-- showing managed skills as checkboxes
-- showing external skills separately
-- syncing desired skills for adapters that implement the new API
+- 加载适配器技能同步状态
+- 清晰显示不受支持的适配器
+- 以复选框形式显示已托管技能
+- 单独显示外部技能
+- 为实现新 API 的适配器同步期望技能
-Current limitations:
+当前限制:
-1. There is no company-level skill library UI.
-2. There is no package import flow for skills in the website.
-3. There is no distinction between skill package management and per-agent skill attachment.
-4. There is no multi-agent desired-vs-actual view.
-5. The current UI is adapter-sync-oriented, not package-oriented.
-6. Unsupported adapters degrade safely, but not elegantly.
+1. 没有公司级技能库 UI。
+2. 网站上没有技能的软件包导入流程。
+3. 技能软件包管理与按 Agent 技能附加之间没有区分。
+4. 没有多 Agent 的期望状态与实际状态对比视图。
+5. 当前 UI 以适配器同步为导向,而非以软件包为导向。
+6. 不受支持的适配器会安全降级,但不够优雅。
-## 2.1 V1 Decisions
+## 2.1 V1 决策
-For V1, this plan assumes the following product decisions are already made:
+对于 V1,本计划假设以下产品决策已经确定:
-1. `skills.sh` compatibility is required.
-2. Agent-to-skill association in `AGENTS.md` is by shortname or slug.
-3. Company skills and agent skill attachments are separate concepts.
-4. Agent skills should move to their own tab rather than living inside configuration.
-5. Company import/export should eventually round-trip skill packages and agent skill attachments.
+1. 必须支持 `skills.sh` 兼容性。
+2. `AGENTS.md` 中 Agent 与技能的关联通过 shortname 或 slug 表示。
+3. 公司技能与 Agent 技能附加是独立的概念。
+4. Agent 技能应移至独立标签页,而不是嵌套在配置中。
+5. 公司导入/导出最终应能完整往返传递技能软件包和 Agent 技能附加信息。
-## 3. Product Principles
+## 3. 产品原则
-1. Skills are company assets first, agent attachments second.
-2. Package management and adapter sync are different concerns and should not be conflated in one screen.
-3. The UI must always tell the truth about what Paperclip knows:
- - desired state in Paperclip
- - actual state reported by the adapter
- - whether the adapter can reconcile the two
-4. Agent Skills compatibility must remain visible in the product model.
-5. Agent-to-skill associations should be human-readable and shortname-based wherever possible.
-6. Unsupported adapters should still have a useful UI, not just a dead end.
+1. 技能首先是公司资产,其次才是 Agent 的附加项。
+2. 软件包管理与适配器同步是不同的关注点,不应在同一个界面中混为一谈。
+3. UI 必须始终如实展示 Paperclip 所知道的内容:
+ - Paperclip 中的期望状态
+ - 适配器上报的实际状态
+ - 适配器是否能够协调两者之间的差异
+4. Agent Skills 兼容性必须在产品模型中保持可见。
+5. Agent 与技能的关联应尽可能以人类可读的 shortname 为基础。
+6. 不受支持的适配器也应有可用的 UI,而不是仅仅显示死胡同。
-## 4. User Model
+## 4. 用户模型
-Paperclip should treat skills at two scopes:
+Paperclip 应在两个范围内处理技能:
-### 4.1 Company skills
+### 4.1 公司技能
-These are reusable skills known to the company.
+这些是公司已知的可复用技能。
-Examples:
+示例:
-- imported from a GitHub repo
-- added from a local folder
-- installed from a `skills.sh`-compatible repo
-- created locally inside Paperclip later
+- 从 GitHub 仓库导入
+- 从本地文件夹添加
+- 从兼容 `skills.sh` 的仓库安装
+- 日后在 Paperclip 内部本地创建
-These should have:
+这些技能应包含:
-- name
-- description
-- slug or package identity
-- source/provenance
-- trust level
-- compatibility status
+- 名称
+- 描述
+- slug 或软件包标识
+- 来源/溯源信息
+- 信任级别
+- 兼容性状态
-### 4.2 Agent skills
+### 4.2 Agent 技能
-These are skill attachments for a specific agent.
+这些是针对特定 Agent 的技能附加项。
-Each attachment should have:
+每个附加项应包含:
- shortname
-- desired state in Paperclip
-- actual state in the adapter when readable
-- sync status
-- origin
+- Paperclip 中的期望状态
+- 适配器中可读取到的实际状态
+- 同步状态
+- 来源
-Agent attachments should normally reference skills by shortname or slug, for example:
+Agent 附加项通常应通过 shortname 或 slug 引用技能,例如:
- `review`
- `react-best-practices`
-not by noisy relative file path.
+而不是使用冗长的相对文件路径。
-## 4.3 Primary user jobs
+## 4.3 主要用户任务
-The UI should support these jobs cleanly:
+UI 应清晰支持以下任务:
-1. “Show me what skills this company has.”
-2. “Import a skill from GitHub or a local folder.”
-3. “See whether a skill is safe, compatible, and who uses it.”
-4. “Attach skills to an agent.”
-5. “See whether the adapter actually has those skills.”
-6. “Reconcile desired vs actual skill state.”
-7. “Understand what Paperclip knows vs what the adapter knows.”
+1. “显示这家公司拥有哪些技能。”
+2. “从 GitHub 或本地文件夹导入技能。”
+3. “查看某项技能是否安全、是否兼容,以及谁在使用它。”
+4. “将技能附加到 Agent。”
+5. “查看适配器是否实际拥有这些技能。”
+6. “协调期望技能状态与实际技能状态之间的差异。”
+7. “了解 Paperclip 所知道的内容与适配器所知道的内容之间的区别。”
-## 5. Core UI Surfaces
+## 5. 核心 UI 界面
-The product should have two primary skill surfaces.
+产品应有两个主要的技能界面。
-### 5.1 Company Skills page
+### 5.1 公司技能页面
-Add a company-level page, likely:
+添加一个公司级页面,建议路径为:
- `/companies/:companyId/skills`
-Purpose:
+目的:
-- manage the company skill library
-- import and inspect skill packages
-- understand provenance and trust
-- see which agents use which skills
+- 管理公司技能库
+- 导入和检查技能软件包
+- 了解溯源信息和信任状态
+- 查看哪些 Agent 使用了哪些技能
-#### Route
+#### 路由
- `/companies/:companyId/skills`
-#### Primary actions
+#### 主要操作
-- import skill
-- inspect skill
-- attach to agents
-- detach from agents
-- export selected skills later
+- 导入技能
+- 检查技能
+- 附加到 Agent
+- 从 Agent 分离
+- 日后导出所选技能
-#### Empty state
+#### 空状态
-When the company has no managed skills:
+当公司没有已托管技能时:
-- explain what skills are
-- explain `skills.sh` / Agent Skills compatibility
-- offer `Import from GitHub` and `Import from folder`
-- optionally show adapter-discovered skills as a secondary “not managed yet” section
+- 解释技能是什么
+- 解释 `skills.sh` / Agent Skills 兼容性
+- 提供 `Import from GitHub` 和 `Import from folder` 入口
+- 可选地将适配器发现的技能作为次级”尚未托管”区块显示
-#### A. Skill library list
+#### A. 技能库列表
-Each skill row should show:
+每行技能应显示:
-- name
-- short description
-- source badge
-- trust badge
-- compatibility badge
-- number of attached agents
+- 名称
+- 简短描述
+- 来源徽标
+- 信任徽标
+- 兼容性徽标
+- 已附加 Agent 数量
-Suggested source states:
+建议的来源状态:
- local
- github
@@ -177,187 +177,187 @@ Suggested source states:
- external reference
- adapter-discovered only
-Suggested compatibility states:
+建议的兼容性状态:
- compatible
- paperclip-extension
- unknown
- invalid
-Suggested trust states:
+建议的信任状态:
- markdown-only
- assets
- scripts/executables
-Suggested list affordances:
+建议的列表操作功能:
-- search by name or slug
-- filter by source
-- filter by trust level
-- filter by usage
-- sort by name, recent import, usage count
+- 按名称或 slug 搜索
+- 按来源筛选
+- 按信任级别筛选
+- 按使用情况筛选
+- 按名称、最近导入时间、使用次数排序
-#### B. Import actions
+#### B. 导入操作
-Allow:
+允许:
-- import from local folder
-- import from GitHub URL
-- import from direct URL
+- 从本地文件夹导入
+- 从 GitHub URL 导入
+- 从直接 URL 导入
-Future:
+未来计划:
-- install from `companies.sh`
-- install from `skills.sh`
+- 从 `companies.sh` 安装
+- 从 `skills.sh` 安装
-V1 requirement:
+V1 要求:
-- importing from a `skills.sh`-compatible source should work without requiring a Paperclip-specific package layout
+- 从兼容 `skills.sh` 的来源导入时,无需要求 Paperclip 特定的软件包布局
-#### C. Skill detail drawer or page
+#### C. 技能详情抽屉或页面
-Each skill should have a detail view showing:
+每个技能应有详情视图,显示:
-- rendered `SKILL.md`
-- package source and pinning
-- included files
-- trust and licensing warnings
-- who uses it
-- adapter compatibility notes
+- 渲染后的 `SKILL.md`
+- 软件包来源与版本固定信息
+- 包含的文件
+- 信任与许可证警告
+- 使用者信息
+- 适配器兼容性说明
-Recommended route:
+推荐路由:
- `/companies/:companyId/skills/:skillId`
-Recommended sections:
+推荐章节:
-- Overview
-- Contents
-- Usage
-- Source
-- Trust / licensing
+- Overview(概览)
+- Contents(内容)
+- Usage(使用情况)
+- Source(来源)
+- Trust / licensing(信任与许可证)
-#### D. Usage view
+#### D. 使用情况视图
-Each company skill should show which agents use it.
+每个公司技能应显示哪些 Agent 在使用它。
-Suggested columns:
+建议的列:
-- agent
-- desired state
-- actual state
-- adapter
-- sync mode
-- last sync status
+- agent(Agent)
+- desired state(期望状态)
+- actual state(实际状态)
+- adapter(适配器)
+- sync mode(同步模式)
+- last sync status(最近同步状态)
-### 5.2 Agent Skills tab
+### 5.2 Agent 技能标签页
-Keep and evolve the existing `AgentDetail` skill sync UI, but move it out of configuration.
+保留并演进现有的 `AgentDetail` 技能同步 UI,但将其从配置中移出。
-Purpose:
+目的:
-- attach/detach company skills to one agent
-- inspect adapter reality for that agent
-- reconcile desired vs actual state
-- keep the association format readable and aligned with `AGENTS.md`
+- 为单个 Agent 附加/分离公司技能
+- 检查该 Agent 的适配器实际状态
+- 协调期望状态与实际状态
+- 保持关联格式可读,并与 `AGENTS.md` 保持一致
-#### Route
+#### 路由
- `/agents/:agentId/skills`
-#### Agent tabs
+#### Agent 标签页
-The intended agent-level tab model becomes:
+预期的 Agent 级标签页模型变为:
- `dashboard`
- `configuration`
- `skills`
- `runs`
-This is preferable to hiding skills inside configuration because:
+这比将技能隐藏在配置中更好,原因是:
-- skills are not just adapter config
-- skills need their own sync/status language
-- skills are a reusable company asset, not merely one agent field
-- the screen needs room for desired vs actual state, warnings, and external skill adoption
+- 技能不仅仅是适配器配置
+- 技能需要独立的同步/状态语言
+- 技能是可复用的公司资产,不仅仅是 Agent 的一个字段
+- 该界面需要空间来展示期望状态与实际状态的差异、警告以及外部技能采纳功能
-#### Tab layout
+#### 标签页布局
-The `Skills` tab should have three stacked sections:
+`Skills` 标签页应包含三个堆叠区块:
-1. Summary
-2. Managed skills
-3. External / discovered skills
+1. 摘要
+2. 已托管技能
+3. 外部/已发现技能
-Summary should show:
+摘要应显示:
-- adapter sync support
-- sync mode
-- number of managed skills
-- number of external skills
-- drift or warning count
+- 适配器同步支持情况
+- 同步模式
+- 已托管技能数量
+- 外部技能数量
+- 漂移或警告数量
-#### A. Desired skills
+#### A. 期望技能
-Show company-managed skills attached to the agent.
+显示附加到该 Agent 的公司托管技能。
-Each row should show:
+每行应显示:
-- skill name
+- 技能名称
- shortname
-- sync state
-- source
-- last adapter observation if available
+- 同步状态
+- 来源
+- 最近适配器观测结果(如可获取)
-Each row should support:
+每行应支持:
-- enable / disable
-- open skill detail
-- see source badge
-- see sync badge
+- 启用/禁用
+- 打开技能详情
+- 查看来源徽标
+- 查看同步徽标
-#### B. External or discovered skills
+#### B. 外部或已发现技能
-Show skills reported by the adapter that are not company-managed.
+显示适配器上报的、非公司托管的技能。
-This matters because Codex and similar adapters may already have local skills that Paperclip did not install.
+这一点很重要,因为 Codex 等适配器可能已有 Paperclip 未安装的本地技能。
-These should be clearly marked:
+这些技能应清晰标注为:
-- external
-- not managed by Paperclip
+- external(外部)
+- not managed by Paperclip(未被 Paperclip 托管)
-Each external row should support:
+每个外部技能行应支持:
-- inspect
-- adopt into company library later
-- attach as managed skill later if appropriate
+- 检查
+- 日后采纳进公司库
+- 日后在适当情况下作为已托管技能附加
-#### C. Sync controls
+#### C. 同步控制
-Support:
+支持:
-- sync
-- reset draft
-- detach
+- sync(同步)
+- reset draft(重置草稿)
+- detach(分离)
-Future:
+未来计划:
-- import external skill into company library
-- promote ad hoc local skill into a managed company skill
+- 将外部技能导入公司库
+- 将临时本地技能升级为公司托管技能
-Recommended footer actions:
+推荐的底部操作按钮:
- `Sync skills`
- `Reset`
- `Refresh adapter state`
-## 6. Skill State Model In The UI
+## 6. UI 中的技能状态模型
-Each skill attachment should have a user-facing state.
+每个技能附加项应有面向用户的状态。
-Suggested states:
+建议的状态:
- `in_sync`
- `desired_only`
@@ -366,16 +366,16 @@ Suggested states:
- `unmanaged`
- `unknown`
-Definitions:
+定义:
-- `in_sync`: desired and actual match
-- `desired_only`: Paperclip wants it, adapter does not show it yet
-- `external`: adapter has it but Paperclip does not manage it
-- `drifted`: adapter has a conflicting or unexpected version/location
-- `unmanaged`: adapter does not support sync, Paperclip only tracks desired state
-- `unknown`: adapter read failed or state cannot be trusted
+- `in_sync`:期望状态与实际状态一致
+- `desired_only`:Paperclip 期望存在,但适配器尚未显示
+- `external`:适配器已有,但 Paperclip 未托管
+- `drifted`:适配器存在版本或位置冲突或异常
+- `unmanaged`:适配器不支持同步,Paperclip 仅跟踪期望状态
+- `unknown`:适配器读取失败或状态不可信
-Suggested badge copy:
+建议的徽标文案:
- `In sync`
- `Needs sync`
@@ -384,346 +384,346 @@ Suggested badge copy:
- `Unmanaged`
- `Unknown`
-## 7. Adapter Presentation Rules
+## 7. 适配器展示规则
-The UI should not describe all adapters the same way.
+UI 不应对所有适配器使用相同的描述方式。
-### 7.1 Persistent adapters
+### 7.1 持久化适配器
-Example:
+示例:
- Codex local
-Language:
+语言表述:
-- installed
-- synced into adapter home
-- external skills detected
+- installed(已安装)
+- synced into adapter home(已同步到适配器主目录)
+- external skills detected(检测到外部技能)
-### 7.2 Ephemeral adapters
+### 7.2 临时适配器
-Example:
+示例:
- Claude local
-Language:
+语言表述:
-- will be mounted on next run
-- effective runtime skills
-- not globally installed
+- will be mounted on next run(将在下次运行时挂载)
+- effective runtime skills(运行时生效的技能)
+- not globally installed(未全局安装)
-### 7.3 Unsupported adapters
+### 7.3 不受支持的适配器
-Language:
+语言表述:
-- this adapter does not implement skill sync yet
-- Paperclip can still track desired skills
-- actual adapter state is unavailable
+- this adapter does not implement skill sync yet(该适配器尚未实现技能同步)
+- Paperclip can still track desired skills(Paperclip 仍可跟踪期望技能)
+- actual adapter state is unavailable(适配器实际状态不可用)
-This state should still allow:
+该状态仍应允许:
-- attaching company skills to the agent as desired state
-- export/import of those desired attachments
+- 将公司技能作为期望状态附加到 Agent
+- 导出/导入这些期望附加项
-## 7.4 Read-only adapters
+## 7.4 只读适配器
-Some adapters may be able to list skills but not mutate them.
+某些适配器可能能够列出技能,但无法修改它们。
-Language:
+语言表述:
-- Paperclip can see adapter skills
-- this adapter does not support applying changes
-- desired state can be tracked, but reconciliation is manual
+- Paperclip can see adapter skills(Paperclip 可以查看适配器技能)
+- this adapter does not support applying changes(该适配器不支持应用变更)
+- desired state can be tracked, but reconciliation is manual(期望状态可被跟踪,但协调需手动完成)
-## 8. Information Architecture
+## 8. 信息架构
-Recommended navigation:
+推荐的导航结构:
-- company nav adds `Skills`
-- agent detail adds `Skills` as its own tab
-- company skill detail gets its own route when the company library ships
+- 公司导航添加 `Skills`
+- Agent 详情添加 `Skills` 作为独立标签页
+- 公司技能详情在公司库上线时获得独立路由
-Recommended separation:
+推荐的功能分离:
-- Company Skills page answers: “What skills do we have?”
-- Agent Skills tab answers: “What does this agent use, and is it synced?”
+- 公司技能页面回答:”我们拥有哪些技能?”
+- Agent 技能标签页回答:”该 Agent 使用了哪些技能,是否已同步?”
-## 8.1 Proposed route map
+## 8.1 路由规划
- `/companies/:companyId/skills`
- `/companies/:companyId/skills/:skillId`
- `/agents/:agentId/skills`
-## 8.2 Nav and discovery
+## 8.2 导航与发现
-Recommended entry points:
+推荐的入口点:
-- company sidebar: `Skills`
-- agent page tabs: `Skills`
-- company import preview: link imported skills to company skills page later
-- agent skills rows: link to company skill detail
+- 公司侧边栏:`Skills`
+- Agent 页面标签页:`Skills`
+- 公司导入预览:日后将导入的技能链接到公司技能页面
+- Agent 技能行:链接到公司技能详情
-## 9. Import / Export Integration
+## 9. 导入/导出集成
-Skill UI and package portability should meet in the company skill library.
+技能 UI 与软件包可移植性应在公司技能库中交汇。
-Import behavior:
+导入行为:
-- importing a company package with `SKILL.md` content should create or update company skills
-- agent attachments should primarily come from `AGENTS.md` shortname associations
-- `.paperclip.yaml` may add Paperclip-specific fidelity, but should not replace the base shortname association model
-- referenced third-party skills should keep provenance visible
+- 导入包含 `SKILL.md` 内容的公司软件包时,应创建或更新公司技能
+- Agent 附加项应主要来自 `AGENTS.md` 中的 shortname 关联
+- `.paperclip.yaml` 可以增加 Paperclip 特定的保真度,但不应替代基础的 shortname 关联模型
+- 引用的第三方技能应保持溯源可见
-Export behavior:
+导出行为:
-- exporting a company should include company-managed skills when selected
-- `AGENTS.md` should emit skill associations by shortname or slug
-- `.paperclip.yaml` may add Paperclip-specific skill fidelity later if needed, but should not be required for ordinary agent-to-skill association
-- adapter-only external skills should not be silently exported as managed company skills
+- 导出公司时,若勾选,应包含公司托管技能
+- `AGENTS.md` 应以 shortname 或 slug 输出技能关联
+- 如有需要,`.paperclip.yaml` 日后可以添加 Paperclip 特定的技能保真度,但对于普通的 Agent 与技能关联不应作为必要条件
+- 仅适配器持有的外部技能不应被静默地导出为托管公司技能
-## 9.1 Import workflows
+## 9.1 导入工作流
-V1 workflows should support:
+V1 工作流应支持:
-1. import one or more skills from a local folder
-2. import one or more skills from a GitHub repo
-3. import a company package that contains skills
-4. attach imported skills to one or more agents
+1. 从本地文件夹导入一个或多个技能
+2. 从 GitHub 仓库导入一个或多个技能
+3. 导入包含技能的公司软件包
+4. 将导入的技能附加到一个或多个 Agent
-Import preview for skills should show:
+技能导入预览应显示:
-- skills discovered
-- source and pinning
-- trust level
-- licensing warnings
-- whether an existing company skill will be created, updated, or skipped
+- 已发现的技能
+- 来源与版本固定信息
+- 信任级别
+- 许可证警告
+- 现有公司技能将被创建、更新还是跳过
-## 9.2 Export workflows
+## 9.2 导出工作流
-V1 should support:
+V1 应支持:
-1. export a company with managed skills included when selected
-2. export an agent whose `AGENTS.md` contains shortname skill associations
-3. preserve Agent Skills compatibility for each `SKILL.md`
+1. 导出公司时,若勾选,包含托管技能
+2. 导出 `AGENTS.md` 中包含 shortname 技能关联的 Agent
+3. 为每个 `SKILL.md` 保留 Agent Skills 兼容性
-Out of scope for V1:
+V1 范围外:
-- exporting adapter-only external skills as managed packages automatically
+- 自动将仅适配器持有的外部技能作为托管软件包导出
-## 10. Data And API Shape
+## 10. 数据与 API 结构
-This plan implies a clean split in backend concepts.
+本计划意味着后端概念需要清晰拆分。
-### 10.1 Company skill records
+### 10.1 公司技能记录
-Paperclip should have a company-scoped skill model or managed package model representing:
+Paperclip 应有一个公司范围的技能模型或托管软件包模型,包含:
-- identity
-- source
-- files
-- provenance
-- trust and licensing metadata
+- 标识信息
+- 来源
+- 文件
+- 溯源信息
+- 信任与许可证元数据
-### 10.2 Agent skill attachments
+### 10.2 Agent 技能附加记录
-Paperclip should separately store:
+Paperclip 应单独存储:
- agent id
-- skill identity
-- desired enabled state
-- optional ordering or metadata later
+- 技能标识
+- 期望启用状态
+- 日后可选的排序或元数据
-### 10.3 Adapter sync snapshot
+### 10.3 适配器同步快照
-Adapter reads should return:
+适配器读取应返回:
-- supported flag
-- sync mode
-- entries
-- warnings
-- desired skills
+- supported flag(支持标志)
+- sync mode(同步模式)
+- entries(条目)
+- warnings(警告)
+- desired skills(期望技能)
-This already exists in rough form and should be the basis for the UI.
+这部分已有雏形,应作为 UI 的基础。
-### 10.4 UI-facing API needs
+### 10.4 UI 侧 API 需求
-The complete UI implies these API surfaces:
+完整的 UI 意味着需要以下 API 接口:
-- list company-managed skills
-- import company skills from path/URL/GitHub
-- get one company skill detail
-- list agents using a given skill
-- attach/detach company skills for an agent
-- list adapter sync snapshot for an agent
-- apply desired skills for an agent
+- 列出公司托管技能
+- 从路径/URL/GitHub 导入公司技能
+- 获取单个公司技能详情
+- 列出使用某技能的 Agent
+- 为 Agent 附加/分离公司技能
+- 获取 Agent 的适配器同步快照列表
+- 为 Agent 应用期望技能
-Existing agent-level skill sync APIs can remain the base for the agent tab.
-The company-level library APIs still need to be designed and implemented.
+现有的 Agent 级技能同步 API 可作为 Agent 标签页的基础。
+公司级库 API 仍需进行设计和实现。
-## 11. Page-by-page UX
+## 11. 逐页 UX 说明
-### 11.1 Company Skills list page
+### 11.1 公司技能列表页
-Header:
+页头:
-- title
-- short explanation of compatibility with Agent Skills / `skills.sh`
-- import button
+- 标题
+- 关于与 Agent Skills / `skills.sh` 兼容性的简短说明
+- 导入按钮
-Body:
+页面主体:
-- filters
-- skill table or cards
-- empty state when none
+- 筛选器
+- 技能表格或卡片
+- 无内容时的空状态
-Secondary content:
+次级内容:
-- warnings panel for untrusted or incompatible skills
+- 不受信任或不兼容技能的警告面板
-### 11.2 Company Skill detail page
+### 11.2 公司技能详情页
-Header:
+页头:
-- skill name
+- 技能名称
- shortname
-- source badge
-- trust badge
-- compatibility badge
+- 来源徽标
+- 信任徽标
+- 兼容性徽标
-Sections:
+章节:
-- rendered `SKILL.md`
-- files and references
-- usage by agents
-- source / provenance
-- trust and licensing warnings
+- 渲染后的 `SKILL.md`
+- 文件与引用
+- Agent 使用情况
+- 来源/溯源信息
+- 信任与许可证警告
-Actions:
+操作:
-- attach to agent
-- remove from company library later
-- export later
+- 附加到 Agent
+- 日后从公司库中移除
+- 日后导出
-### 11.3 Agent Skills tab
+### 11.3 Agent 技能标签页
-Header:
+页头:
-- adapter support summary
-- sync mode
-- refresh and sync actions
+- 适配器支持摘要
+- 同步模式
+- 刷新和同步操作
-Body:
+页面主体:
-- managed skills list
-- external/discovered skills list
-- warnings / unsupported state block
+- 已托管技能列表
+- 外部/已发现技能列表
+- 警告/不受支持状态区块
-## 12. States And Empty Cases
+## 12. 状态与空状态处理
-### 12.1 Company Skills page
+### 12.1 公司技能页面
-States:
+状态:
-- empty
-- loading
-- loaded
-- import in progress
-- import failed
+- empty(空)
+- loading(加载中)
+- loaded(已加载)
+- import in progress(导入中)
+- import failed(导入失败)
-### 12.2 Company Skill detail
+### 12.2 公司技能详情
-States:
+状态:
-- loading
-- not found
-- incompatible
-- loaded
+- loading(加载中)
+- not found(未找到)
+- incompatible(不兼容)
+- loaded(已加载)
-### 12.3 Agent Skills tab
+### 12.3 Agent 技能标签页
-States:
+状态:
-- loading snapshot
-- unsupported adapter
-- read-only adapter
-- sync-capable adapter
-- sync failed
-- stale draft
+- loading snapshot(加载快照中)
+- unsupported adapter(不受支持的适配器)
+- read-only adapter(只读适配器)
+- sync-capable adapter(支持同步的适配器)
+- sync failed(同步失败)
+- stale draft(草稿已过期)
-## 13. Permissions And Governance
+## 13. 权限与治理
-Suggested V1 policy:
+建议的 V1 策略:
-- board users can manage company skills
-- board users can attach skills to agents
-- agents themselves do not mutate company skill library by default
-- later, certain agents may get scoped permissions for skill attachment or sync
+- 管理员用户可以管理公司技能
+- 管理员用户可以将技能附加到 Agent
+- Agent 本身默认不修改公司技能库
+- 日后,某些 Agent 可能会获得技能附加或同步的范围权限
-## 14. UI Phases
+## 14. UI 阶段规划
-### Phase A: Stabilize current agent skill sync UI
+### 阶段 A:稳定当前 Agent 技能同步 UI
-Goals:
+目标:
-- move skills to an `AgentDetail` tab
-- improve status language
-- support desired-only state even on unsupported adapters
-- polish copy for persistent vs ephemeral adapters
+- 将技能移至 `AgentDetail` 标签页
+- 改进状态语言表述
+- 在不受支持的适配器上也支持仅期望状态
+- 优化持久化适配器与临时适配器的文案
-### Phase B: Add Company Skills page
+### 阶段 B:添加公司技能页面
-Goals:
+目标:
-- company-level skill library
-- import from GitHub/local folder
-- basic detail view
-- usage counts by agent
-- `skills.sh`-compatible import path
+- 公司级技能库
+- 从 GitHub/本地文件夹导入
+- 基础详情视图
+- 按 Agent 统计使用次数
+- 兼容 `skills.sh` 的导入路径
-### Phase C: Connect skills to portability
+### 阶段 C:将技能与可移植性连接
-Goals:
+目标:
-- importing company packages creates company skills
-- exporting selected skills works cleanly
-- agent attachments round-trip primarily through `AGENTS.md` shortnames
+- 导入公司软件包时创建公司技能
+- 导出所选技能时流程顺畅
+- Agent 附加项主要通过 `AGENTS.md` 中的 shortname 实现往返传递
-### Phase D: External skill adoption flow
+### 阶段 D:外部技能采纳流程
-Goals:
+目标:
-- detect adapter external skills
-- allow importing them into company-managed state where possible
-- make provenance explicit
+- 检测适配器外部技能
+- 允许在适当情况下将其导入为公司托管状态
+- 使溯源信息明确可见
-### Phase E: Advanced sync and drift UX
+### 阶段 E:高级同步与漂移 UX
-Goals:
+目标:
-- desired-vs-actual diffing
-- drift resolution actions
-- multi-agent skill usage and sync reporting
+- 期望状态与实际状态的差异对比
+- 漂移解决操作
+- 多 Agent 技能使用与同步报告
-## 15. Design Risks
+## 15. 设计风险
-1. Overloading the agent page with package management will make the feature confusing.
-2. Treating unsupported adapters as broken rather than unmanaged will make the product feel inconsistent.
-3. Mixing external adapter-discovered skills with company-managed skills without clear labels will erode trust.
-4. If company skill records do not exist, import/export and UI will remain loosely coupled and round-trip fidelity will stay weak.
-5. If agent skill associations are path-based instead of shortname-based, the format will feel too technical and too Paperclip-specific.
+1. 将软件包管理叠加到 Agent 页面会让功能变得令人困惑。
+2. 将不受支持的适配器视为"损坏"而非"未托管"会让产品显得不一致。
+3. 在没有清晰标签的情况下将外部适配器发现的技能与公司托管技能混合,会削弱用户信任。
+4. 如果公司技能记录不存在,导入/导出与 UI 将保持松耦合,往返传递的保真度也会偏低。
+5. 如果 Agent 技能关联基于路径而非 shortname,格式将显得过于技术性且过于 Paperclip 特定。
-## 16. Recommendation
+## 16. 建议
-The next product step should be:
+下一个产品步骤应是:
-1. move skills out of agent configuration and into a dedicated `Skills` tab
-2. add a dedicated company-level `Skills` page as the library and package-management surface
-3. make company import/export target that company skill library, not the agent page directly
-4. preserve adapter-aware truth in the UI by clearly separating:
- - desired
- - actual
- - external
- - unmanaged
-5. keep agent-to-skill associations shortname-based in `AGENTS.md`
+1. 将技能从 Agent 配置中移出,放入专属的 `Skills` 标签页
+2. 添加专属的公司级 `Skills` 页面,作为库与软件包管理的界面
+3. 让公司导入/导出指向该公司技能库,而非直接指向 Agent 页面
+4. 通过清晰分离以下状态,在 UI 中保持适配器感知的真实性:
+ - desired(期望)
+ - actual(实际)
+ - external(外部)
+ - unmanaged(未托管)
+5. 在 `AGENTS.md` 中保持 Agent 与技能关联基于 shortname
-That gives Paperclip one coherent skill story instead of forcing package management, adapter sync, and agent configuration into the same screen.
+这将使 Paperclip 拥有一个连贯的技能叙述,而不是将软件包管理、适配器同步和 Agent 配置强行压缩在同一个界面中。
diff --git a/doc/plans/2026-03-17-docker-release-browser-e2e.md b/doc/plans/2026-03-17-docker-release-browser-e2e.md
index e776206ae2..30fcaf7f5b 100644
--- a/doc/plans/2026-03-17-docker-release-browser-e2e.md
+++ b/doc/plans/2026-03-17-docker-release-browser-e2e.md
@@ -1,424 +1,424 @@
-# Docker Release Browser E2E Plan
+# Docker 发布浏览器端到端测试计划
-## Context
+## 背景
-Today release smoke testing for published Paperclip packages is manual and shell-driven:
+目前,针对已发布 Paperclip 包的发布冒烟测试是手动且依赖 shell 脚本的:
```sh
HOST_PORT=3232 DATA_DIR=./data/release-smoke-canary PAPERCLIPAI_VERSION=canary ./scripts/docker-onboard-smoke.sh
HOST_PORT=3233 DATA_DIR=./data/release-smoke-stable PAPERCLIPAI_VERSION=latest ./scripts/docker-onboard-smoke.sh
```
-That is useful because it exercises the same public install surface users hit:
+这种方式的价值在于,它与用户实际使用的公开安装路径完全一致:
- Docker
- `npx paperclipai@canary`
- `npx paperclipai@latest`
-- authenticated bootstrap flow
+- 已认证的引导流程
-But it still leaves the most important release questions to a human with a browser:
+但最关键的发布问题仍然需要人工在浏览器中验证:
-- can I sign in with the smoke credentials?
-- do I land in onboarding?
-- can I complete onboarding?
-- does the initial CEO agent actually get created and run?
+- 能否使用冒烟凭据登录?
+- 是否进入了引导流程页面?
+- 能否完成引导流程?
+- 初始 CEO 智能体是否真正被创建并运行?
-The repo already has two adjacent pieces:
+代码仓库中已有两个相关组件:
-- `tests/e2e/onboarding.spec.ts` covers the onboarding wizard against the local source tree
-- `scripts/docker-onboard-smoke.sh` boots a published Docker install and auto-bootstraps authenticated mode, but only verifies the API/session layer
+- `tests/e2e/onboarding.spec.ts` 负责针对本地源代码树验证引导向导
+- `scripts/docker-onboard-smoke.sh` 启动已发布的 Docker 安装并自动引导已认证模式,但仅验证 API/会话层
-What is missing is one deterministic browser test that joins those two paths.
+目前缺失的是一个能将这两条路径衔接起来的确定性浏览器测试。
-## Goal
+## 目标
-Add a release-grade Docker-backed browser E2E that validates the published `canary` and `latest` installs end to end:
+添加一套以 Docker 为后端的发布级浏览器端到端测试,全面验证已发布的 `canary` 和 `latest` 安装:
-1. boot the published package in Docker
-2. sign in with known smoke credentials
-3. verify the user is routed into onboarding
-4. complete onboarding in the browser
-5. verify the first CEO agent exists
-6. verify the initial CEO run was triggered and reached a terminal or active state
+1. 在 Docker 中启动已发布的包
+2. 使用已知冒烟凭据登录
+3. 验证用户被正确路由至引导流程页面
+4. 在浏览器中完成引导流程
+5. 验证首个 CEO 智能体已存在
+6. 验证初始 CEO 运行已触发,并达到终态或活跃状态
-Then wire that test into GitHub Actions so release validation is no longer manual-only.
+然后将该测试接入 GitHub Actions,使发布验证不再只是手动操作。
-## Recommendation In One Sentence
+## 一句话建议
-Turn the current Docker smoke script into a machine-friendly test harness, add a dedicated Playwright release-smoke spec that drives the authenticated browser flow against published Docker installs, and run it in GitHub Actions for both `canary` and `latest`.
+将现有 Docker 冒烟脚本改造为机器友好的测试框架,添加专用的 Playwright 发布冒烟规范,驱动已认证的浏览器流程针对已发布的 Docker 安装运行,并在 GitHub Actions 中分别对 `canary` 和 `latest` 执行该测试。
-## What We Have Today
+## 现有基础
-### Existing local browser coverage
+### 现有本地浏览器覆盖
-`tests/e2e/onboarding.spec.ts` already proves the onboarding wizard can:
+`tests/e2e/onboarding.spec.ts` 已经验证引导向导能够:
-- create a company
-- create a CEO agent
-- create an initial issue
-- optionally observe task progress
+- 创建公司
+- 创建 CEO 智能体
+- 创建初始问题
+- 可选地观察任务进度
-That is a good base, but it does not validate the public npm package, Docker path, authenticated login flow, or release dist-tags.
+这是一个良好的基础,但它不能验证公开 npm 包、Docker 路径、已认证登录流程或发布 dist-tag。
-### Existing Docker smoke coverage
+### 现有 Docker 冒烟覆盖
-`scripts/docker-onboard-smoke.sh` already does useful setup work:
+`scripts/docker-onboard-smoke.sh` 已经完成了有价值的设置工作:
-- builds `Dockerfile.onboard-smoke`
-- runs `paperclipai@${PAPERCLIPAI_VERSION}` inside Docker
-- waits for health
-- signs up or signs in a smoke admin user
-- generates and accepts the bootstrap CEO invite in authenticated mode
-- verifies a board session and `/api/companies`
+- 构建 `Dockerfile.onboard-smoke`
+- 在 Docker 内运行 `paperclipai@${PAPERCLIPAI_VERSION}`
+- 等待健康检查通过
+- 注册或登录冒烟管理员用户
+- 在已认证模式下生成并接受引导 CEO 邀请
+- 验证 board 会话以及 `/api/companies`
-That means the hard bootstrap problem is mostly solved already. The main gap is that the script is human-oriented and never hands control to a browser test.
+这意味着困难的引导问题已基本解决。主要缺口在于该脚本面向人工操作,从未将控制权移交给浏览器测试。
-### Existing CI shape
+### 现有 CI 结构
-The repo already has:
+代码仓库已有:
-- `.github/workflows/e2e.yml` for manual Playwright runs against local source
-- `.github/workflows/release.yml` for canary publish on `master` and manual stable promotion
+- `.github/workflows/e2e.yml`:用于针对本地源代码手动运行 Playwright
+- `.github/workflows/release.yml`:用于在 `master` 上发布 canary 以及手动晋升稳定版
-So the right move is to extend the current test/release system, not create a parallel one.
+因此,正确的做法是扩展现有的测试/发布体系,而非另起炉灶。
-## Product Decision
+## 产品决策
-### 1. The release smoke should stay deterministic and token-free
+### 1. 发布冒烟应保持确定性且无需外部 token
-The first version should not require OpenAI, Anthropic, or external agent credentials.
+第一个版本不应依赖 OpenAI、Anthropic 或外部智能体凭据。
-Use the onboarding flow with a deterministic adapter that can run on a stock GitHub runner and inside the published Docker install. The existing `process` adapter with a trivial command is the right base path for this release gate.
+使用确定性适配器的引导流程,该适配器可在标准 GitHub runner 和已发布的 Docker 安装中运行。现有的 `process` 适配器配合一个简单命令是此发布门禁的正确基础路径。
-That keeps this test focused on:
+这样可以让该测试聚焦于:
-- release packaging
-- auth/bootstrap
-- UI routing
-- onboarding contract
-- agent creation
-- heartbeat invocation plumbing
+- 发布打包
+- 认证/引导
+- UI 路由
+- 引导流程契约
+- 智能体创建
+- 心跳调用管道
-Later we can add a second credentialed smoke lane for real model-backed agents.
+之后可以为真实模型驱动的智能体添加第二条需要凭据的冒烟通道。
-### 2. Smoke credentials become an explicit test contract
+### 2. 冒烟凭据成为明确的测试契约
-The current defaults in `scripts/docker-onboard-smoke.sh` should be treated as stable test fixtures:
+`scripts/docker-onboard-smoke.sh` 中的当前默认值应被视为稳定的测试固件:
-- email: `smoke-admin@paperclip.local`
-- password: `paperclip-smoke-password`
+- 邮箱:`smoke-admin@paperclip.local`
+- 密码:`paperclip-smoke-password`
-The browser test should log in with those exact values unless overridden by env vars.
+除非通过环境变量覆盖,否则浏览器测试应使用这些确切值登录。
-### 3. Published-package smoke and source-tree E2E stay separate
+### 3. 已发布包的冒烟测试与源代码树端到端测试保持独立
-Keep two lanes:
+维护两条通道:
-- source-tree E2E for feature development
-- published Docker release smoke for release confidence
+- 源代码树端到端测试用于功能开发
+- 已发布 Docker 发布冒烟测试用于发布信心保障
-They overlap on onboarding assertions, but they guard different failure classes.
+两者在引导流程断言上有重叠,但它们防护的是不同类别的故障。
-## Proposed Design
+## 方案设计
-## 1. Add a CI-friendly Docker smoke harness
+## 1. 添加 CI 友好的 Docker 冒烟框架
-Refactor `scripts/docker-onboard-smoke.sh` so it can run in two modes:
+重构 `scripts/docker-onboard-smoke.sh`,使其支持两种运行模式:
-- interactive mode
- - current behavior
- - streams logs and waits in foreground for manual inspection
-- CI mode
- - starts the container
- - waits for health and authenticated bootstrap
- - prints machine-readable metadata
- - exits while leaving the container running for Playwright
+- 交互模式
+ - 保留当前行为
+ - 在前台流式输出日志,等待人工检查
+- CI 模式
+ - 启动容器
+ - 等待健康检查通过并完成已认证引导
+ - 输出机器可读的元数据
+ - 退出时保留容器运行,供 Playwright 使用
-Recommended shape:
+推荐结构:
-- keep `scripts/docker-onboard-smoke.sh` as the public entry point
-- add a `SMOKE_DETACH=true` or `--detach` mode
-- emit a JSON blob or `.env` file containing:
+- 保留 `scripts/docker-onboard-smoke.sh` 作为公开入口点
+- 添加 `SMOKE_DETACH=true` 或 `--detach` 模式
+- 输出包含以下内容的 JSON 数据块或 `.env` 文件:
- `SMOKE_BASE_URL`
- `SMOKE_ADMIN_EMAIL`
- `SMOKE_ADMIN_PASSWORD`
- `SMOKE_CONTAINER_NAME`
- `SMOKE_DATA_DIR`
-The workflow and Playwright tests can then consume the emitted metadata instead of scraping logs.
+工作流和 Playwright 测试随后可以使用输出的元数据,而无需解析日志。
-### Why this matters
+### 为何重要
-The current script always tails logs and then blocks on `wait "$LOG_PID"`. That is convenient for manual smoke testing, but it is the wrong shape for CI orchestration.
+当前脚本始终跟踪日志,然后阻塞在 `wait "$LOG_PID"` 处。这对手动冒烟测试来说很方便,但对 CI 编排而言是错误的形态。
-## 2. Add a dedicated Playwright release-smoke spec
+## 2. 添加专用的 Playwright 发布冒烟规范
-Create a second Playwright entry point specifically for published Docker installs, for example:
+为已发布的 Docker 安装创建第二个 Playwright 入口点,例如:
- `tests/release-smoke/playwright.config.ts`
- `tests/release-smoke/docker-auth-onboarding.spec.ts`
-This suite should not use Playwright `webServer`, because the app server will already be running inside Docker.
+该测试套件不应使用 Playwright 的 `webServer`,因为应用服务器已在 Docker 内部运行。
-### Browser scenario
+### 浏览器测试场景
-The first release-smoke scenario should validate:
+第一个发布冒烟场景应验证:
-1. open `/`
-2. unauthenticated user is redirected to `/auth`
-3. sign in using the smoke credentials
-4. authenticated user lands on onboarding when no companies exist
-5. onboarding wizard appears with the expected step labels
-6. create a company
-7. create the first agent using `process`
-8. create the initial issue
-9. finish onboarding and open the created issue
-10. verify via API:
- - company exists
- - CEO agent exists
- - issue exists and is assigned to the CEO
-11. verify the first heartbeat run was triggered:
- - either by checking issue status changed from initial state, or
- - by checking agent/runs API shows a run for the CEO, or
- - both
+1. 打开 `/`
+2. 未认证用户被重定向到 `/auth`
+3. 使用冒烟凭据登录
+4. 已认证用户在无公司时进入引导流程页面
+5. 引导向导显示预期的步骤标签
+6. 创建公司
+7. 使用 `process` 创建首个智能体
+8. 创建初始问题
+9. 完成引导流程并打开已创建的问题
+10. 通过 API 验证:
+ - 公司已存在
+ - CEO 智能体已存在
+ - 问题已存在且分配给 CEO
+11. 验证首次心跳运行已触发:
+ - 检查问题状态是否从初始状态改变,或
+ - 检查 agent/runs API 是否显示 CEO 的运行记录,或
+ - 两者都检查
-The test should tolerate the run completing quickly. For this reason, the assertion should accept:
+测试应容忍运行快速完成的情况。因此,断言应接受以下状态:
- `queued`
- `running`
- `succeeded`
-and similarly for issue progression if the issue status changes before the assertion runs.
+对于断言运行前问题状态已发生变化的情况,问题进展也应同样处理。
-### Why a separate spec instead of reusing `tests/e2e/onboarding.spec.ts`
+### 为何使用独立规范而非复用 `tests/e2e/onboarding.spec.ts`
-The local-source test and release-smoke test have different assumptions:
+本地源代码测试和发布冒烟测试的前提假设不同:
-- different server lifecycle
-- different auth path
-- different deployment mode
-- published npm package instead of local workspace code
+- 服务器生命周期不同
+- 认证路径不同
+- 部署模式不同
+- 使用已发布的 npm 包而非本地工作区代码
-Trying to force both through one spec will make both worse.
+强行将两者合并到一个规范中只会让两者都变得更糟。
-## 3. Add a release-smoke workflow in GitHub Actions
+## 3. 在 GitHub Actions 中添加发布冒烟工作流
-Add a workflow dedicated to this surface, ideally reusable:
+添加一个专用于此场景的工作流,最好可复用:
- `.github/workflows/release-smoke.yml`
-Recommended triggers:
+推荐触发方式:
- `workflow_dispatch`
- `workflow_call`
-Recommended inputs:
+推荐输入参数:
- `paperclip_version`
- - `canary` or `latest`
+ - `canary` 或 `latest`
- `host_port`
- - optional, default runner-safe port
+ - 可选,默认为 runner 安全端口
- `artifact_name`
- - optional for clearer uploads
-
-### Job outline
-
-1. checkout repo
-2. install Node/pnpm
-3. install Playwright browser dependencies
-4. launch Docker smoke harness in detached mode with the chosen dist-tag
-5. run the release-smoke Playwright suite against the returned base URL
-6. always collect diagnostics:
- - Playwright report
- - screenshots
- - trace
+ - 可选,用于更清晰的产物上传命名
+
+### 作业概要
+
+1. 检出代码仓库
+2. 安装 Node/pnpm
+3. 安装 Playwright 浏览器依赖
+4. 以分离模式启动 Docker 冒烟框架,使用选定的 dist-tag
+5. 针对返回的 base URL 运行发布冒烟 Playwright 测试套件
+6. 始终收集诊断信息:
+ - Playwright 报告
+ - 截图
+ - 追踪记录
- `docker logs`
- - harness metadata file
-7. stop and remove container
+ - 框架元数据文件
+7. 停止并移除容器
-### Why a reusable workflow
+### 为何使用可复用工作流
-This lets us:
+这使我们能够:
-- run the smoke manually on demand
-- call it from `release.yml`
-- reuse the same job for both `canary` and `latest`
+- 按需手动运行冒烟测试
+- 从 `release.yml` 调用它
+- 对 `canary` 和 `latest` 复用同一个作业
-## 4. Integrate it into release automation incrementally
+## 4. 逐步集成到发布自动化中
-### Phase A: Manual workflow only
+### 阶段 A:仅限手动工作流
-First ship the workflow as manual-only so the harness and test can be stabilized without blocking releases.
+首先将工作流作为纯手动方式发布,以便在不阻塞发布的情况下稳定框架和测试。
-### Phase B: Run automatically after canary publish
+### 阶段 B:在 canary 发布后自动运行
-After `publish_canary` succeeds in `.github/workflows/release.yml`, call the reusable release-smoke workflow with:
+当 `.github/workflows/release.yml` 中的 `publish_canary` 成功后,调用可复用的发布冒烟工作流,参数为:
- `paperclip_version=canary`
-This proves the just-published public canary really boots and onboards.
+这将证明刚发布的公开 canary 确实能正常启动并完成引导流程。
-### Phase C: Run automatically after stable publish
+### 阶段 C:在稳定版发布后自动运行
-After `publish_stable` succeeds, call the same workflow with:
+当 `publish_stable` 成功后,以如下参数调用同一工作流:
- `paperclip_version=latest`
-This gives us post-publish confirmation that the stable dist-tag is healthy.
+这为我们提供了稳定版 dist-tag 健康状况的发布后确认。
-### Important nuance
+### 重要说明
-Testing `latest` from npm cannot happen before stable publish, because the package under test does not exist under `latest` yet. So the `latest` smoke is a post-publish verification, not a pre-publish gate.
+在稳定版发布之前无法测试来自 npm 的 `latest`,因为待测包在 `latest` 标签下尚不存在。因此,`latest` 冒烟是发布后验证,而非发布前门禁。
-If we later want a true pre-publish stable gate, that should be a separate source-ref or locally built package smoke job.
+如果之后需要真正的发布前稳定版门禁,应使用独立的 source-ref 或本地构建的包冒烟作业来实现。
-## 5. Make diagnostics first-class
+## 5. 将诊断信息提升为一等公民
-This workflow is only valuable if failures are fast to debug.
+只有当失败能被快速调试时,这个工作流才真正有价值。
-Always capture:
+始终捕获:
-- Playwright HTML report
-- Playwright trace on failure
-- final screenshot on failure
-- full `docker logs` output
-- emitted smoke metadata
-- optional `curl /api/health` snapshot
+- Playwright HTML 报告
+- 失败时的 Playwright 追踪记录
+- 失败时的最终截图
+- 完整的 `docker logs` 输出
+- 输出的冒烟元数据
+- 可选的 `curl /api/health` 快照
-Without that, the test will become a flaky black box and people will stop trusting it.
+否则,测试将变成一个不稳定的黑盒,大家最终会失去对它的信任。
-## Implementation Plan
+## 实施计划
-## Phase 1: Harness refactor
+## 第一阶段:框架重构
-Files:
+涉及文件:
- `scripts/docker-onboard-smoke.sh`
-- optionally `scripts/lib/docker-onboard-smoke.sh` or similar helper
+- 可选:`scripts/lib/docker-onboard-smoke.sh` 或类似辅助文件
- `doc/DOCKER.md`
- `doc/RELEASING.md`
-Tasks:
+任务:
-1. Add detached/CI mode to the Docker smoke script.
-2. Make the script emit machine-readable connection metadata.
-3. Keep the current interactive manual mode intact.
-4. Add reliable cleanup commands for CI.
+1. 为 Docker 冒烟脚本添加分离/CI 模式。
+2. 让脚本输出机器可读的连接元数据。
+3. 保留当前的交互式手动模式不变。
+4. 为 CI 添加可靠的清理命令。
-Acceptance:
+验收标准:
-- a script invocation can start the published Docker app, auto-bootstrap it, and return control to the caller with enough metadata for browser automation
+- 一次脚本调用能够启动已发布的 Docker 应用、自动引导它,并将控制权返回给调用者,同时附带足够的浏览器自动化元数据
-## Phase 2: Browser release-smoke suite
+## 第二阶段:浏览器发布冒烟测试套件
-Files:
+涉及文件:
- `tests/release-smoke/playwright.config.ts`
- `tests/release-smoke/docker-auth-onboarding.spec.ts`
-- root `package.json`
+- 根目录 `package.json`
-Tasks:
+任务:
-1. Add a dedicated Playwright config for external server testing.
-2. Implement login + onboarding + CEO creation flow.
-3. Assert a CEO run was created or completed.
-4. Add a root script such as:
+1. 为外部服务器测试添加专用的 Playwright 配置。
+2. 实现登录 + 引导流程 + CEO 创建流程。
+3. 断言 CEO 运行已被创建或完成。
+4. 添加根级脚本,例如:
- `test:release-smoke`
-Acceptance:
+验收标准:
-- the suite passes locally against both:
+- 测试套件在本地针对以下两种情况均能通过:
- `PAPERCLIPAI_VERSION=canary`
- `PAPERCLIPAI_VERSION=latest`
-## Phase 3: GitHub Actions workflow
+## 第三阶段:GitHub Actions 工作流
-Files:
+涉及文件:
- `.github/workflows/release-smoke.yml`
-Tasks:
+任务:
-1. Add manual and reusable workflow entry points.
-2. Install Chromium and runner dependencies.
-3. Start Docker smoke in detached mode.
-4. Run the release-smoke Playwright suite.
-5. Upload diagnostics artifacts.
+1. 添加手动和可复用的工作流入口点。
+2. 安装 Chromium 和 runner 依赖项。
+3. 以分离模式启动 Docker 冒烟测试。
+4. 运行发布冒烟 Playwright 测试套件。
+5. 上传诊断产物。
-Acceptance:
+验收标准:
-- a maintainer can run the workflow manually for either `canary` or `latest`
+- 维护者可以针对 `canary` 或 `latest` 手动运行工作流
-## Phase 4: Release workflow integration
+## 第四阶段:发布工作流集成
-Files:
+涉及文件:
- `.github/workflows/release.yml`
- `doc/RELEASING.md`
-Tasks:
+任务:
-1. Trigger release smoke automatically after canary publish.
-2. Trigger release smoke automatically after stable publish.
-3. Document expected behavior and failure handling.
+1. 在 canary 发布后自动触发发布冒烟测试。
+2. 在稳定版发布后自动触发发布冒烟测试。
+3. 记录预期行为和失败处理方式。
-Acceptance:
+验收标准:
-- canary releases automatically produce a published-package browser smoke result
-- stable releases automatically produce a `latest` browser smoke result
+- canary 发布后自动产生已发布包的浏览器冒烟结果
+- 稳定版发布后自动产生 `latest` 浏览器冒烟结果
-## Phase 5: Future extension for real model-backed agent validation
+## 第五阶段:未来扩展——真实模型驱动的智能体验证
-Not part of the first implementation, but this should be the next layer after the deterministic lane is stable.
+不属于第一版实现,但这应该是确定性通道稳定后的下一层。
-Possible additions:
+可能的扩展:
-- a second Playwright project gated on repo secrets
-- real `claude_local` or `codex_local` adapter validation in Docker-capable environments
-- assertion that the CEO posts a real task/comment artifact
-- stable release holdback until the credentialed lane passes
+- 第二个 Playwright 项目,以仓库 secrets 为门禁
+- 在支持 Docker 的环境中对真实 `claude_local` 或 `codex_local` 适配器进行验证
+- 断言 CEO 发布了真实的任务/评论产物
+- 稳定版发布需等待凭据通道通过才能放行
-This should stay optional until the token-free lane is trustworthy.
+在无 token 通道可信赖之前,此部分应保持可选状态。
-## Acceptance Criteria
+## 验收标准
-The plan is complete when the implemented system can demonstrate all of the following:
+当已实现的系统能够证明以下所有内容时,本计划即告完成:
-1. A published `paperclipai@canary` Docker install can be smoke-tested by Playwright in CI.
-2. A published `paperclipai@latest` Docker install can be smoke-tested by Playwright in CI.
-3. The test logs into authenticated mode with the smoke credentials.
-4. The test sees onboarding for a fresh instance.
-5. The test completes onboarding in the browser.
-6. The test verifies the initial CEO agent was created.
-7. The test verifies at least one CEO heartbeat run was triggered.
-8. Failures produce actionable artifacts rather than just a red job.
+1. 已发布的 `paperclipai@canary` Docker 安装可以在 CI 中由 Playwright 进行冒烟测试。
+2. 已发布的 `paperclipai@latest` Docker 安装可以在 CI 中由 Playwright 进行冒烟测试。
+3. 测试使用冒烟凭据登录已认证模式。
+4. 测试在全新实例中看到引导流程。
+5. 测试在浏览器中完成引导流程。
+6. 测试验证初始 CEO 智能体已被创建。
+7. 测试验证至少一次 CEO 心跳运行已触发。
+8. 失败时产生可操作的产物,而不仅仅是一个红色的作业状态。
-## Risks And Decisions To Make
+## 风险与待决策事项
-### 1. Fast process runs may finish before the UI visibly updates
+### 1. 快速运行的进程可能在 UI 更新前已完成
-That is expected. The assertions should prefer API polling for run existence/status rather than only visual indicators.
+这是预期行为。断言应优先通过 API 轮询运行的存在性/状态,而非仅依赖视觉指示器。
-### 2. `latest` smoke is post-publish, not preventive
+### 2. `latest` 冒烟是发布后验证,而非预防性措施
-This is a real limitation of testing the published dist-tag itself. It is still valuable, but it should not be confused with a pre-publish gate.
+这是测试已发布 dist-tag 本身的真实局限性。它仍然有价值,但不应与发布前门禁混淆。
-### 3. We should not overcouple the test to cosmetic onboarding text
+### 3. 不应将测试过度耦合到引导流程的界面文本上
-The important contract is flow success, created entities, and run creation. Use visible labels sparingly and prefer stable semantic selectors where possible.
+重要的契约是流程成功、已创建的实体以及运行的创建。尽量少使用可见标签,尽可能优先选用稳定的语义选择器。
-### 4. Keep the smoke adapter path boring
+### 4. 保持冒烟适配器路径简单无趣
-For release safety, the first test should use the most boring runnable adapter possible. This is not the place to validate every adapter.
+为了发布安全,第一个测试应使用尽可能简单的可运行适配器。这里不是验证每个适配器的地方。
-## Recommended First Slice
+## 推荐首个切片
-If we want the fastest path to value, ship this in order:
+如果希望以最快路径创造价值,请按以下顺序交付:
-1. add detached mode to `scripts/docker-onboard-smoke.sh`
-2. add one Playwright spec for authenticated login + onboarding + CEO run verification
-3. add manual `release-smoke.yml`
-4. once stable, wire canary into `release.yml`
-5. after that, wire stable `latest` smoke into `release.yml`
+1. 为 `scripts/docker-onboard-smoke.sh` 添加分离模式
+2. 添加一个 Playwright 规范,覆盖已认证登录 + 引导流程 + CEO 运行验证
+3. 添加手动 `release-smoke.yml`
+4. 稳定后,将 canary 接入 `release.yml`
+5. 之后,将稳定版 `latest` 冒烟接入 `release.yml`
-That gives release confidence quickly without turning the first version into a large CI redesign.
+这能在不将第一版变成大规模 CI 重设计的前提下,快速建立发布信心。
diff --git a/doc/plans/2026-03-17-memory-service-surface-api.md b/doc/plans/2026-03-17-memory-service-surface-api.md
index 68b33bd3f5..30ab9cb0a2 100644
--- a/doc/plans/2026-03-17-memory-service-surface-api.md
+++ b/doc/plans/2026-03-17-memory-service-surface-api.md
@@ -1,117 +1,117 @@
-# Paperclip Memory Service Plan
+# Paperclip 记忆服务计划
-## Goal
+## 目标
-Define a Paperclip memory service and surface API that can sit above multiple memory backends, while preserving Paperclip's control-plane requirements:
+定义一套 Paperclip 记忆服务及其表层 API,使其能够位于多个记忆后端之上,同时保留 Paperclip 控制平面的核心要求:
-- company scoping
-- auditability
-- provenance back to Paperclip work objects
-- budget / cost visibility
-- plugin-first extensibility
+- 公司级隔离范围
+- 可审计性
+- 溯源至 Paperclip 工作对象
+- 预算 / 成本可见性
+- 插件优先的可扩展性
-This plan is based on the external landscape summarized in `doc/memory-landscape.md` and on the current Paperclip architecture in:
+本计划基于 `doc/memory-landscape.md` 中总结的外部技术全景,以及以下文件中描述的当前 Paperclip 架构:
- `doc/SPEC-implementation.md`
- `doc/plugins/PLUGIN_SPEC.md`
- `doc/plugins/PLUGIN_AUTHORING_GUIDE.md`
- `packages/plugins/sdk/src/types.ts`
-## Recommendation In One Sentence
+## 一句话建议
-Paperclip should not embed one opinionated memory engine into core. It should add a company-scoped memory control plane with a small normalized adapter contract, then let built-ins and plugins implement the provider-specific behavior.
+Paperclip 不应将某一特定记忆引擎嵌入核心。它应添加一个公司级范围的记忆控制平面,并附带一套小型规范化适配器契约,然后由内置实现和插件负责提供商特定的行为。
-## Product Decisions
+## 产品决策
-### 1. Memory is company-scoped by default
+### 1. 记忆默认以公司为范围
-Every memory binding belongs to exactly one company.
+每个记忆绑定恰好属于一家公司。
-That binding can then be:
+该绑定随后可以是:
-- the company default
-- an agent override
-- a project override later if we need it
+- 公司默认绑定
+- Agent 覆盖绑定
+- 如有需要,后续添加项目级覆盖绑定
-No cross-company memory sharing in the initial design.
+初始设计中不支持跨公司记忆共享。
-### 2. Providers are selected by key
+### 2. 提供商通过键名选择
-Each configured memory provider gets a stable key inside a company, for example:
+每个已配置的记忆提供商在公司内部拥有一个稳定的键名,例如:
- `default`
- `mem0-prod`
- `local-markdown`
- `research-kb`
-Agents and services resolve the active provider by key, not by hard-coded vendor logic.
+Agent 和服务通过键名解析活跃提供商,而非通过硬编码的供应商逻辑。
-### 3. Plugins are the primary provider path
+### 3. 插件是主要的提供商接入路径
-Built-ins are useful for a zero-config local path, but most providers should arrive through the existing Paperclip plugin runtime.
+内置实现对零配置的本地路径很有价值,但大多数提供商应通过现有的 Paperclip 插件运行时接入。
-That keeps the core small and matches the current direction that optional knowledge-like systems live at the edges.
+这样可以保持核心精简,并与当前将可选知识型系统置于边缘的方向保持一致。
-### 4. Paperclip owns routing, provenance, and accounting
+### 4. Paperclip 负责路由、溯源和计费
-Providers should not decide how Paperclip entities map to governance.
+提供商不应决定 Paperclip 实体如何映射到治理机制。
-Paperclip core should own:
+Paperclip 核心应负责:
-- who is allowed to call a memory operation
-- which company / agent / project scope is active
-- what issue / run / comment / document the operation belongs to
-- how usage gets recorded
+- 哪些主体被允许调用记忆操作
+- 当前活跃的公司 / Agent / 项目范围
+- 该操作属于哪个工单 / 运行 / 评论 / 文档
+- 使用量如何被记录
-### 5. Automatic memory should be narrow at first
+### 5. 自动记忆在初期应保持范围收窄
-Automatic capture is useful, but broad silent capture is dangerous.
+自动捕获很有价值,但大范围的静默捕获是危险的。
-Initial automatic hooks should be:
+初始自动钩子应为:
-- post-run capture from agent runs
-- issue comment / document capture when the binding enables it
-- pre-run recall for agent context hydration
+- Agent 运行结束后的捕获
+- 绑定启用时的工单评论 / 文档捕获
+- 运行前的记忆召回,用于 Agent 上下文预填充
-Everything else should start explicit.
+其他所有情况应从显式操作开始。
-## Proposed Concepts
+## 核心概念
-### Memory provider
+### 记忆提供商
-A built-in or plugin-supplied implementation that stores and retrieves memory.
+内置或由插件提供的实现,负责存储和检索记忆。
-Examples:
+示例:
-- local markdown + vector index
-- mem0 adapter
-- supermemory adapter
-- MemOS adapter
+- 本地 markdown + 向量索引
+- mem0 适配器
+- supermemory 适配器
+- MemOS 适配器
-### Memory binding
+### 记忆绑定
-A company-scoped configuration record that points to a provider and carries provider-specific config.
+一条公司级范围的配置记录,指向某个提供商并携带该提供商的特定配置。
-This is the object selected by key.
+这是通过键名选择的对象。
-### Memory scope
+### 记忆范围
-The normalized Paperclip scope passed into a provider request.
+传入提供商请求的规范化 Paperclip 范围对象。
-At minimum:
+最低包含:
- `companyId`
-- optional `agentId`
-- optional `projectId`
-- optional `issueId`
-- optional `runId`
-- optional `subjectId` for external/user identity
+- 可选的 `agentId`
+- 可选的 `projectId`
+- 可选的 `issueId`
+- 可选的 `runId`
+- 可选的 `subjectId`,用于外部 / 用户身份
-### Memory source reference
+### 记忆来源引用
-The provenance handle that explains where a memory came from.
+解释记忆来源的溯源句柄。
-Supported source kinds should include:
+支持的来源类型应包括:
- `issue_comment`
- `issue_document`
@@ -121,15 +121,15 @@ Supported source kinds should include:
- `manual_note`
- `external_document`
-### Memory operation
+### 记忆操作
-A normalized write, query, browse, or delete action performed through Paperclip.
+通过 Paperclip 执行的规范化写入、查询、浏览或删除动作。
-Paperclip should log every operation, whether the provider is local or external.
+无论提供商是本地还是外部,Paperclip 都应记录每次操作的日志。
-## Required Adapter Contract
+## 必需的适配器契约
-The required core should be small enough to fit `memsearch`, `mem0`, `Memori`, `MemOS`, or `OpenViking`.
+必需的核心应足够精简,以兼容 `memsearch`、`mem0`、`Memori`、`MemOS` 或 `OpenViking`。
```ts
export interface MemoryAdapterCapabilities {
@@ -230,32 +230,32 @@ export interface MemoryAdapter {
}
```
-This contract intentionally does not force a provider to expose its internal graph, filesystem, or ontology.
+该契约有意不强制要求提供商暴露其内部图结构、文件系统或本体论。
-## Optional Adapter Surfaces
+## 可选的适配器接口
-These should be capability-gated, not required:
+以下接口应基于能力声明来开放,而非强制要求:
-- `browse(scope, filters)` for file-system / graph / timeline inspection
-- `correct(handle, patch)` for natural-language correction flows
-- `profile(scope)` when the provider can synthesize stable preferences or summaries
-- `sync(source)` for connectors or background ingestion
-- `explain(queryResult)` for providers that can expose retrieval traces
+- `browse(scope, filters)`:用于文件系统 / 图结构 / 时间线检查
+- `correct(handle, patch)`:用于自然语言纠错流程
+- `profile(scope)`:当提供商能够合成稳定的偏好或摘要时使用
+- `sync(source)`:用于连接器或后台数据摄取
+- `explain(queryResult)`:用于能够暴露检索追踪信息的提供商
-## What Paperclip Should Persist
+## Paperclip 应持久化的内容
-Paperclip should not mirror the full provider memory corpus into Postgres unless the provider is a Paperclip-managed local provider.
+除非提供商是由 Paperclip 管理的本地提供商,否则 Paperclip 不应将提供商的完整记忆语料库镜像到 Postgres。
-Paperclip core should persist:
+Paperclip 核心应持久化:
-- memory bindings and overrides
-- provider keys and capability metadata
-- normalized memory operation logs
-- provider record handles returned by operations when available
-- source references back to issue comments, documents, runs, and activity
-- usage and cost data
+- 记忆绑定及其覆盖配置
+- 提供商键名和能力元数据
+- 规范化的记忆操作日志
+- 操作返回的提供商记录句柄(如有)
+- 指向工单评论、文档、运行和活动的来源引用
+- 使用量和成本数据
-For external providers, the memory payload itself can remain in the provider.
+对于外部提供商,记忆的实际内容可以保留在提供商侧。
## Hook Model
diff --git a/doc/plans/2026-03-17-release-automation-and-versioning.md b/doc/plans/2026-03-17-release-automation-and-versioning.md
index 5701a7abc6..9610d1ec68 100644
--- a/doc/plans/2026-03-17-release-automation-and-versioning.md
+++ b/doc/plans/2026-03-17-release-automation-and-versioning.md
@@ -1,8 +1,8 @@
-# Release Automation and Versioning Simplification Plan
+# 发布自动化与版本管理简化方案
-## Context
+## 背景
-Paperclip's current release flow is documented in `doc/RELEASING.md` and implemented through:
+Paperclip 当前的发布流程记录于 `doc/RELEASING.md`,并通过以下文件实现:
- `.github/workflows/release.yml`
- `scripts/release-lib.sh`
@@ -11,478 +11,478 @@ Paperclip's current release flow is documented in `doc/RELEASING.md` and impleme
- `scripts/release.sh`
- `scripts/create-github-release.sh`
-Today the model is:
+当前的工作模型是:
-1. pick `patch`, `minor`, or `major`
-2. create `release/X.Y.Z`
-3. draft `releases/vX.Y.Z.md`
-4. publish one or more canaries from that release branch
-5. publish stable from that same branch
-6. push tag + create GitHub Release
-7. merge the release branch back to `master`
+1. 选择 `patch`、`minor` 或 `major`
+2. 创建 `release/X.Y.Z`
+3. 起草 `releases/vX.Y.Z.md`
+4. 从该发布分支发布一个或多个 canary 版本
+5. 从同一分支发布稳定版
+6. 推送标签并创建 GitHub Release
+7. 将发布分支合并回 `master`
-That is workable, but it creates friction in exactly the places that should be cheap:
+这套流程虽然可行,但在本应低成本的环节引入了不必要的摩擦:
-- deciding `patch` vs `minor` vs `major`
-- cutting and carrying release branches
-- manually publishing canaries
-- thinking about changelog generation for canaries
-- handling npm credentials safely in a public repo
+- 决定用 `patch`、`minor` 还是 `major`
+- 创建并维护发布分支
+- 手动发布 canary 版本
+- 为 canary 版本考虑变更日志生成
+- 在公开仓库中安全管理 npm 凭证
-The target state from this discussion is simpler:
+本次讨论所期望达到的目标状态更为简洁:
-- every push to `master` publishes a canary automatically
-- stable releases are promoted deliberately from a vetted commit
-- versioning is date-driven instead of semantics-driven
-- stable publishing is secure even in a public open-source repository
-- changelog generation happens only for real stable releases
+- 每次推送到 `master` 都自动发布 canary 版本
+- 稳定版从经过验证的提交中有意识地晋升
+- 版本号以日期为驱动,而非语义化驱动
+- 即使在公开的开源仓库中,稳定版发布也是安全的
+- 变更日志生成仅针对真正的稳定版发布
-## Recommendation In One Sentence
+## 一句话建议
-Move Paperclip to semver-compatible calendar versioning, auto-publish canaries from `master`, promote stable from a chosen tested commit, and use npm trusted publishing plus GitHub environments so no long-lived npm or LLM token needs to live in Actions.
+将 Paperclip 迁移到与 semver 兼容的日历版本格式,从 `master` 自动发布 canary 版本,从选定的已测试提交中晋升稳定版,并使用 npm 可信发布与 GitHub 环境,从而无需在 Actions 中存储长期有效的 npm 或 LLM 令牌。
-## Core Decisions
+## 核心决策
-### 1. Use calendar versions, but keep semver syntax
+### 1. 使用日历版本,但保留 semver 语法
-The repo and npm tooling still assume semver-shaped version strings in many places. That does not mean Paperclip must keep semver as a product policy. It does mean the version format should remain semver-valid.
+仓库和 npm 工具链在许多地方仍假定版本字符串具有 semver 形式。这并不意味着 Paperclip 必须将 semver 作为产品策略,但版本格式应保持 semver 合法性。
-Recommended format:
+推荐格式:
- stable: `YYYY.MDD.P`
- canary: `YYYY.MDD.P-canary.N`
-Examples:
+示例:
-- first stable on March 17, 2026: `2026.317.0`
-- third canary on the `2026.317.0` line: `2026.317.0-canary.2`
+- 2026 年 3 月 17 日的首个稳定版:`2026.317.0`
+- `2026.317.0` 系列的第三个 canary 版本:`2026.317.0-canary.2`
-Why this shape:
+选用此格式的原因:
-- it removes `patch/minor/major` decisions
-- it is valid semver syntax
-- it stays compatible with npm, dist-tags, and existing semver validators
-- it is close to the format you actually want
+- 消除了 `patch/minor/major` 的决策负担
+- 符合 semver 语法规范
+- 与 npm、dist-tags 及现有 semver 校验器保持兼容
+- 接近你实际期望的格式
-Important constraints:
+重要约束:
-- the middle numeric slot should be `MDD`, where `M` is the month and `DD` is the zero-padded day
-- `2026.03.17` is not the format to use
- - numeric semver identifiers do not allow leading zeroes
-- `2026.3.17.1` is not the format to use
- - semver has three numeric components, not four
-- the practical semver-safe equivalent is `2026.317.0-canary.8`
+- 中间数字段应为 `MDD`,其中 `M` 是月份,`DD` 是零填充的日期
+- 不应使用 `2026.03.17` 这种格式
+ - semver 数字标识符不允许前导零
+- 不应使用 `2026.3.17.1` 这种格式
+ - semver 只有三个数字部分,不是四个
+- 实际符合 semver 规范的等效写法为 `2026.317.0-canary.8`
-This is effectively CalVer on semver rails.
+这实际上是在 semver 轨道上运行的 CalVer。
-### 2. Accept that CalVer changes the compatibility contract
+### 2. 接受 CalVer 改变了兼容性契约这一事实
-This is not semver in spirit anymore. It is semver in syntax only.
+这在精神层面上不再是 semver,只是在语法上保留了 semver 的形式。
-That tradeoff is probably acceptable for Paperclip, but it should be explicit:
+这种权衡对 Paperclip 而言可能是可以接受的,但应当明确说明:
-- consumers no longer infer compatibility from `major/minor/patch`
-- release notes become the compatibility signal
-- downstream users should prefer exact pins or deliberate upgrades
+- 消费者不能再从 `major/minor/patch` 推断兼容性
+- 发布说明成为兼容性信号
+- 下游用户应优先使用精确版本锁定或有意识的升级
-This is especially relevant for public library packages like `@paperclipai/shared`, `@paperclipai/db`, and the adapter packages.
+这对 `@paperclipai/shared`、`@paperclipai/db` 及各适配器等公开库包尤为重要。
-### 3. Drop release branches for normal publishing
+### 3. 常规发布不再使用发布分支
-If every merge to `master` publishes a canary, the current `release/X.Y.Z` train model becomes more ceremony than value.
+如果每次合并到 `master` 都会发布 canary,当前的 `release/X.Y.Z` 列车模型就变成了形式大于实质的繁文缛节。
-Recommended replacement:
+建议的替代方案:
-- `master` is the only canary train
-- every push to `master` can publish a canary
-- stable is published from a chosen commit or canary tag on `master`
+- `master` 是唯一的 canary 发布轨道
+- 每次推送到 `master` 都可以发布 canary 版本
+- 稳定版从 `master` 上选定的提交或 canary 标签发布
-This matches the workflow you actually want:
+这与你实际期望的工作流相符:
-- merge continuously
-- let npm always have a fresh canary
-- choose a known-good canary later and promote that commit to stable
+- 持续合并代码
+- 让 npm 始终拥有最新的 canary 版本
+- 稍后选择一个已知可靠的 canary 版本,并将该提交晋升为稳定版
-### 4. Promote by source ref, not by "renaming" a canary
+### 4. 通过源引用晋升,而不是"重命名" canary 版本
-This is the most important mechanical constraint.
+这是最重要的机制约束。
-npm can move dist-tags, but it does not let you rename an already-published version. That means:
+npm 可以移动 dist-tags,但不允许重命名已发布的版本。这意味着:
-- you can move `latest` to `paperclipai@1.2.3`
-- you cannot turn `paperclipai@2026.317.0-canary.8` into `paperclipai@2026.317.0`
+- 可以将 `latest` 指向 `paperclipai@1.2.3`
+- 无法将 `paperclipai@2026.317.0-canary.8` 改名为 `paperclipai@2026.317.0`
-So "promote canary to stable" really means:
+因此,"将 canary 晋升为稳定版"实际上意味着:
-1. choose the commit or canary tag you trust
-2. rebuild from that exact commit
-3. publish it again with the stable version string
+1. 选择你信任的提交或 canary 标签
+2. 从该精确提交重新构建
+3. 使用稳定版版本字符串重新发布
-Because of that, the stable workflow should take a source ref, not just a bump type.
+基于此,稳定版工作流应接受源引用作为输入,而不仅仅是一个升级类型。
-Recommended stable input:
+推荐的稳定版输入:
- `source_ref`
- - commit SHA, or
- - a canary git tag such as `canary/v2026.317.1-canary.8`
+ - 提交 SHA,或
+ - 形如 `canary/v2026.317.1-canary.8` 的 canary git 标签
-### 5. Only stable releases get release notes, tags, and GitHub Releases
+### 5. 只有稳定版才生成发布说明、标签和 GitHub Release
-Canaries should stay lightweight:
+Canary 版本应保持轻量:
-- publish to npm under `canary`
-- optionally create a lightweight or annotated git tag
-- do not create GitHub Releases
-- do not require `releases/v*.md`
-- do not spend LLM tokens
+- 以 `canary` dist-tag 发布到 npm
+- 可选地创建轻量或注释型 git 标签
+- 不创建 GitHub Release
+- 不要求 `releases/v*.md`
+- 不消耗 LLM token
-Stable releases should remain the public narrative surface:
+稳定版应继续作为公开叙述的呈现面:
-- git tag `v2026.317.0`
+- git 标签 `v2026.317.0`
- GitHub Release `v2026.317.0`
-- stable changelog file `releases/v2026.317.0.md`
+- 稳定版变更日志文件 `releases/v2026.317.0.md`
-## Security Model
+## 安全模型
-### Recommendation
+### 建议
-Use npm trusted publishing with GitHub Actions OIDC, then disable token-based publishing access for the packages.
+使用带 GitHub Actions OIDC 的 npm 可信发布,然后禁用各包基于令牌的发布访问权限。
-Why:
+原因:
-- no long-lived `NPM_TOKEN` in repo or org secrets
-- no personal npm token in Actions
-- short-lived credentials minted only for the authorized workflow
-- automatic npm provenance for public packages in public repos
+- 仓库或组织 secrets 中无需存储长期有效的 `NPM_TOKEN`
+- Actions 中无需个人 npm 令牌
+- 短期凭证仅在授权工作流执行时生成
+- 在公开仓库中自动为公开包提供 npm 来源证明
-This is the cleanest answer to the open-repo security concern.
+这是应对开放仓库安全顾虑最简洁的答案。
-### Concrete controls
+### 具体控制措施
-#### 1. Use one release workflow file
+#### 1. 使用单一发布工作流文件
-Use one workflow filename for both canary and stable publishing:
+canary 和稳定版发布统一使用同一个工作流文件:
- `.github/workflows/release.yml`
-Why:
+原因:
-- npm trusted publishing is configured per workflow filename
-- npm currently allows one trusted publisher configuration per package
-- GitHub environments can still provide separate canary/stable approval rules inside the same workflow
+- npm 可信发布按工作流文件名进行配置
+- npm 目前每个包只允许一个可信发布者配置
+- GitHub 环境仍可在同一工作流内提供独立的 canary/稳定版审批规则
-#### 2. Use separate GitHub environments
+#### 2. 使用独立的 GitHub 环境
-Recommended environments:
+推荐的环境:
- `npm-canary`
- `npm-stable`
-Recommended policy:
+推荐策略:
- `npm-canary`
- - allowed branch: `master`
- - no human reviewer required
+ - 允许分支:`master`
+ - 无需人工审查
- `npm-stable`
- - allowed branch: `master`
- - required reviewer enabled
- - prevent self-review enabled
- - admin bypass disabled
+ - 允许分支:`master`
+ - 启用必要审查人
+ - 启用禁止自我审查
+ - 禁用管理员绕过
-Stable should require an explicit second human gate even if the workflow is manually dispatched.
+即使工作流是手动触发的,稳定版也应要求明确的第二道人工关卡。
-#### 3. Lock down workflow edits
+#### 3. 锁定工作流编辑权限
-Add or tighten `CODEOWNERS` coverage for:
+为以下路径添加或收紧 `CODEOWNERS` 覆盖范围:
- `.github/workflows/*`
- `scripts/release*`
- `doc/RELEASING.md`
-This matters because trusted publishing authorizes a workflow file. The biggest remaining risk is not secret exfiltration from forks. It is a maintainer-approved change to the release workflow itself.
+这一点很重要,因为可信发布授权的是工作流文件。最大的剩余风险不是 fork 中的 secret 泄露,而是经维护者批准对发布工作流本身的修改。
-#### 4. Remove traditional npm token access after OIDC works
+#### 4. OIDC 验证通过后移除传统 npm 令牌访问权限
-After trusted publishing is verified:
+可信发布验证完成后:
-- set package publishing access to require 2FA and disallow tokens
-- revoke any legacy automation tokens
+- 将包发布访问设置为要求 2FA,并禁止令牌访问
+- 撤销所有旧的自动化令牌
-That eliminates the "someone stole the npm token" class of failure.
+这消除了"有人窃取 npm 令牌"这类故障的可能性。
-### What not to do
+### 不应做的事
-- do not put your personal Claude or npm token in GitHub Actions
-- do not run release logic from `pull_request_target`
-- do not make stable publishing depend on a repo secret if OIDC can handle it
-- do not create canary GitHub Releases
+- 不要将个人 Claude 或 npm 令牌放入 GitHub Actions
+- 不要从 `pull_request_target` 运行发布逻辑
+- 如果 OIDC 可以处理,就不要让稳定版发布依赖仓库 secret
+- 不要为 canary 版本创建 GitHub Release
-## Changelog Strategy
+## 变更日志策略
-### Recommendation
+### 建议
-Generate stable changelogs only, and keep LLM-assisted changelog generation out of CI for now.
+仅为稳定版生成变更日志,暂时将 LLM 辅助变更日志生成排除在 CI 之外。
-Reasoning:
+理由:
-- canaries happen too often
-- canaries do not need polished public notes
-- putting a personal Claude token into Actions is not worth the risk
-- stable release cadence is low enough that a human-in-the-loop step is acceptable
+- canary 版本发布过于频繁
+- canary 版本不需要精心打磨的公开说明
+- 将个人 Claude 令牌放入 Actions 所带来的风险不值得冒
+- 稳定版发布频率较低,人工介入的步骤是可以接受的
-Recommended stable path:
+推荐的稳定版流程:
-1. pick a canary commit or tag
-2. run changelog generation locally from a trusted machine
-3. commit `releases/vYYYY.MDD.P.md`
-4. run stable promotion
+1. 选取一个 canary 提交或标签
+2. 在可信机器上本地运行变更日志生成
+3. 提交 `releases/vYYYY.MDD.P.md`
+4. 执行稳定版晋升
-If the notes are not ready yet, a fallback is acceptable:
+如果说明文档尚未就绪,可采用备用方案:
-- publish stable
-- create a minimal GitHub Release
-- update `releases/vYYYY.MDD.P.md` immediately afterward
+- 发布稳定版
+- 创建一个最简 GitHub Release
+- 随后立即更新 `releases/vYYYY.MDD.P.md`
-But the better steady-state is to have the stable notes committed before stable publish.
+但更理想的常态是在发布稳定版之前就已提交稳定版说明文档。
-### Future option
+### 未来选项
-If you later want CI-assisted changelog drafting, do it with:
+如果日后需要 CI 辅助起草变更日志,可通过以下方式实现:
-- a dedicated service account
-- a token scoped only for changelog generation
-- a manual workflow
-- a dedicated environment with required reviewers
+- 专用服务账户
+- 仅限变更日志生成范围的令牌
+- 手动触发的工作流
+- 配有必要审查人的专用环境
-That is phase-two hardening work, not a phase-one requirement.
+这是第二阶段的加固工作,不是第一阶段的必要条件。
-## Proposed Future Workflow
+## 拟定的未来工作流
-### Canary workflow
+### Canary 工作流
-Trigger:
+触发条件:
-- `push` on `master`
+- `master` 分支上的 `push` 事件
-Steps:
+步骤:
-1. checkout the merged `master` commit
-2. run verification on that exact commit
-3. compute canary version for current UTC date
-4. version public packages to `YYYY.MDD.P-canary.N`
-5. publish to npm with dist-tag `canary`
-6. create a canary git tag for traceability
+1. 检出已合并的 `master` 提交
+2. 对该精确提交运行验证
+3. 根据当前 UTC 日期计算 canary 版本号
+4. 将公开包版本设为 `YYYY.MDD.P-canary.N`
+5. 以 dist-tag `canary` 发布到 npm
+6. 创建 canary git 标签以便追溯
-Recommended canary tag format:
+推荐的 canary 标签格式:
- `canary/v2026.317.1-canary.4`
-Outputs:
+产出:
-- npm canary published
-- git tag created
-- no GitHub Release
-- no changelog file required
+- npm canary 版本已发布
+- git 标签已创建
+- 无 GitHub Release
+- 无需变更日志文件
-### Stable workflow
+### 稳定版工作流
-Trigger:
+触发条件:
-- `workflow_dispatch`
+- `workflow_dispatch`(手动触发)
-Inputs:
+输入参数:
- `source_ref`
-- optional `stable_date`
+- 可选的 `stable_date`
- `dry_run`
-Steps:
+步骤:
-1. checkout `source_ref`
-2. run verification on that exact commit
-3. compute the next stable patch slot for the UTC date or provided override
-4. fail if `vYYYY.MDD.P` already exists
-5. require `releases/vYYYY.MDD.P.md`
-6. version public packages to `YYYY.MDD.P`
-7. publish to npm under `latest`
-8. create git tag `vYYYY.MDD.P`
-9. push tag
-10. create GitHub Release from `releases/vYYYY.MDD.P.md`
+1. 检出 `source_ref`
+2. 对该精确提交运行验证
+3. 根据 UTC 日期或提供的覆盖值计算下一个稳定版 patch 槽位
+4. 如果 `vYYYY.MDD.P` 已存在则失败
+5. 要求存在 `releases/vYYYY.MDD.P.md`
+6. 将公开包版本设为 `YYYY.MDD.P`
+7. 以 `latest` 标签发布到 npm
+8. 创建 git 标签 `vYYYY.MDD.P`
+9. 推送标签
+10. 基于 `releases/vYYYY.MDD.P.md` 创建 GitHub Release
-Outputs:
+产出:
-- stable npm release
-- stable git tag
+- 稳定版 npm 发布
+- 稳定版 git 标签
- GitHub Release
-- clean public changelog surface
+- 整洁的公开变更日志呈现面
-## Implementation Guidance
+## 实施指导
-### 1. Replace bump-type version math with explicit version computation
+### 1. 用显式版本计算替换基于升级类型的版本数学
-The current release scripts depend on:
+当前发布脚本依赖于:
- `patch`
- `minor`
- `major`
-That logic should be replaced with:
+这些逻辑应替换为:
- `compute_canary_version_for_date`
- `compute_stable_version_for_date`
-For example:
+例如:
- `next_stable_version(2026-03-17) -> 2026.317.0`
- `next_canary_for_utc_date(2026-03-17) -> 2026.317.0-canary.0`
-### 2. Stop requiring `release/X.Y.Z`
+### 2. 不再要求 `release/X.Y.Z`
-These current invariants should be removed from the happy path:
+以下当前不变式应从正常流程中移除:
-- "must run from branch `release/X.Y.Z`"
-- "stable and canary for `X.Y.Z` come from the same release branch"
+- "必须从分支 `release/X.Y.Z` 运行"
+- "`X.Y.Z` 的稳定版和 canary 版来自同一发布分支"
- `release-start.sh`
-Replace them with:
+替换为:
-- canary must run from `master`
-- stable may run from a pinned `source_ref`
+- canary 必须从 `master` 运行
+- 稳定版可从固定的 `source_ref` 运行
-### 3. Keep Changesets only if it stays helpful
+### 3. 仅在 Changesets 仍有帮助时才保留它
-The current system uses Changesets to:
+当前系统使用 Changesets 来:
-- rewrite package versions
-- maintain package-level `CHANGELOG.md` files
-- publish packages
+- 重写包版本
+- 维护包级别的 `CHANGELOG.md` 文件
+- 发布包
-With CalVer, Changesets may still be useful for publish orchestration, but it should no longer own version selection.
+使用 CalVer 后,Changesets 在发布编排方面可能仍然有用,但不应再由它主导版本选择。
-Recommended implementation order:
+推荐的实施顺序:
-1. keep `changeset publish` if it works with explicitly-set versions
-2. replace version computation with a small explicit versioning script
-3. if Changesets keeps fighting the model, remove it from release publishing entirely
+1. 如果 `changeset publish` 能与显式设置的版本配合使用,则保留它
+2. 用一个小型的显式版本脚本替换版本计算逻辑
+3. 如果 Changesets 持续与该模型产生冲突,则将其从发布流程中完全移除
-Paperclip's release problem is now "publish the whole fixed package set at one explicit version", not "derive the next semantic bump from human intent".
+Paperclip 的发布问题现在是"以一个显式版本发布整个固定包集合",而不是"从人类意图推导出下一个语义升级"。
-### 4. Add a dedicated versioning script
+### 4. 添加专用版本设置脚本
-Recommended new script:
+推荐的新脚本:
- `scripts/set-release-version.mjs`
-Responsibilities:
+职责:
-- set the version in all public publishable packages
-- update any internal exact-version references needed for publishing
-- update CLI version strings
-- avoid broad string replacement across unrelated files
+- 为所有公开可发布的包设置版本号
+- 更新发布所需的内部精确版本引用
+- 更新 CLI 版本字符串
+- 避免在无关文件中进行宽泛的字符串替换
-This is safer than keeping a bump-oriented changeset flow and then forcing it into a date-based scheme.
+这比保留以升级为导向的 changeset 流程再强行将其纳入日期方案更为安全。
-### 5. Keep rollback based on dist-tags
+### 5. 保留基于 dist-tags 的回滚机制
-`rollback-latest.sh` should stay, but it should stop assuming a semver meaning beyond syntax.
+`rollback-latest.sh` 应保留,但应不再假定 semver 语法之外的语义含义。
-It should continue to:
+它应继续:
-- repoint `latest` to a prior stable version
-- never unpublish
+- 将 `latest` 重新指向先前的稳定版
+- 从不取消发布
-## Tradeoffs and Risks
+## 权衡与风险
-### 1. The stable patch slot is now part of the version contract
+### 1. 稳定版 patch 槽位现在是版本契约的一部分
-With `YYYY.MDD.P`, same-day hotfixes are supported, but the stable patch slot is now part of the visible version format.
+使用 `YYYY.MDD.P` 后,同日热修复仍受支持,但稳定版 patch 槽位现已成为可见版本格式的一部分。
-That is the right tradeoff because:
+这是正确的权衡,因为:
-1. npm still gets semver-valid versions
-2. same-day hotfixes stay possible
-3. chronological ordering still works as long as the day is zero-padded inside `MDD`
+1. npm 仍能获得符合 semver 的版本
+2. 同日热修复依然可行
+3. 只要在 `MDD` 内对日期进行零填充,时间顺序排列仍然有效
-### 2. Public package consumers lose semver intent signaling
+### 2. 公开包消费者失去了 semver 意图信号
-This is the main downside of CalVer.
+这是 CalVer 的主要缺点。
-If that becomes a problem, one alternative is:
+如果这成为问题,一种替代方案是:
-- use CalVer for the CLI package only
-- keep semver for library packages
+- 仅对 CLI 包使用 CalVer
+- 库包继续使用 semver
-That is more complex operationally, so I would not start there unless package consumers actually need it.
+这在操作上更为复杂,因此除非包消费者确实有此需求,否则不建议从这里开始。
-### 3. Auto-canary means more publish traffic
+### 3. 自动 canary 意味着更多发布流量
-Publishing on every `master` merge means:
+每次合并到 `master` 都发布意味着:
-- more npm versions
-- more git tags
-- more registry noise
+- 更多 npm 版本
+- 更多 git 标签
+- 更多注册表噪声
-That is acceptable if canaries stay clearly separate:
+如果 canary 版本保持清晰分离,这是可以接受的:
- npm dist-tag `canary`
-- no GitHub Release
-- no external announcement
+- 无 GitHub Release
+- 无外部公告
-## Rollout Plan
+## 推进计划
-### Phase 1: Security foundation
+### 第一阶段:安全基础
-1. Create `release.yml`
-2. Configure npm trusted publishers for all public packages
-3. Create `npm-canary` and `npm-stable` environments
-4. Add `CODEOWNERS` protection for release files
-5. Verify OIDC publishing works
-6. Disable token-based publishing access and revoke old tokens
+1. 创建 `release.yml`
+2. 为所有公开包配置 npm 可信发布者
+3. 创建 `npm-canary` 和 `npm-stable` 环境
+4. 为发布文件添加 `CODEOWNERS` 保护
+5. 验证 OIDC 发布是否正常工作
+6. 禁用基于令牌的发布访问权限并撤销旧令牌
-### Phase 2: Canary automation
+### 第二阶段:Canary 自动化
-1. Add canary workflow on `push` to `master`
-2. Add explicit calendar-version computation
-3. Add canary git tagging
-4. Remove changelog requirement from canaries
-5. Update `doc/RELEASING.md`
+1. 添加在 `master` 上 `push` 时触发的 canary 工作流
+2. 添加显式日历版本计算
+3. 添加 canary git 标签创建
+4. 移除 canary 版本的变更日志要求
+5. 更新 `doc/RELEASING.md`
-### Phase 3: Stable promotion
+### 第三阶段:稳定版晋升
-1. Add manual stable workflow with `source_ref`
-2. Require stable notes file
-3. Publish stable + tag + GitHub Release
-4. Update rollback docs and scripts
-5. Retire release-branch assumptions
+1. 添加带 `source_ref` 参数的手动稳定版工作流
+2. 要求存在稳定版说明文件
+3. 发布稳定版 + 标签 + GitHub Release
+4. 更新回滚文档和脚本
+5. 废弃发布分支相关假设
-### Phase 4: Cleanup
+### 第四阶段:清理
-1. Remove `release-start.sh` from the primary path
-2. Remove `patch/minor/major` from maintainer docs
-3. Decide whether to keep or remove Changesets from publishing
-4. Document the CalVer compatibility contract publicly
+1. 从主流程中移除 `release-start.sh`
+2. 从维护者文档中移除 `patch/minor/major`
+3. 决定是否在发布流程中保留或移除 Changesets
+4. 公开记录 CalVer 兼容性契约
-## Concrete Recommendation
+## 具体建议
-Paperclip should adopt this model:
+Paperclip 应采用以下模型:
-- stable versions: `YYYY.MDD.P`
-- canary versions: `YYYY.MDD.P-canary.N`
-- canaries auto-published on every push to `master`
-- stables manually promoted from a chosen tested commit or canary tag
-- no release branches in the default path
-- no canary changelog files
-- no canary GitHub Releases
-- no Claude token in GitHub Actions
-- no npm automation token in GitHub Actions
-- npm trusted publishing plus GitHub environments for release security
+- 稳定版格式:`YYYY.MDD.P`
+- canary 版格式:`YYYY.MDD.P-canary.N`
+- 每次推送到 `master` 自动发布 canary 版本
+- 稳定版从选定的已测试提交或 canary 标签手动晋升
+- 默认流程中不使用发布分支
+- 无 canary 变更日志文件
+- 无 canary GitHub Release
+- GitHub Actions 中无 Claude 令牌
+- GitHub Actions 中无 npm 自动化令牌
+- 使用 npm 可信发布与 GitHub 环境保障发布安全
-That gets rid of the annoying part of semver without fighting npm, makes canaries cheap, keeps stables deliberate, and materially improves the security posture of the public repository.
+这在不与 npm 对抗的前提下消除了 semver 中令人烦恼的部分,使 canary 版本轻量化,保持稳定版发布的审慎性,并从实质上改善了公开仓库的安全态势。
-## External References
+## 外部参考
-- npm trusted publishing: https://docs.npmjs.com/trusted-publishers/
-- npm dist-tags: https://docs.npmjs.com/adding-dist-tags-to-packages/
-- npm semantic versioning guidance: https://docs.npmjs.com/about-semantic-versioning/
-- GitHub environments and deployment protection rules: https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments
-- GitHub secrets behavior for forks: https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets
+- npm 可信发布:https://docs.npmjs.com/trusted-publishers/
+- npm dist-tags:https://docs.npmjs.com/adding-dist-tags-to-packages/
+- npm 语义化版本指导:https://docs.npmjs.com/about-semantic-versioning/
+- GitHub 环境与部署保护规则:https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments
+- fork 中的 GitHub secrets 行为:https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets
diff --git a/doc/plans/workspace-product-model-and-work-product.md b/doc/plans/workspace-product-model-and-work-product.md
index 25c8c46454..d88cf88c91 100644
--- a/doc/plans/workspace-product-model-and-work-product.md
+++ b/doc/plans/workspace-product-model-and-work-product.md
@@ -1,191 +1,191 @@
-# Workspace Product Model, Work Product, and PR Flow
+# 工作区产品模型、工作成果与 PR 流程
-## Context
+## 背景
-Paperclip needs to support two very different but equally valid ways of working:
+Paperclip 需要支持两种截然不同但同样合理的工作方式:
-- a solo developer working directly on `master`, or in a folder that is not even a git repo
-- a larger engineering workflow with isolated branches, previews, pull requests, and cleanup automation
+- 单人开发者直接在 `master` 上工作,或在甚至不是 git 仓库的文件夹中工作
+- 更大规模的工程流程,包含隔离分支、预览环境、拉取请求和清理自动化
-Today, Paperclip already has the beginnings of this model:
+目前,Paperclip 已经具备了该模型的雏形:
-- `projects` can carry execution workspace policy
-- `project_workspaces` already exist as a durable project-scoped object
-- issues can carry execution workspace settings
-- runtime services can be attached to a workspace or issue
+- `projects` 可以携带执行工作区策略
+- `project_workspaces` 已作为持久的项目级对象存在
+- issues 可以携带执行工作区设置
+- 运行时服务可以绑定到工作区或 issue
-What is missing is a clear product model and UI that make these capabilities understandable and operable.
+目前缺少的是清晰的产品模型和 UI,使这些功能可被理解和操作。
-The main product risk is overloading one concept to do too much:
+主要的产品风险在于让一个概念承担过多职责:
-- making subissues do the job of branches or PRs
-- making projects too infrastructure-heavy
-- making workspaces so hidden that users cannot form a mental model
-- making Paperclip feel like a code review tool instead of a control plane
+- 让子 issue 承担分支或 PR 的职责
+- 让项目变得过于基础设施化
+- 让工作区过于隐蔽,导致用户无法建立心智模型
+- 让 Paperclip 看起来像是代码评审工具而非控制平面
-## Goals
+## 目标
-1. Keep `project` lightweight enough to remain a planning container.
-2. Make workspace behavior understandable for both git and non-git projects.
-3. Support three real workflows without forcing one:
- - shared workspace / direct-edit workflows
- - isolated issue workspace workflows
- - long-lived branch or operator integration workflows
-4. Provide a first-class place to see the outputs of work:
- - previews
- - PRs
- - branches
- - commits
- - documents and artifacts
-5. Keep the main navigation and task board simple.
-6. Seamlessly upgrade existing Paperclip users to the new model without forcing disruptive reconfiguration.
-7. Support cloud-hosted Paperclip deployments where execution happens in remote or adapter-managed environments rather than local workers.
+1. 保持 `project` 足够轻量,使其仍然是一个规划容器。
+2. 让工作区行为对 git 和非 git 项目都易于理解。
+3. 支持三种真实工作流,而不强制选择某一种:
+ - 共享工作区 / 直接编辑工作流
+ - 隔离 issue 工作区工作流
+ - 长期存活的分支或运营者集成工作流
+4. 提供一个一等位置来查看工作成果:
+ - 预览
+ - PR
+ - 分支
+ - 提交
+ - 文档和制品
+5. 保持主导航和任务看板简洁。
+6. 无缝升级现有 Paperclip 用户至新模型,不强制进行破坏性的重新配置。
+7. 支持云托管的 Paperclip 部署,其中执行发生在远程或适配器管理的环境中,而非本地工作进程。
-## Non-Goals
+## 非目标
-- Turning Paperclip into a full code review product
-- Requiring every issue to have its own branch or PR
-- Requiring every project to configure code/workspace automation
-- Making workspaces a top-level global navigation primitive in V1
-- Requiring a local filesystem path or local git checkout to use workspace-aware execution
+- 将 Paperclip 变成完整的代码评审产品
+- 要求每个 issue 必须有自己的分支或 PR
+- 要求每个项目必须配置代码/工作区自动化
+- 在 V1 中将工作区设为顶级全局导航入口
+- 要求使用本地文件系统路径或本地 git checkout 才能使用工作区感知执行
-## Core Product Decisions
+## 核心产品决策
-### 1. Project stays the planning object
+### 1. Project 保持为规划对象
-A `project` remains the thing that groups work around a deliverable or initiative.
+`project` 仍然是将工作围绕某个交付成果或计划进行分组的对象。
-It may have:
+它可以具有:
-- no code at all
-- one default codebase/workspace
-- several codebases/workspaces
+- 完全没有代码
+- 一个默认代码库/工作区
+- 多个代码库/工作区
-Projects are not required to become heavyweight.
+项目不需要变得笨重。
-### 2. Project workspace is a first-class object, but scoped under project
+### 2. 项目工作区是一等对象,但归属于项目范围
-A `project workspace` is the durable codebase or root environment for a project.
+`project workspace` 是项目的持久代码库或根环境。
-Examples:
+示例:
-- a local folder on disk
-- a git repo checkout
-- a monorepo package root
-- a non-git design/doc folder
-- a remote adapter-managed codebase reference
+- 磁盘上的本地文件夹
+- git 仓库的检出
+- 单体仓库的包根目录
+- 非 git 设计/文档文件夹
+- 远程适配器管理的代码库引用
-This is the stable anchor that operators configure once.
+这是运营者一次性配置的稳定锚点。
-It should not be a top-level sidebar item in the main app. It should live under the project experience.
+它不应该是主应用中的顶级侧边栏条目,而应该存在于项目体验之下。
-### 3. Execution workspace is a first-class runtime object
+### 3. 执行工作区是一等运行时对象
-An `execution workspace` is where a specific run or issue actually executes.
+`execution workspace` 是特定运行或 issue 实际执行的地方。
-Examples:
+示例:
-- the shared project workspace itself
-- an isolated git worktree
-- a long-lived operator branch checkout
-- an adapter-managed remote sandbox
-- a cloud agent provider's isolated branch/session environment
+- 共享的项目工作区本身
+- 隔离的 git worktree
+- 长期存活的运营者分支检出
+- 适配器管理的远程沙箱
+- 云代理提供商的隔离分支/会话环境
-This object must be recorded explicitly so that Paperclip can:
+必须显式记录此对象,以便 Paperclip 能够:
-- show where work happened
-- attach previews and runtime services
-- link PRs and branches
-- decide cleanup behavior
-- support reuse across multiple related issues
+- 显示工作发生的位置
+- 绑定预览和运行时服务
+- 关联 PR 和分支
+- 决定清理行为
+- 支持跨多个相关 issue 的重用
-### 4. PRs are work product, not the core issue model
+### 4. PR 是工作成果,而非核心 issue 模型
-A PR is an output of work, not the planning unit.
+PR 是工作的输出,而非规划单元。
-Paperclip should treat PRs as a type of work product linked back to:
+Paperclip 应将 PR 视为一种工作成果,关联回:
-- the issue
-- the execution workspace
-- optionally the project workspace
+- issue
+- 执行工作区
+- 可选关联项目工作区
-Git-specific automation should live under workspace policy, not under the core issue abstraction.
+Git 专属自动化应存在于工作区策略之下,而非核心 issue 抽象之下。
-### 5. Existing users must upgrade automatically
+### 5. 现有用户必须自动升级
-Paperclip already has users and existing project/task data. Any new model must preserve continuity.
+Paperclip 已有用户和现有的项目/任务数据。任何新模型都必须保持延续性。
-The product should default existing installs into a sensible compatibility mode:
+产品应将现有安装默认设置为合理的兼容模式:
-- existing projects without workspace configuration continue to work unchanged
-- existing `project_workspaces` become the durable `project workspace` objects
-- existing project execution workspace policy is mapped forward rather than discarded
-- issues without explicit workspace fields continue to inherit current behavior
+- 没有工作区配置的现有项目继续正常工作
+- 现有的 `project_workspaces` 成为持久的 `project workspace` 对象
+- 现有的项目执行工作区策略被映射延续,而非丢弃
+- 没有显式工作区字段的 issue 继续继承当前行为
-This migration should feel additive, not like a mandatory re-onboarding flow.
+此迁移应感觉是累加的,而非强制重新引导流程。
-### 6. Cloud-hosted Paperclip must be a first-class deployment mode
+### 6. 云托管 Paperclip 必须是一等部署模式
-Paperclip cannot assume that it is running on the same machine as the code.
+Paperclip 不能假设它与代码运行在同一台机器上。
-In cloud deployments, Paperclip may:
+在云部署中,Paperclip 可能:
-- run on Vercel or another serverless host
-- have no long-lived local worker process
-- delegate execution to a remote coding agent or provider-managed sandbox
-- receive back a branch, PR, preview URL, or artifact from that remote environment
+- 运行在 Vercel 或其他无服务器主机上
+- 没有长期存活的本地工作进程
+- 将执行委托给远程编码代理或提供商管理的沙箱
+- 从该远程环境接收回分支、PR、预览 URL 或制品
-The model therefore must be portable:
+因此模型必须是可移植的:
-- `project workspace` may be remote-managed, not local
-- `execution workspace` may have no local `cwd`
-- `runtime services` may be tracked by provider reference and URL rather than a host process
-- work product harvesting must handle externally owned previews and PRs
+- `project workspace` 可能是远程管理的,而非本地
+- `execution workspace` 可能没有本地 `cwd`
+- `runtime services` 可能通过提供商引用和 URL 进行追踪,而非宿主进程
+- 工作成果收集必须处理外部拥有的预览和 PR
-### 7. Subissues remain planning and ownership structure
+### 7. 子 issue 保持为规划和所有权结构
-Subissues are for decomposition and parallel ownership.
+子 issue 用于分解和并行所有权。
-They are not the same thing as:
+它们与以下内容不同:
-- a branch
-- a worktree
-- a PR
-- a preview
+- 分支
+- worktree
+- PR
+- 预览
-They may correlate with those things, but they should not be overloaded to mean them.
+它们可能与这些事物相关联,但不应被过度赋予其含义。
-## Terminology
+## 术语
-Use these terms consistently in product copy:
+在产品文案中一致使用以下术语:
-- `Project`: planning container
-- `Project workspace`: durable configured codebase/root
-- `Execution workspace`: actual runtime workspace used for issue execution
-- `Isolated issue workspace`: user-facing term for an issue-specific derived workspace
-- `Work product`: previews, PRs, branches, commits, artifacts, docs
-- `Runtime service`: a process or service Paperclip owns or tracks for a workspace
+- `Project`:规划容器
+- `Project workspace`:持久配置的代码库/根目录
+- `Execution workspace`:用于 issue 执行的实际运行时工作区
+- `Isolated issue workspace`:面向用户的术语,指特定于某 issue 的派生工作区
+- `Work product`:预览、PR、分支、提交、制品、文档
+- `Runtime service`:Paperclip 为工作区拥有或追踪的进程或服务
-Use these terms consistently in migration and deployment messaging:
+在迁移和部署消息中一致使用以下术语:
-- `Compatible mode`: existing behavior preserved without new workspace automation
-- `Adapter-managed workspace`: workspace realized by a remote or cloud execution provider
+- `Compatible mode`:在没有新工作区自动化的情况下保留现有行为
+- `Adapter-managed workspace`:由远程或云执行提供商实现的工作区
-Avoid teaching users that "workspace" always means "git worktree on my machine".
+避免让用户认为"工作区"总是意味着"我机器上的 git worktree"。
-## Product Object Model
+## 产品对象模型
## 1. Project
-Existing object. No fundamental change in role.
+现有对象。角色没有根本性变化。
-### Required behavior
+### 必需行为
-- can exist without code/workspace configuration
-- can have zero or more project workspaces
-- can define execution defaults that new issues inherit
+- 可以在没有代码/工作区配置的情况下存在
+- 可以有零个或多个项目工作区
+- 可以定义新 issue 继承的执行默认值
-### Proposed fields
+### 建议字段
- `id`
- `companyId`
@@ -201,24 +201,24 @@ Existing object. No fundamental change in role.
## 2. Project Workspace
-Durable, configured, project-scoped codebase/root object.
+持久、已配置、项目范围的代码库/根目录对象。
-This should evolve from the current `project_workspaces` table into a more explicit product object.
+这应该从当前的 `project_workspaces` 表演进为更明确的产品对象。
-### Motivation
+### 动机
-This separates:
+这将以下两者分离:
-- "what codebase/root does this project use?"
+- "该项目使用哪个代码库/根目录?"
-from:
+与:
-- "what temporary execution environment did this issue run in?"
+- "该 issue 在哪个临时执行环境中运行?"
-That keeps the model simple for solo users while still supporting advanced automation.
-It also lets cloud-hosted Paperclip deployments point at codebases and remotes without pretending the Paperclip host has direct filesystem access.
+这让模型对单人用户保持简单,同时仍然支持高级自动化。
+这也使云托管的 Paperclip 部署能够指向代码库和远程仓库,而无需假装 Paperclip 主机具有直接的文件系统访问权限。
-### Proposed fields
+### 建议字段
- `id`
- `companyId`
@@ -242,31 +242,31 @@ It also lets cloud-hosted Paperclip deployments point at codebases and remotes w
- `createdAt`
- `updatedAt`
-### Notes
+### 注意事项
-- `sourceType=non_git_path` is important so non-git projects are first-class.
-- `setupCommand` and `cleanupCommand` should be allowed here for workspace-root bootstrap, even when isolated execution is not used.
-- For a monorepo, multiple project workspaces may point at different roots or packages under one repo.
-- `sourceType=remote_managed` is important for cloud deployments where the durable codebase is defined by provider/repo metadata rather than a local checkout path.
+- `sourceType=non_git_path` 很重要,使非 git 项目成为一等公民。
+- 即使不使用隔离执行,这里也应该允许 `setupCommand` 和 `cleanupCommand` 用于工作区根目录引导。
+- 对于单体仓库,多个项目工作区可以指向同一仓库下的不同根目录或包。
+- `sourceType=remote_managed` 对于云部署很重要,其中持久代码库由提供商/仓库元数据定义,而非本地检出路径。
-## 3. Project Execution Workspace Policy
+## 3. 项目执行工作区策略
-Project-level defaults for how issues execute.
+issue 执行方式的项目级默认配置。
-This is the main operator-facing configuration surface.
+这是面向运营者的主要配置界面。
-### Motivation
+### 动机
-This lets Paperclip support:
+这让 Paperclip 支持:
-- direct editing in a shared workspace
-- isolated workspaces for issue parallelism
-- long-lived integration branch workflows
-- remote cloud-agent execution that returns a branch or PR
+- 在共享工作区中直接编辑
+- 用于 issue 并行的隔离工作区
+- 长期存活的集成分支工作流
+- 返回分支或 PR 的远程云代理执行
-without forcing every issue or agent to expose low-level runtime configuration.
+无需强制每个 issue 或代理暴露低级运行时配置。
-### Proposed fields
+### 建议字段
- `enabled: boolean`
- `defaultMode`
@@ -314,23 +314,23 @@ without forcing every issue or agent to expose low-level runtime configuration.
- `keepWhilePreviewHealthy`
- `keepWhileOpenPrExists`
-## 4. Issue Workspace Binding
+## 4. Issue 工作区绑定
-Issue-level selection of execution behavior.
+issue 级别的执行行为选择。
-This should remain lightweight in the normal case and only surface richer controls when relevant.
+正常情况下应保持轻量,仅在相关时展示更丰富的控件。
-### Motivation
+### 动机
-Not every issue in a code project should create a new derived workspace.
+代码项目中的每个 issue 不必都创建新的派生工作区。
-Examples:
+示例:
-- a tiny fix can run in the shared workspace
-- three related issues may intentionally share one integration branch
-- a solo operator may be working directly on `master`
+- 小修复可以在共享工作区中运行
+- 三个相关 issue 可以故意共享一个集成分支
+- 单人运营者可能直接在 `master` 上工作
-### Proposed fields on `issues`
+### `issues` 上的建议字段
- `projectWorkspaceId: uuid | null`
- `executionWorkspacePreference`
@@ -341,37 +341,37 @@ Examples:
- `reuse_existing`
- `preferredExecutionWorkspaceId: uuid | null`
- `executionWorkspaceSettings`
- - keep advanced per-issue override fields here
+ - 在此保留高级的每个 issue 覆盖字段
-### Rules
+### 规则
-- if the project has no workspace automation, these fields may all be null
-- if the project has one primary workspace, issue creation should default to it silently
-- `reuse_existing` is advanced-only and should target active execution workspaces, not the whole workspace universe
-- existing issues without these fields should behave as `inherit` during migration
+- 如果项目没有工作区自动化,这些字段可以全部为 null
+- 如果项目有一个主工作区,issue 创建时应默认选择它而不提示用户
+- `reuse_existing` 仅供高级使用,应针对活跃的执行工作区,而非整个工作区集合
+- 迁移期间,没有这些字段的现有 issue 应表现为 `inherit`
-## 5. Execution Workspace
+## 5. 执行工作区
-A durable record for a shared or derived runtime workspace.
+共享或派生运行时工作区的持久记录。
-This is the missing object that makes cleanup, previews, PRs, and branch reuse tractable.
+这是使清理、预览、PR 和分支重用变得可行的缺失对象。
-### Motivation
+### 动机
-Without an explicit `execution workspace` record, Paperclip has nowhere stable to attach:
+没有明确的 `execution workspace` 记录,Paperclip 没有稳定的地方来绑定:
-- derived branch/worktree identity
-- active preview ownership
-- PR linkage
-- cleanup state
-- "reuse this existing integration branch" behavior
-- remote provider session identity
+- 派生分支/worktree 身份
+- 活跃预览的所有权
+- PR 关联
+- 清理状态
+- "重用此现有集成分支"的行为
+- 远程提供商会话身份
-### Proposed new object
+### 建议的新对象
`execution_workspaces`
-### Proposed fields
+### 建议字段
- `id`
- `companyId`
@@ -414,27 +414,27 @@ Without an explicit `execution workspace` record, Paperclip has nowhere stable t
- `createdAt`
- `updatedAt`
-### Notes
+### 注意事项
-- `sourceIssueId` is the issue that originally caused the workspace to be created, not necessarily the only issue linked to it later.
-- multiple issues may link to the same execution workspace in a long-lived branch workflow.
-- `cwd` may be null for remote execution workspaces; provider identity and work product links still make the object useful.
+- `sourceIssueId` 是最初导致工作区创建的 issue,不一定是后来唯一关联到它的 issue。
+- 在长期存活的分支工作流中,多个 issue 可能关联到同一个执行工作区。
+- 对于远程执行工作区,`cwd` 可以为 null;提供商身份和工作成果链接仍然使该对象有用。
-## 6. Issue-to-Execution Workspace Link
+## 6. Issue 到执行工作区的链接
-An issue may need to link to one or more execution workspaces over time.
+随着时间推移,一个 issue 可能需要关联到一个或多个执行工作区。
-Examples:
+示例:
-- an issue begins in a shared workspace and later moves to an isolated one
-- a failed attempt is archived and a new workspace is created
-- several issues intentionally share one operator branch workspace
+- 一个 issue 从共享工作区开始,后来移到隔离工作区
+- 一次失败的尝试被归档,新的工作区被创建
+- 多个 issue 故意共享一个运营者分支工作区
-### Proposed object
+### 建议对象
`issue_execution_workspaces`
-### Proposed fields
+### 建议字段
- `issueId`
- `executionWorkspaceId`
@@ -445,31 +445,31 @@ Examples:
- `createdAt`
- `updatedAt`
-### UI simplification
+### UI 简化
-Most issues should only show one current workspace in the main UI. Historical links belong in advanced/history views.
+大多数 issue 在主 UI 中应只显示一个当前工作区。历史链接属于高级/历史视图。
-## 7. Work Product
+## 7. 工作成果
-User-facing umbrella concept for outputs of work.
+工作输出的面向用户的统一概念。
-### Motivation
+### 动机
-Paperclip needs a single place to show:
+Paperclip 需要一个统一的地方来显示:
-- "here is the preview"
-- "here is the PR"
-- "here is the branch"
-- "here is the commit"
-- "here is the artifact/report/doc"
+- "这是预览"
+- "这是 PR"
+- "这是分支"
+- "这是提交"
+- "这是制品/报告/文档"
-without turning issues into a raw dump of adapter details.
+而不是将 issue 变成适配器详情的原始堆积。
-### Proposed new object
+### 建议的新对象
`issue_work_products`
-### Proposed fields
+### 建议字段
- `id`
- `companyId`
@@ -518,25 +518,25 @@ without turning issues into a raw dump of adapter details.
- `createdAt`
- `updatedAt`
-### Behavior
+### 行为
-- PRs are stored here as `type=pull_request`
-- previews are stored here as `type=preview_url` or `runtime_service`
-- Paperclip-owned processes should update health/status automatically
-- external providers should at least store link, provider, external id, and latest known state
-- cloud agents should be able to create work product records without Paperclip owning the execution host
+- PR 以 `type=pull_request` 存储在此
+- 预览以 `type=preview_url` 或 `runtime_service` 存储在此
+- Paperclip 拥有的进程应自动更新健康状态/状态
+- 外部提供商至少应存储链接、提供商、外部 id 和最新已知状态
+- 云代理应能够在 Paperclip 不拥有执行主机的情况下创建工作成果记录
-## Page and UI Model
+## 页面与 UI 模型
-## 1. Global Navigation
+## 1. 全局导航
-Do not add `Workspaces` as a top-level sidebar item in V1.
+在 V1 中不要将 `Workspaces` 添加为顶级侧边栏条目。
-### Motivation
+### 动机
-That would make the whole product feel infra-heavy, even for companies that do not use code automation.
+这会让整个产品感觉基础设施过重,即使对于不使用代码自动化的公司也是如此。
-### Global nav remains
+### 全局导航保持
- Dashboard
- Inbox
@@ -547,222 +547,222 @@ That would make the whole product feel infra-heavy, even for companies that do n
- Issues
- Approvals
-Workspaces and work product should be surfaced through project and issue detail views.
+工作区和工作成果应通过项目和 issue 详情视图展示。
-## 2. Project Detail
+## 2. 项目详情
-Add a project sub-navigation that keeps planning first and code second.
+添加一个以规划为先、代码为辅的项目子导航。
-### Tabs
+### 标签页
- `Overview`
- `Issues`
- `Code`
- `Activity`
-Optional future:
+未来可选:
- `Outputs`
-### `Overview` tab
+### `Overview` 标签页
-Planning-first summary:
+以规划为先的摘要:
-- project status
-- goals
-- lead
-- issue counts
-- top-level progress
-- latest major work product summaries
+- 项目状态
+- 目标
+- 负责人
+- issue 计数
+- 顶级进度
+- 最新的主要工作成果摘要
-### `Issues` tab
+### `Issues` 标签页
-- default to top-level issues only
-- show parent issue rollups:
- - child count
- - `x/y` done
- - active preview/PR badges
-- optional toggle: `Show subissues`
+- 默认仅显示顶级 issue
+- 显示父 issue 汇总:
+ - 子 issue 数量
+ - `x/y` 已完成
+ - 活跃预览/PR 标记
+- 可选切换:`显示子 issue`
-### `Code` tab
+### `Code` 标签页
-This is the main workspace configuration and visibility surface.
+这是主要的工作区配置和可见性界面。
-#### Section: `Project Workspaces`
+#### 区域:`Project Workspaces`
-List durable project workspaces for the project.
+列出项目的持久项目工作区。
-Card/list columns:
+卡片/列表列:
-- workspace name
-- source type
-- path or repo
-- default ref
-- primary/default badge
-- active execution workspaces count
-- active issue count
-- active preview count
-- hosting type / provider when remote-managed
+- 工作区名称
+- 来源类型
+- 路径或仓库
+- 默认 ref
+- 主要/默认标记
+- 活跃执行工作区数量
+- 活跃 issue 数量
+- 活跃预览数量
+- 远程管理时的托管类型/提供商
-Actions:
+操作:
-- `Add workspace`
-- `Edit`
-- `Set default`
-- `Archive`
+- `添加工作区`
+- `编辑`
+- `设为默认`
+- `归档`
-#### Section: `Execution Defaults`
+#### 区域:`Execution Defaults`
-Fields:
+字段:
-- `Enable workspace automation`
-- `Default issue execution mode`
+- `启用工作区自动化`
+- `默认 issue 执行模式`
- `Shared workspace`
- `Isolated workspace`
- `Operator branch`
- `Adapter default`
-- `Default codebase`
-- `Allow issue override`
+- `默认代码库`
+- `允许 issue 覆盖`
-#### Section: `Provisioning`
+#### 区域:`Provisioning`
-Fields:
+字段:
- `Setup command`
- `Cleanup command`
-- `Implementation`
+- `实现方式`
- `Shared workspace`
- `Git worktree`
- `Adapter-managed`
- `Base ref`
-- `Branch naming template`
-- `Derived workspace parent directory`
+- `分支命名模板`
+- `派生工作区父目录`
-Hide git-specific fields when the selected workspace is not git-backed.
-Hide local-path-specific fields when the selected workspace is remote-managed.
+当所选工作区不是 git 支持时,隐藏 git 专属字段。
+当所选工作区是远程管理时,隐藏本地路径专属字段。
-#### Section: `Pull Requests`
+#### 区域:`Pull Requests`
-Fields:
+字段:
-- `PR workflow`
+- `PR 工作流`
- `Disabled`
- `Manual`
- `Agent may open draft PR`
- `Approval required to open PR`
- `Approval required to mark ready`
-- `Default base branch`
-- `PR title template`
-- `PR body template`
+- `默认基础分支`
+- `PR 标题模板`
+- `PR 正文模板`
-#### Section: `Previews and Runtime`
+#### 区域:`Previews and Runtime`
-Fields:
+字段:
-- `Allow workspace runtime services`
-- `Default services profile`
-- `Harvest owned preview URLs`
-- `Track external preview URLs`
+- `允许工作区运行时服务`
+- `默认服务配置文件`
+- `收集所有预览 URL`
+- `追踪外部预览 URL`
-#### Section: `Cleanup`
+#### 区域:`Cleanup`
-Fields:
+字段:
-- `Cleanup mode`
+- `清理模式`
- `Manual`
- `When issue is terminal`
- `When PR closes`
- `After retention window`
-- `Retention window`
-- `Keep while preview is active`
-- `Keep while PR is open`
+- `保留时间窗口`
+- `预览活跃时保持`
+- `PR 开放时保持`
-## 3. Add Project Workspace Flow
+## 3. 添加项目工作区流程
-Entry point: `Project > Code > Add workspace`
+入口点:`Project > Code > 添加工作区`
-### Form fields
+### 表单字段
-- `Name`
-- `Source type`
+- `名称`
+- `来源类型`
- `Local folder`
- `Git repo`
- `Non-git folder`
- `Remote managed`
-- `Local path`
-- `Repository URL`
-- `Remote provider`
-- `Remote workspace reference`
+- `本地路径`
+- `仓库 URL`
+- `远程提供商`
+- `远程工作区引用`
- `Default ref`
-- `Set as default workspace`
+- `设为默认工作区`
- `Setup command`
- `Cleanup command`
-### Behavior
+### 行为
-- if source type is non-git, hide branch/PR-specific setup
-- if source type is git, show ref and optional advanced branch fields
-- if source type is remote-managed, show provider/reference fields and hide local-path-only configuration
-- for simple solo users, this can be one path field and one save button
+- 如果来源类型是非 git,隐藏分支/PR 专属设置
+- 如果来源类型是 git,显示 ref 和可选的高级分支字段
+- 如果来源类型是远程管理,显示提供商/引用字段并隐藏本地路径专属配置
+- 对于简单的单人用户,这可以是一个路径字段和一个保存按钮
-## 4. Issue Create Flow
+## 4. Issue 创建流程
-Issue creation should stay simple by default.
+Issue 创建在默认情况下应保持简单。
-### Default behavior
+### 默认行为
-If the selected project:
+如果所选项目:
-- has no workspace automation: show no workspace UI
-- has one default project workspace and default execution mode: inherit silently
+- 没有工作区自动化:不显示工作区 UI
+- 有一个默认项目工作区和默认执行模式:静默继承
-### Show a `Workspace` section only when relevant
+### 仅在相关时显示 `Workspace` 区域
-#### Basic fields
+#### 基本字段
-- `Codebase`
- - default selected project workspace
-- `Execution mode`
+- `代码库`
+ - 默认选择项目工作区
+- `执行模式`
- `Project default`
- `Shared workspace`
- `Isolated workspace`
- `Operator branch`
-#### Advanced-only field
+#### 仅高级字段
-- `Reuse existing execution workspace`
+- `重用现有执行工作区`
-This dropdown should show only active execution workspaces for the selected project workspace, with labels like:
+此下拉列表应仅显示所选项目工作区的活跃执行工作区,标签如:
- `dotta/integration-branch`
- `PAP-447-add-worktree-support`
- `shared primary workspace`
-### Important rule
+### 重要规则
-Do not show a picker containing every possible workspace object by default.
+默认情况下不要显示包含所有可能工作区对象的选择器。
-The normal flow should feel like:
+正常流程应该感觉是:
-- choose project
-- optionally choose codebase
-- optionally choose execution mode
+- 选择项目
+- 可选择代码库
+- 可选择执行模式
-not:
+而不是:
-- choose from a long mixed list of roots, derived worktrees, previews, and branch names
+- 从一个包含根目录、派生 worktree、预览和分支名称的混合长列表中选择
-### Migration rule
+### 迁移规则
-For existing users, issue creation should continue to look the same until a project explicitly enables richer workspace behavior.
+对于现有用户,issue 创建应继续保持相同的外观,直到项目明确启用更丰富的工作区行为。
-## 5. Issue Detail
+## 5. Issue 详情
-Issue detail should expose workspace and work product clearly, but without becoming a code host UI.
+Issue 详情应清晰展示工作区和工作成果,但不应变成代码托管 UI。
-### Header chips
+### 标题栏标记
-Show compact summary chips near the title/status area:
+在标题/状态区域附近显示紧凑的摘要标记:
- `Codebase: Web App`
- `Workspace: Shared`
@@ -770,16 +770,16 @@ Show compact summary chips near the title/status area:
- `PR: Open`
- `Preview: Healthy`
-### Tabs
+### 标签页
- `Comments`
- `Subissues`
- `Work Product`
- `Activity`
-### `Work Product` tab
+### `Work Product` 标签页
-Sections:
+区域:
- `Current workspace`
- `Previews`
@@ -787,129 +787,129 @@ Sections:
- `Branches and commits`
- `Artifacts and documents`
-#### Current workspace panel
+#### 当前工作区面板
-Fields:
+字段:
-- workspace name
-- mode
-- branch
-- base ref
-- last used
-- linked issues count
-- cleanup status
+- 工作区名称
+- 模式
+- 分支
+- 基础 ref
+- 最后使用时间
+- 关联 issue 数量
+- 清理状态
-Actions:
+操作:
-- `Open workspace details`
-- `Mark in review`
-- `Request cleanup`
+- `打开工作区详情`
+- `标记为审查中`
+- `请求清理`
-#### Pull request cards
+#### PR 卡片
-Fields:
+字段:
-- title
-- provider
-- status
-- review state
-- linked branch
-- open/ready/merged timestamps
+- 标题
+- 提供商
+- 状态
+- 审查状态
+- 关联分支
+- 开启/就绪/合并时间戳
-Actions:
+操作:
-- `Open PR`
-- `Refresh status`
-- `Request board review`
+- `打开 PR`
+- `刷新状态`
+- `请求看板审查`
-#### Preview cards
+#### 预览卡片
-Fields:
+字段:
-- title
+- 标题
- URL
-- provider
-- health
-- ownership
-- updated at
+- 提供商
+- 健康状态
+- 所有权
+- 更新时间
-Actions:
+操作:
-- `Open preview`
-- `Refresh`
-- `Archive`
+- `打开预览`
+- `刷新`
+- `归档`
-## 6. Execution Workspace Detail
+## 6. 执行工作区详情
-This can be reached from a project code tab or an issue work product tab.
+可以从项目代码标签页或 issue 工作成果标签页进入。
-It does not need to be in the main sidebar.
+不需要在主侧边栏中。
-### Sections
+### 区域
-- identity
-- source issue
-- linked issues
-- branch/ref
-- provider/session identity
-- active runtime services
-- previews
-- PRs
-- cleanup state
-- event/activity history
+- 身份信息
+- 来源 issue
+- 关联 issue
+- 分支/ref
+- 提供商/会话身份
+- 活跃运行时服务
+- 预览
+- PR
+- 清理状态
+- 事件/活动历史
-### Motivation
+### 动机
-This is where advanced users go when they need to inspect the mechanics. Most users should not need it in normal flow.
+这是高级用户需要检查机制时的去处。大多数用户在正常流程中不需要它。
-## 7. Inbox Behavior
+## 7. 收件箱行为
-Inbox should surface actionable work product events, not every implementation detail.
+收件箱应展示可操作的工作成果事件,而非每个实现细节。
-### Show inbox items for
+### 显示以下收件箱条目
-- issue assigned or updated
-- PR needs board review
-- PR opened or marked ready
-- preview unhealthy
-- workspace cleanup failed
-- runtime service failed
-- remote cloud-agent run returned PR or preview that needs review
+- issue 被分配或更新
+- PR 需要看板审查
+- PR 已开启或标记为就绪
+- 预览不健康
+- 工作区清理失败
+- 运行时服务失败
+- 远程云代理运行返回了需要审查的 PR 或预览
-### Do not show by default
+### 默认不显示
-- every workspace heartbeat
-- every branch update
-- every derived workspace creation
+- 每次工作区心跳
+- 每次分支更新
+- 每次派生工作区创建
-### Display style
+### 显示风格
-If the inbox item is about a preview or PR, show issue context with it:
+如果收件箱条目是关于预览或 PR 的,一并显示 issue 上下文:
-- issue identifier and title
-- parent issue if this is a subissue
-- workspace name if relevant
+- issue 标识符和标题
+- 如果是子 issue 则显示父 issue
+- 相关时显示工作区名称
-## 8. Issues List and Kanban
+## 8. Issue 列表和看板
-Keep list and board planning-first.
+保持列表和看板以规划为先。
-### Default behavior
+### 默认行为
-- show top-level issues by default
-- show parent rollups for subissues
-- do not flatten every child execution detail into the main board
+- 默认显示顶级 issue
+- 显示子 issue 的父 issue 汇总
+- 不要将每个子执行细节展平到主看板
-### Row/card adornments
+### 行/卡片装饰
-For issues with linked work product, show compact badges:
+对于有关联工作成果的 issue,显示紧凑标记:
- `1 PR`
- `2 previews`
- `shared workspace`
- `isolated workspace`
-### Optional advanced filters
+### 可选高级过滤器
- `Has PR`
- `Has preview`
diff --git a/doc/plans/workspace-technical-implementation.md b/doc/plans/workspace-technical-implementation.md
index c60bc019ef..5e75dd6baf 100644
--- a/doc/plans/workspace-technical-implementation.md
+++ b/doc/plans/workspace-technical-implementation.md
@@ -1,149 +1,149 @@
-# Workspace Technical Implementation Spec
+# 工作区技术实现规范
-## Role of This Document
+## 本文档的作用
-This document translates [workspace-product-model-and-work-product.md](/Users/dotta/paperclip-subissues/doc/plans/workspace-product-model-and-work-product.md) into an implementation-ready engineering plan.
+本文档将 [workspace-product-model-and-work-product.md](/Users/dotta/paperclip-subissues/doc/plans/workspace-product-model-and-work-product.md) 转化为可直接执行的工程实施计划。
-It is intentionally concrete:
+本文档有意保持具体性,涵盖以下内容:
-- schema and migration shape
-- shared contract updates
-- route and service changes
-- UI changes
-- rollout and compatibility rules
+- schema 与迁移结构
+- 共享契约更新
+- 路由与服务变更
+- UI 变更
+- 发布与兼容性规则
-This is the implementation target for the first workspace-aware delivery slice.
+这是第一个具备 workspace 感知能力的交付切片的实施目标。
-## Locked Decisions
+## 已锁定决策
-These decisions are treated as settled for this implementation:
+以下决策在本次实施中视为已确定:
-1. Add a new durable `execution_workspaces` table now.
-2. Each issue has at most one current execution workspace at a time.
-3. `issues` get explicit `project_workspace_id` and `execution_workspace_id`.
-4. Workspace reuse is in scope for V1.
-5. The feature is gated in the UI by `/instance/settings > Experimental > Workspaces`.
-6. The gate is UI-only. Backend model changes and migrations always ship.
-7. Existing users upgrade into compatibility-preserving defaults.
-8. `project_workspaces` evolves in place rather than being replaced.
-9. Work product is issue-first, with optional links to execution workspaces and runtime services.
-10. GitHub is the only PR provider in the first slice.
-11. Both `adapter_managed` and `cloud_sandbox` execution modes are in scope.
-12. Workspace controls ship first inside existing project properties, not in a new global navigation area.
-13. Subissues are out of scope for this implementation slice.
+1. 现在新增一张持久化的 `execution_workspaces` 表。
+2. 每个 issue 同一时刻最多关联一个当前执行 workspace。
+3. `issues` 表新增显式字段 `project_workspace_id` 和 `execution_workspace_id`。
+4. Workspace 复用在 V1 范围之内。
+5. 该功能通过 UI 路径 `/instance/settings > Experimental > Workspaces` 进行开关控制。
+6. 开关仅限 UI 层。后端模型变更和迁移始终随版本发布。
+7. 现有用户升级后将自动获得保持兼容性的默认值。
+8. `project_workspaces` 原地演进,不做替换。
+9. 工作产物以 issue 为核心,可选地与执行 workspace 和运行时服务关联。
+10. 第一个切片中 GitHub 是唯一的 PR 提供方。
+11. `adapter_managed` 和 `cloud_sandbox` 两种执行模式均在范围之内。
+12. Workspace 控件优先集成到现有项目属性中发布,不在新的全局导航区域中发布。
+13. 子 issue 不在本实施切片范围之内。
-## Non-Goals
+## 非目标
-- Building a full code review system
-- Solving subissue UX in this slice
-- Implementing reusable shared workspace definitions across projects in this slice
-- Reworking all current runtime service behavior before introducing execution workspaces
+- 构建完整的代码审查系统
+- 在本切片中解决子 issue 的用户体验
+- 在本切片中实现跨项目的可复用共享 workspace 定义
+- 在引入执行 workspace 之前重构所有现有运行时服务行为
-## Existing Baseline
+## 现有基线
-The repo already has:
+该代码库已包含:
- `project_workspaces`
- `projects.execution_workspace_policy`
- `issues.execution_workspace_settings`
-- runtime service persistence in `workspace_runtime_services`
-- local git-worktree realization in `workspace-runtime.ts`
+- `workspace_runtime_services` 中的运行时服务持久化
+- `workspace-runtime.ts` 中的本地 git-worktree 实现
-This implementation should build on that baseline rather than fork it.
+本次实施应在现有基线之上构建,而非另起炉灶。
-## Terminology
+## 术语
-- `Project workspace`: durable configured codebase/root for a project
-- `Execution workspace`: actual runtime workspace used for one or more issues
-- `Work product`: user-facing output such as PR, preview, branch, commit, artifact, document
-- `Runtime service`: process or service owned or tracked for a workspace
-- `Compatibility mode`: existing behavior preserved for upgraded installs with no explicit workspace opt-in
+- `Project workspace`:为项目持久配置的代码库/根目录
+- `Execution workspace`:供一个或多个 issue 使用的实际运行时 workspace
+- `Work product`:面向用户的输出物,例如 PR、预览、分支、提交、构件、文档
+- `Runtime service`:workspace 所拥有或追踪的进程或服务
+- `Compatibility mode`:为升级后尚未显式启用 workspace 的安装实例保留的现有行为
-## Architecture Summary
+## 架构概述
-The first slice should introduce three explicit layers:
+第一个切片应引入三个明确的层次:
1. `Project workspace`
- - existing durable project-scoped codebase record
- - extended to support local, git, non-git, and remote-managed shapes
+ - 现有的、项目范围内的持久化代码库记录
+ - 扩展以支持本地、git、非 git 及远程托管等形态
2. `Execution workspace`
- - new durable runtime record
- - represents shared, isolated, operator-branch, or remote-managed execution context
+ - 新的持久化运行时记录
+ - 代表共享、隔离、operator 分支或远程托管的执行上下文
3. `Issue work product`
- - new durable output record
- - stores PRs, previews, branches, commits, artifacts, and documents
+ - 新的持久化输出记录
+ - 存储 PR、预览、分支、提交、构件和文档
-The issue remains the planning and ownership unit.
-The execution workspace remains the runtime unit.
-The work product remains the deliverable/output unit.
+issue 仍然是规划和所有权单元。
+执行 workspace 仍然是运行时单元。
+工作产物仍然是可交付/输出单元。
-## Configuration and Deployment Topology
+## 配置与部署拓扑
-## Important correction
+## 重要更正
-This repo already uses `PAPERCLIP_DEPLOYMENT_MODE` for auth/deployment behavior (`local_trusted | authenticated`).
+该代码库已使用 `PAPERCLIP_DEPLOYMENT_MODE` 来处理认证/部署行为(`local_trusted | authenticated`)。
-Do not overload that variable for workspace execution topology.
+请勿将该变量复用于 workspace 执行拓扑。
-## New env var
+## 新增环境变量
-Add a separate execution-host hint:
+新增一个独立的执行主机提示变量:
- `PAPERCLIP_EXECUTION_TOPOLOGY=local|cloud|hybrid`
-Default:
+默认值:
-- if unset, treat as `local`
+- 若未设置,视为 `local`
-Purpose:
+用途:
-- influences defaults and validation for workspace configuration
-- does not change current auth/deployment semantics
-- does not break existing installs
+- 影响 workspace 配置的默认值和校验逻辑
+- 不改变当前的认证/部署语义
+- 不破坏现有安装实例
-### Semantics
+### 语义说明
- `local`
- - Paperclip may create host-local worktrees, processes, and paths
+ - Paperclip 可在宿主机上创建 worktree、进程和路径
- `cloud`
- - Paperclip should assume no durable host-local execution workspace management
- - adapter-managed and cloud-sandbox flows should be treated as first-class
+ - Paperclip 应假设没有持久化的宿主机本地执行 workspace 管理
+ - adapter 托管流程和 cloud sandbox 流程应作为一等公民对待
- `hybrid`
- - both local and remote execution strategies may exist
+ - 本地和远程执行策略可以并存
-This is a guardrail and defaulting aid, not a hard policy engine in the first slice.
+这是第一个切片中的护栏和默认值辅助机制,而非严格的策略引擎。
-## Instance Settings
+## 实例设置
-Add a new `Experimental` section under `/instance/settings`.
+在 `/instance/settings` 下新增 `Experimental`(实验性功能)分区。
-### New setting
+### 新增设置项
- `experimental.workspaces: boolean`
-Rules:
+规则:
-- default `false`
-- UI-only gate
-- stored in instance config or instance settings API response
-- backend routes and migrations remain available even when false
+- 默认值为 `false`
+- 仅为 UI 层开关
+- 存储在实例配置或实例设置 API 响应中
+- 即使该值为 false,后端路由和迁移仍保持可用
-### UI behavior when off
+### 关闭时的 UI 行为
-- hide workspace-specific issue controls
-- hide workspace-specific project configuration
-- hide issue `Work Product` tab if it would otherwise be empty
-- do not remove or invalidate any stored workspace data
+- 隐藏 workspace 专属的 issue 控件
+- 隐藏 workspace 专属的项目配置
+- 若 issue 的 `Work Product` 标签页内容为空,则将其隐藏
+- 不删除或使任何已存储的 workspace 数据失效
-## Data Model
+## 数据模型
-## 1. Extend `project_workspaces`
+## 1. 扩展 `project_workspaces`
-Current table exists and should evolve in place.
+该表已存在,应原地演进。
-### New columns
+### 新增字段
- `source_type text not null default 'local_path'`
- `local_path | git_repo | non_git_path | remote_managed`
@@ -156,26 +156,26 @@ Current table exists and should evolve in place.
- examples: `github`, `openai`, `anthropic`, `custom`
- `remote_workspace_ref text null`
- `shared_workspace_key text null`
- - reserved for future cross-project shared workspace definitions
+ - 为未来跨项目共享 workspace 定义预留
-### Backfill rules
+### 回填规则
-- if existing row has `repo_url`, backfill `source_type='git_repo'`
-- else if existing row has `cwd`, backfill `source_type='local_path'`
-- else backfill `source_type='remote_managed'`
-- copy existing `repo_ref` into `default_ref`
+- 若已有行包含 `repo_url`,则回填 `source_type='git_repo'`
+- 否则若已有行包含 `cwd`,则回填 `source_type='local_path'`
+- 否则回填 `source_type='remote_managed'`
+- 将现有 `repo_ref` 复制到 `default_ref`
-### Indexes
+### 索引
-- retain current indexes
-- add `(project_id, source_type)`
-- add `(company_id, shared_workspace_key)` non-unique for future support
+- 保留现有索引
+- 新增 `(project_id, source_type)`
+- 新增非唯一索引 `(company_id, shared_workspace_key)`,供未来使用
-## 2. Add `execution_workspaces`
+## 2. 新增 `execution_workspaces`
-Create a new durable table.
+创建一张新的持久化表。
-### Columns
+### 字段
- `id uuid pk`
- `company_id uuid not null`
@@ -206,7 +206,7 @@ Create a new durable table.
- `created_at timestamptz not null default now()`
- `updated_at timestamptz not null default now()`
-### Foreign keys
+### 外键
- `company_id -> companies.id`
- `project_id -> projects.id`
@@ -214,46 +214,46 @@ Create a new durable table.
- `source_issue_id -> issues.id on delete set null`
- `derived_from_execution_workspace_id -> execution_workspaces.id on delete set null`
-### Indexes
+### 索引
- `(company_id, project_id, status)`
- `(company_id, project_workspace_id, status)`
- `(company_id, source_issue_id)`
- `(company_id, last_used_at desc)`
-- `(company_id, branch_name)` non-unique
+- `(company_id, branch_name)` 非唯一索引
-## 3. Extend `issues`
+## 3. 扩展 `issues`
-Add explicit workspace linkage.
+新增显式的 workspace 关联字段。
-### New columns
+### 新增字段
- `project_workspace_id uuid null`
- `execution_workspace_id uuid null`
- `execution_workspace_preference text null`
- `inherit | shared_workspace | isolated_workspace | operator_branch | reuse_existing`
-### Foreign keys
+### 外键
- `project_workspace_id -> project_workspaces.id on delete set null`
- `execution_workspace_id -> execution_workspaces.id on delete set null`
-### Backfill rules
+### 回填规则
-- all existing issues get null values
-- null should be interpreted as compatibility/inherit behavior
+- 所有现有 issue 的新增字段赋值为 null
+- null 应被解读为兼容性/继承行为
-### Invariants
+### 不变式约束
-- if `project_workspace_id` is set, it must belong to the issue's project and company
-- if `execution_workspace_id` is set, it must belong to the issue's company
-- if `execution_workspace_id` is set, the referenced workspace's `project_id` must match the issue's `project_id`
+- 若设置了 `project_workspace_id`,则其所属项目和公司必须与该 issue 一致
+- 若设置了 `execution_workspace_id`,则其所属公司必须与该 issue 一致
+- 若设置了 `execution_workspace_id`,则所引用 workspace 的 `project_id` 必须与该 issue 的 `project_id` 一致
-## 4. Add `issue_work_products`
+## 4. 新增 `issue_work_products`
-Create a new durable table for outputs.
+创建一张新的持久化输出记录表。
-### Columns
+### 字段
- `id uuid pk`
- `company_id uuid not null`
@@ -281,7 +281,7 @@ Create a new durable table for outputs.
- `created_at timestamptz not null default now()`
- `updated_at timestamptz not null default now()`
-### Foreign keys
+### 外键
- `company_id -> companies.id`
- `project_id -> projects.id on delete set null`
@@ -290,37 +290,37 @@ Create a new durable table for outputs.
- `runtime_service_id -> workspace_runtime_services.id on delete set null`
- `created_by_run_id -> heartbeat_runs.id on delete set null`
-### Indexes
+### 索引
- `(company_id, issue_id, type)`
- `(company_id, execution_workspace_id, type)`
- `(company_id, provider, external_id)`
- `(company_id, updated_at desc)`
-## 5. Extend `workspace_runtime_services`
+## 5. 扩展 `workspace_runtime_services`
-This table already exists and should remain the system of record for owned/tracked services.
+该表已存在,应继续作为已拥有/已追踪服务的权威记录。
-### New column
+### 新增字段
- `execution_workspace_id uuid null`
-### Foreign key
+### 外键
- `execution_workspace_id -> execution_workspaces.id on delete set null`
-### Behavior
+### 行为规范
-- runtime services remain workspace-first
-- issue UIs should surface them through linked execution workspaces and work products
+- 运行时服务仍以 workspace 为优先
+- issue UI 应通过关联的执行 workspace 和工作产物来展示运行时服务
-## Shared Contracts
+## 共享契约
## 1. `packages/shared`
-### Update project workspace types and validators
+### 更新项目 workspace 类型与校验器
-Add fields:
+新增字段:
- `sourceType`
- `defaultRef`
@@ -331,36 +331,36 @@ Add fields:
- `remoteWorkspaceRef`
- `sharedWorkspaceKey`
-### Add execution workspace types and validators
+### 新增执行 workspace 类型与校验器
-New shared types:
+新增共享类型:
- `ExecutionWorkspace`
- `ExecutionWorkspaceMode`
- `ExecutionWorkspaceStatus`
- `ExecutionWorkspaceProviderType`
-### Add work product types and validators
+### 新增工作产物类型与校验器
-New shared types:
+新增共享类型:
- `IssueWorkProduct`
- `IssueWorkProductType`
- `IssueWorkProductStatus`
- `IssueWorkProductReviewState`
-### Update issue types and validators
+### 更新 issue 类型与校验器
-Add:
+新增:
- `projectWorkspaceId`
- `executionWorkspaceId`
- `executionWorkspacePreference`
- `workProducts?: IssueWorkProduct[]`
-### Extend project execution policy contract
+### 扩展项目执行策略契约
-Replace the current narrow policy with a more explicit shape:
+将现有的精简策略替换为更明确的结构:
- `enabled`
- `defaultMode`
@@ -373,118 +373,118 @@ Replace the current narrow policy with a more explicit shape:
- `runtimePolicy`
- `cleanupPolicy`
-Do not try to encode every possible provider-specific field in V1. Keep provider-specific extensibility in nested JSON where needed.
+V1 中不应尝试编码每个可能的 provider 专属字段。在需要时,将 provider 专属的扩展性保留在嵌套 JSON 中。
-## Service Layer Changes
+## 服务层变更
-## 1. Project service
+## 1. 项目服务
-Update project workspace CRUD to handle the extended schema.
+更新项目 workspace 的 CRUD 逻辑以处理扩展后的 schema。
-### Required rules
+### 必要规则
-- when setting a primary workspace, clear `is_primary` on siblings
-- `source_type=remote_managed` may have null `cwd`
-- local/git-backed workspaces should still require one of `cwd` or `repo_url`
-- preserve current behavior for existing callers that only send `cwd/repoUrl/repoRef`
+- 设置主 workspace 时,清除同级记录的 `is_primary` 标记
+- `source_type=remote_managed` 的记录 `cwd` 可为 null
+- 本地/git 支持的 workspace 仍应要求 `cwd` 或 `repo_url` 其中之一
+- 保留仅发送 `cwd/repoUrl/repoRef` 的现有调用方的当前行为
-## 2. Issue service
+## 2. Issue 服务
-Update create/update flows to handle explicit workspace binding.
+更新 issue 的创建/更新流程,以处理显式的 workspace 绑定。
-### Create behavior
+### 创建行为
-Resolve defaults in this order:
+按以下顺序解析默认值:
1. explicit `projectWorkspaceId` from request
2. `project.executionWorkspacePolicy.defaultProjectWorkspaceId`
3. project's primary workspace
4. null
-Resolve `executionWorkspacePreference`:
+解析 `executionWorkspacePreference`:
-1. explicit request field
-2. project policy default
-3. compatibility fallback to `inherit`
+1. 请求中的显式字段
+2. 项目策略默认值
+3. 兼容性回退值 `inherit`
-Do not create an execution workspace at issue creation time unless:
+不应在 issue 创建时即创建执行 workspace,除非:
-- `reuse_existing` is explicitly chosen and `executionWorkspaceId` is provided
+- 显式选择了 `reuse_existing` 且提供了 `executionWorkspaceId`
-Otherwise, workspace realization happens when execution starts.
+否则,workspace 的实例化应在执行启动时进行。
-### Update behavior
+### 更新行为
-- allow changing `projectWorkspaceId` only if the workspace belongs to the same project
-- allow setting `executionWorkspaceId` only if it belongs to the same company and project
-- do not automatically destroy or relink historical work products when workspace linkage changes
+- 仅当 workspace 属于同一项目时,允许修改 `projectWorkspaceId`
+- 仅当 `executionWorkspaceId` 属于同一公司和项目时,允许设置该字段
+- 当 workspace 关联变更时,不自动销毁或重新关联历史工作产物
-## 3. Workspace realization service
+## 3. Workspace 实例化服务
-Refactor `workspace-runtime.ts` so realization produces or reuses an `execution_workspaces` row.
+重构 `workspace-runtime.ts`,使实例化过程能够创建或复用一条 `execution_workspaces` 记录。
-### New flow
+### 新流程
-Input:
+输入:
- issue
-- project workspace
-- project execution policy
-- execution topology hint
-- adapter/runtime configuration
+- 项目 workspace
+- 项目执行策略
+- 执行拓扑提示
+- adapter/运行时配置
-Output:
+输出:
-- realized execution workspace record
-- runtime cwd/provider metadata
+- 已实例化的执行 workspace 记录
+- 运行时 cwd/provider 元数据
-### Required modes
+### 必须支持的模式
- `shared_workspace`
- - reuse a stable execution workspace representing the project primary/shared workspace
+ - 复用代表项目主/共享 workspace 的稳定执行 workspace
- `isolated_workspace`
- - create or reuse a derived isolated execution workspace
+ - 创建或复用派生的隔离执行 workspace
- `operator_branch`
- - create or reuse a long-lived branch workspace
+ - 创建或复用长期存活的分支 workspace
- `adapter_managed`
- - create an execution workspace with provider references and optional null `cwd`
+ - 创建带有 provider 引用的执行 workspace,`cwd` 可选为 null
- `cloud_sandbox`
- - same as adapter-managed, but explicit remote sandbox semantics
+ - 与 adapter-managed 相同,但明确采用远程沙箱语义
-### Reuse rules
+### 复用规则
-When `reuse_existing` is requested:
+当请求 `reuse_existing` 时:
-- only list active or recently used execution workspaces
-- only for the same project
-- only for the same project workspace if one is specified
-- exclude archived and cleanup-failed workspaces
+- 仅列出活跃或近期使用过的执行 workspace
+- 仅限同一项目
+- 若指定了项目 workspace,则仅限同一项目 workspace
+- 排除已归档及清理失败的 workspace
-### Shared workspace realization
+### 共享 workspace 实例化
-For compatibility mode and shared-workspace projects:
+针对兼容性模式和共享 workspace 项目:
-- create a stable execution workspace per project workspace when first needed
-- reuse it for subsequent runs
+- 在首次需要时,为每个项目 workspace 创建一个稳定的执行 workspace
+- 后续运行时复用该 workspace
-This avoids a special-case branch in later work product linkage.
+这可避免在后续工作产物关联中引入特殊分支逻辑。
-## 4. Runtime service integration
+## 4. 运行时服务集成
-When runtime services are started or reused:
+当运行时服务启动或被复用时:
-- populate `execution_workspace_id`
-- continue populating `project_workspace_id`, `project_id`, and `issue_id`
+- 填充 `execution_workspace_id`
+- 继续填充 `project_workspace_id`、`project_id` 和 `issue_id`
-When a runtime service yields a URL:
+当运行时服务产出 URL 时:
-- optionally create or update a linked `issue_work_products` row of type `runtime_service` or `preview_url`
+- 可选地创建或更新一条类型为 `runtime_service` 或 `preview_url` 的关联 `issue_work_products` 记录
-## 5. PR and preview reporting
+## 5. PR 与预览报告
-Add a service for creating/updating `issue_work_products`.
+新增用于创建/更新 `issue_work_products` 的服务。
-### Supported V1 product types
+### V1 支持的工作产物类型
- `pull_request`
- `preview_url`
@@ -494,11 +494,11 @@ Add a service for creating/updating `issue_work_products`.
- `artifact`
- `document`
-### GitHub PR reporting
+### GitHub PR 报告
-For V1, GitHub is the only provider with richer semantics.
+V1 中,GitHub 是唯一具有更丰富语义的 provider。
-Supported statuses:
+支持的状态:
- `draft`
- `ready_for_review`
@@ -507,20 +507,20 @@ Supported statuses:
- `merged`
- `closed`
-Represent these in `status` and `review_state` rather than inventing a separate PR table in V1.
+在 V1 中,通过 `status` 和 `review_state` 字段表示上述状态,而不另建独立的 PR 表。
-## Routes and API
+## 路由与 API
-## 1. Project workspace routes
+## 1. 项目 workspace 路由
-Extend existing routes:
+扩展现有路由:
- `GET /projects/:id/workspaces`
- `POST /projects/:id/workspaces`
- `PATCH /projects/:id/workspaces/:workspaceId`
- `DELETE /projects/:id/workspaces/:workspaceId`
-### New accepted/returned fields
+### 新增接受/返回字段
- `sourceType`
- `defaultRef`
@@ -530,12 +530,12 @@ Extend existing routes:
- `remoteProvider`
- `remoteWorkspaceRef`
-## 2. Execution workspace routes
+## 2. 执行 workspace 路由
-Add:
+新增:
- `GET /companies/:companyId/execution-workspaces`
- - filters:
+ - 过滤条件:
- `projectId`
- `projectWorkspaceId`
- `status`
@@ -543,34 +543,34 @@ Add:
- `reuseEligible=true`
- `GET /execution-workspaces/:id`
- `PATCH /execution-workspaces/:id`
- - update status/metadata/cleanup fields only in V1
+ - V1 中仅更新 status/metadata/cleanup 相关字段
-Do not add top-level navigation for these routes yet.
+暂不为这些路由添加顶层导航入口。
-## 3. Work product routes
+## 3. 工作产物路由
-Add:
+新增:
- `GET /issues/:id/work-products`
- `POST /issues/:id/work-products`
- `PATCH /work-products/:id`
- `DELETE /work-products/:id`
-### V1 mutation permissions
+### V1 变更权限
-- board can create/update/delete all
-- agents can create/update for issues they are assigned or currently executing
-- deletion should generally archive rather than hard-delete once linked to historical output
+- board 可对所有记录进行创建/更新/删除
+- agent 可对其被分配或正在执行的 issue 进行创建/更新
+- 一旦与历史输出关联,删除操作通常应归档而非硬删除
-## 4. Issue routes
+## 4. Issue 路由
-Extend existing create/update payloads to accept:
+扩展现有的创建/更新请求体,新增接受字段:
- `projectWorkspaceId`
- `executionWorkspacePreference`
- `executionWorkspaceId`
-Extend `GET /issues/:id` to return:
+扩展 `GET /issues/:id` 的返回字段:
- `projectWorkspaceId`
- `executionWorkspaceId`
@@ -578,155 +578,154 @@ Extend `GET /issues/:id` to return:
- `currentExecutionWorkspace`
- `workProducts[]`
-## 5. Instance settings routes
+## 5. 实例设置路由
-Add support for:
+新增对以下操作的支持:
-- reading/writing `experimental.workspaces`
+- 读取/写入 `experimental.workspaces`
-This is a UI gate only.
+此为纯 UI 开关。
-If there is no generic instance settings storage yet, the first slice can store this in the existing config/instance settings mechanism used by `/instance/settings`.
+若尚无通用的实例设置存储机制,第一个切片可将其存储在 `/instance/settings` 已使用的现有配置/实例设置机制中。
-## UI Changes
+## UI 变更
## 1. `/instance/settings`
-Add section:
+新增分区:
-- `Experimental`
- - `Enable Workspaces`
+- `Experimental`(实验性功能)
+ - `Enable Workspaces`(启用 Workspaces)
-When off:
+关闭时:
-- hide new workspace-specific affordances
-- do not alter existing project or issue behavior
+- 隐藏新的 workspace 专属交互控件
+- 不改变现有的项目或 issue 行为
-## 2. Project properties
+## 2. 项目属性
-Do not create a separate `Code` tab yet.
-Ship inside existing project properties first.
+暂不新建独立的 `Code` 标签页,优先在现有项目属性中发布。
-### Add or re-enable sections
+### 新增或重新启用的分区
-- `Project Workspaces`
-- `Execution Defaults`
-- `Provisioning`
-- `Pull Requests`
-- `Previews and Runtime`
-- `Cleanup`
+- `Project Workspaces`(项目 Workspace)
+- `Execution Defaults`(执行默认值)
+- `Provisioning`(资源供给)
+- `Pull Requests`(拉取请求)
+- `Previews and Runtime`(预览与运行时)
+- `Cleanup`(清理)
-### Display rules
+### 显示规则
-- only show when `experimental.workspaces=true`
-- keep wording generic enough for local and remote setups
-- only show git-specific fields when `sourceType=git_repo`
-- only show local-path-specific fields when not `remote_managed`
+- 仅在 `experimental.workspaces=true` 时显示
+- 措辞应足够通用,同时适用于本地和远程配置
+- 仅在 `sourceType=git_repo` 时显示 git 专属字段
+- 仅在非 `remote_managed` 时显示本地路径专属字段
-## 3. Issue create dialog
+## 3. Issue 创建对话框
-When the workspace experimental flag is on and the selected project has workspace automation or workspaces:
+当 workspace 实验性功能开关开启,且所选项目具有 workspace 自动化或 workspace 时:
-### Basic fields
+### 基本字段
-- `Codebase`
- - select from project workspaces
- - default to policy default or primary workspace
-- `Execution mode`
- - `Project default`
- - `Shared workspace`
- - `Isolated workspace`
- - `Operator branch`
+- `Codebase`(代码库)
+ - 从项目 workspace 中选择
+ - 默认为策略默认值或主 workspace
+- `Execution mode`(执行模式)
+ - `Project default`(项目默认)
+ - `Shared workspace`(共享 workspace)
+ - `Isolated workspace`(隔离 workspace)
+ - `Operator branch`(operator 分支)
-### Advanced section
+### 高级选项区
-- `Reuse existing execution workspace`
+- `Reuse existing execution workspace`(复用现有执行 workspace)
-This control should query only:
+该控件的查询范围仅限于:
-- same project
-- same codebase if selected
-- active/recent workspaces
-- compact labels with branch or workspace name
+- 同一项目
+- 若已选择代码库,则限同一代码库
+- 活跃或近期使用过的 workspace
+- 以分支名或 workspace 名为简洁标签
-Do not expose all execution workspaces in a noisy unfiltered list.
+不应以未经过滤的冗长列表展示所有执行 workspace。
-## 4. Issue detail
+## 4. Issue 详情
-Add a `Work Product` tab when:
+在以下情况下显示 `Work Product`(工作产物)标签页:
-- the experimental flag is on, or
-- the issue already has work products
+- 实验性功能开关开启,或
+- 该 issue 已有工作产物
-### Show
+### 展示内容
-- current execution workspace summary
-- PR cards
-- preview cards
-- branch/commit rows
-- artifacts/documents
+- 当前执行 workspace 摘要
+- PR 卡片
+- 预览卡片
+- 分支/提交行
+- 构件/文档
-Add compact header chips:
+新增头部紧凑标签(chip):
-- codebase
+- 代码库
- workspace
-- PR count/status
-- preview status
+- PR 数量/状态
+- 预览状态
-## 5. Execution workspace detail page
+## 5. 执行 workspace 详情页
-Add a detail route but no nav item.
+新增详情路由,但不添加导航入口。
-Linked from:
+从以下位置链接跳转:
-- issue work product tab
-- project workspace/execution panels
+- issue 工作产物标签页
+- 项目 workspace/执行面板
-### Show
+### 展示内容
-- identity and status
-- project workspace origin
-- source issue
-- linked issues
-- branch/ref/provider info
-- runtime services
-- work products
-- cleanup state
+- 身份标识与状态
+- 来源项目 workspace
+- 来源 issue
+- 关联 issue
+- 分支/ref/provider 信息
+- 运行时服务
+- 工作产物
+- 清理状态
-## Runtime and Adapter Behavior
+## 运行时与 Adapter 行为
-## 1. Local adapters
+## 1. 本地 Adapter
-For local adapters:
+对于本地 adapter:
-- continue to use existing cwd/worktree realization paths
-- persist the result as execution workspaces
-- attach runtime services and work product to the execution workspace and issue
+- 继续使用现有的 cwd/worktree 实例化路径
+- 将结果持久化为执行 workspace
+- 将运行时服务和工作产物挂载到执行 workspace 和 issue
-## 2. Remote or cloud adapters
+## 2. 远程或云端 Adapter
-For remote adapters:
+对于远程 adapter:
-- allow execution workspaces with null `cwd`
-- require provider metadata sufficient to identify the remote workspace/session
-- allow work product creation without any host-local process ownership
+- 允许执行 workspace 的 `cwd` 为 null
+- 要求提供足以标识远程 workspace/会话的 provider 元数据
+- 允许在不持有宿主机本地进程的情况下创建工作产物
-Examples:
+示例:
-- cloud coding agent opens a branch and PR on GitHub
-- Vercel preview URL is reported back as a preview work product
-- remote sandbox emits artifact URLs
+- 云端编码 agent 在 GitHub 上创建分支和 PR
+- Vercel 预览 URL 作为预览工作产物上报
+- 远程沙箱产出构件 URL
-## 3. Approval-aware PR workflow
+## 3. 支持审批的 PR 工作流
-V1 should support richer PR state tracking, but not a full review engine.
+V1 应支持更丰富的 PR 状态追踪,但不构建完整的审查引擎。
-### Required actions
+### 必须支持的操作
- `open_pr`
- `mark_ready`
-### Required review states
+### 必须支持的审查状态
- `draft`
- `ready_for_review`
@@ -735,148 +734,148 @@ V1 should support richer PR state tracking, but not a full review engine.
- `merged`
- `closed`
-### Storage approach
+### 存储方案
-- represent these as `issue_work_products` with `type='pull_request'`
-- use `status` and `review_state`
-- store provider-specific details in `metadata`
+- 以 `type='pull_request'` 的 `issue_work_products` 记录来表示上述状态
+- 使用 `status` 和 `review_state` 字段
+- 将 provider 专属详情存储在 `metadata` 中
-## Migration Plan
+## 迁移计划
-## 1. Existing installs
+## 1. 现有安装实例
-The migration posture is backward-compatible by default.
+迁移的基本立场是默认向后兼容。
-### Guarantees
+### 保证事项
-- no existing project must be edited before it keeps working
-- no existing issue flow should start requiring workspace input
-- all new nullable columns must preserve current behavior when absent
+- 现有项目无需编辑即可继续正常运行
+- 现有 issue 流程不应开始强制要求 workspace 输入
+- 所有新增的可空字段在缺失时必须保留当前行为
-## 2. Project workspace migration
+## 2. 项目 workspace 迁移
-Migrate `project_workspaces` in place.
+原地迁移 `project_workspaces`。
-### Backfill
+### 回填
-- derive `source_type`
-- copy `repo_ref` to `default_ref`
-- leave new optional fields null
+- 推导 `source_type`
+- 将 `repo_ref` 复制到 `default_ref`
+- 新增可选字段留空为 null
-## 3. Issue migration
+## 3. Issue 迁移
-Do not backfill `project_workspace_id` or `execution_workspace_id` on all existing issues.
+不对所有现有 issue 回填 `project_workspace_id` 或 `execution_workspace_id`。
-Reason:
+原因:
-- the safest migration is to preserve current runtime behavior and bind explicitly only when new workspace-aware flows are used
+- 最安全的迁移方式是保留当前运行时行为,仅在使用新的 workspace 感知流程时才进行显式绑定
-Interpret old issues as:
+将旧 issue 解读为:
- `executionWorkspacePreference = inherit`
-- compatibility/shared behavior
+- 兼容性/共享行为
-## 4. Runtime history migration
+## 4. 运行时历史迁移
-Do not attempt a perfect historical reconstruction of execution workspaces in the migration itself.
+迁移本身不应尝试对执行 workspace 进行完整的历史重建。
-Instead:
+替代方案:
-- create execution workspace records forward from first new run
-- optionally add a later backfill tool for recent runtime services if it proves valuable
+- 从第一次新运行起向前创建执行 workspace 记录
+- 若事后证明有价值,可选地为近期运行时服务添加补充回填工具
-## Rollout Order
+## 发布顺序
-## Phase 1: Schema and shared contracts
+## 阶段一:Schema 与共享契约
-1. extend `project_workspaces`
-2. add `execution_workspaces`
-3. add `issue_work_products`
-4. extend `issues`
-5. extend `workspace_runtime_services`
-6. update shared types and validators
+1. 扩展 `project_workspaces`
+2. 新增 `execution_workspaces`
+3. 新增 `issue_work_products`
+4. 扩展 `issues`
+5. 扩展 `workspace_runtime_services`
+6. 更新共享类型与校验器
-## Phase 2: Service wiring
+## 阶段二:服务层串联
-1. update project workspace CRUD
-2. update issue create/update resolution
-3. refactor workspace realization to persist execution workspaces
-4. attach runtime services to execution workspaces
-5. add work product service and persistence
+1. 更新项目 workspace 的 CRUD
+2. 更新 issue 创建/更新的解析逻辑
+3. 重构 workspace 实例化以持久化执行 workspace
+4. 将运行时服务挂载到执行 workspace
+5. 新增工作产物服务与持久化
-## Phase 3: API and UI
+## 阶段三:API 与 UI
-1. add execution workspace routes
-2. add work product routes
-3. add instance experimental settings toggle
-4. re-enable and revise project workspace UI behind the flag
-5. add issue create/update controls behind the flag
-6. add issue work product tab
-7. add execution workspace detail page
+1. 新增执行 workspace 路由
+2. 新增工作产物路由
+3. 新增实例实验性功能设置开关
+4. 在功能开关后重新启用并修订项目 workspace UI
+5. 在功能开关后新增 issue 创建/更新控件
+6. 新增 issue 工作产物标签页
+7. 新增执行 workspace 详情页
-## Phase 4: Provider integrations
+## 阶段四:Provider 集成
-1. GitHub PR reporting
-2. preview URL reporting
-3. runtime-service-to-work-product linking
-4. remote/cloud provider references
+1. GitHub PR 报告
+2. 预览 URL 报告
+3. 运行时服务到工作产物的关联
+4. 远程/云端 provider 引用
-## Acceptance Criteria
+## 验收标准
-1. Existing installs continue to behave predictably with no required reconfiguration.
-2. Projects can define local, git, non-git, and remote-managed project workspaces.
-3. Issues can explicitly select a project workspace and execution preference.
-4. Each issue can point to one current execution workspace.
-5. Multiple issues can intentionally reuse the same execution workspace.
-6. Execution workspaces are persisted for both local and remote execution flows.
-7. Work products can be attached to issues with optional execution workspace linkage.
-8. GitHub PRs can be represented with richer lifecycle states.
-9. The main UI remains simple when the experimental flag is off.
-10. No top-level workspace navigation is required for this first slice.
+1. 现有安装实例在无需重新配置的情况下继续可预期地运行。
+2. 项目可定义本地、git、非 git 及远程托管等类型的项目 workspace。
+3. Issue 可显式选择项目 workspace 和执行偏好。
+4. 每个 issue 可关联一个当前执行 workspace。
+5. 多个 issue 可有意地复用同一执行 workspace。
+6. 执行 workspace 在本地和远程执行流程中均可持久化。
+7. 工作产物可挂载到 issue,并可选择关联执行 workspace。
+8. GitHub PR 可使用更丰富的生命周期状态来表示。
+9. 当实验性功能开关关闭时,主 UI 保持简洁。
+10. 第一个切片无需顶层 workspace 导航入口。
-## Risks and Mitigations
+## 风险与缓解措施
-## Risk: too many overlapping workspace concepts
+## 风险:workspace 概念过多且相互重叠
-Mitigation:
+缓解措施:
-- keep issue UI to `Codebase` and `Execution mode`
-- reserve execution workspace details for advanced pages
+- 将 issue UI 限定于 `Codebase`(代码库)和 `Execution mode`(执行模式)
+- 将执行 workspace 详情保留在高级页面中
-## Risk: breaking current projects on upgrade
+## 风险:升级后破坏现有项目
-Mitigation:
+缓解措施:
-- nullable schema additions
-- in-place `project_workspaces` migration
-- compatibility defaults
+- 新增字段均为可空
+- 对 `project_workspaces` 进行原地迁移
+- 设置兼容性默认值
-## Risk: local-only assumptions leaking into cloud mode
+## 风险:本地专属假设泄漏到云端模式
-Mitigation:
+缓解措施:
-- make `cwd` optional for execution workspaces
-- use `provider_type` and `provider_ref`
-- use `PAPERCLIP_EXECUTION_TOPOLOGY` as a defaulting guardrail
+- 使执行 workspace 的 `cwd` 为可选
+- 使用 `provider_type` 和 `provider_ref`
+- 使用 `PAPERCLIP_EXECUTION_TOPOLOGY` 作为默认值护栏
-## Risk: turning PRs into a bespoke subsystem too early
+## 风险:过早将 PR 构建为定制子系统
-Mitigation:
+缓解措施:
-- represent PRs as work products in V1
-- keep provider-specific details in metadata
-- defer a dedicated PR table unless usage proves it necessary
+- V1 中将 PR 表示为工作产物
+- 将 provider 专属详情保留在 metadata 中
+- 推迟独立 PR 表的建设,除非实际使用证明有必要
-## Recommended First Engineering Slice
+## 推荐的首个工程切片
-If we want the narrowest useful implementation:
+若追求最小可用实现:
-1. extend `project_workspaces`
-2. add `execution_workspaces`
-3. extend `issues` with explicit workspace fields
-4. persist execution workspaces from existing local workspace realization
-5. add `issue_work_products`
-6. show project workspace controls and issue workspace controls behind the experimental flag
-7. add issue `Work Product` tab with PR/preview/runtime service display
+1. 扩展 `project_workspaces`
+2. 新增 `execution_workspaces`
+3. 为 `issues` 新增显式 workspace 字段
+4. 从现有本地 workspace 实例化中持久化执行 workspace
+5. 新增 `issue_work_products`
+6. 在实验性功能开关后展示项目 workspace 控件和 issue workspace 控件
+7. 新增 issue `Work Product` 标签页,展示 PR/预览/运行时服务
-This slice is enough to validate the model without yet building every provider integration or cleanup workflow.
+该切片已足以验证模型,无需在此阶段构建所有 provider 集成或清理工作流。
diff --git a/doc/plugins/PLUGIN_AUTHORING_GUIDE.md b/doc/plugins/PLUGIN_AUTHORING_GUIDE.md
index 075156fd0f..bb4a57be70 100644
--- a/doc/plugins/PLUGIN_AUTHORING_GUIDE.md
+++ b/doc/plugins/PLUGIN_AUTHORING_GUIDE.md
@@ -1,28 +1,28 @@
-# Plugin Authoring Guide
+# 插件开发指南
-This guide describes the current, implemented way to create a Paperclip plugin in this repo.
+本指南描述了在此仓库中创建 Paperclip 插件的当前已实现方式。
-It is intentionally narrower than [PLUGIN_SPEC.md](./PLUGIN_SPEC.md). The spec includes future ideas; this guide only covers the alpha surface that exists now.
+它有意比 [PLUGIN_SPEC.md](./PLUGIN_SPEC.md) 范围更窄。规范包含未来的构想;本指南仅涵盖当前已存在的 alpha 版本接口。
-## Current reality
+## 当前现状
-- Treat plugin workers and plugin UI as trusted code.
-- Plugin UI runs as same-origin JavaScript inside the main Paperclip app.
-- Worker-side host APIs are capability-gated.
-- Plugin UI is not sandboxed by manifest capabilities.
-- There is no host-provided shared React component kit for plugins yet.
-- `ctx.assets` is not supported in the current runtime.
+- 将插件 worker 和插件 UI 视为可信代码。
+- 插件 UI 作为同源 JavaScript 在 Paperclip 主应用内运行。
+- Worker 端宿主 API 受能力门控。
+- 插件 UI 不受清单能力的沙箱限制。
+- 目前还没有为插件提供宿主共享的 React 组件工具包。
+- 当前运行时不支持 `ctx.assets`。
-## Scaffold a plugin
+## 创建插件脚手架
-Use the scaffold package:
+使用脚手架包:
```bash
pnpm --filter @paperclipai/create-paperclip-plugin build
node packages/plugins/create-paperclip-plugin/dist/index.js @yourscope/plugin-name --output ./packages/plugins/examples
```
-For a plugin that lives outside the Paperclip repo:
+对于位于 Paperclip 仓库外部的插件:
```bash
pnpm --filter @paperclipai/create-paperclip-plugin build
@@ -31,7 +31,7 @@ node packages/plugins/create-paperclip-plugin/dist/index.js @yourscope/plugin-na
--sdk-path /absolute/path/to/paperclip/packages/plugins/sdk
```
-That creates a package with:
+这将创建一个包含以下内容的包:
- `src/manifest.ts`
- `src/worker.ts`
@@ -40,13 +40,13 @@ That creates a package with:
- `esbuild.config.mjs`
- `rollup.config.mjs`
-Inside this monorepo, the scaffold uses `workspace:*` for `@paperclipai/plugin-sdk`.
+在此 monorepo 内,脚手架使用 `workspace:*` 引用 `@paperclipai/plugin-sdk`。
-Outside this monorepo, the scaffold snapshots `@paperclipai/plugin-sdk` from the local Paperclip checkout into a `.paperclip-sdk/` tarball so you can build and test a plugin without publishing anything to npm first.
+在此 monorepo 外部,脚手架会从本地 Paperclip 检出中快照 `@paperclipai/plugin-sdk` 到 `.paperclip-sdk/` tarball,这样您无需先发布到 npm 即可构建和测试插件。
-## Recommended local workflow
+## 推荐的本地工作流
-From the generated plugin folder:
+从生成的插件文件夹中:
```bash
pnpm install
@@ -55,9 +55,9 @@ pnpm test
pnpm build
```
-For local development, install it into Paperclip from an absolute local path through the plugin manager or API. The server supports local filesystem installs and watches local-path plugins for file changes so worker restarts happen automatically after rebuilds.
+对于本地开发,通过插件管理器或 API 从绝对本地路径安装插件。服务器支持本地文件系统安装,并会监视本地路径插件的文件变更,因此重建后 worker 会自动重启。
-Example:
+示例:
```bash
curl -X POST http://127.0.0.1:3100/api/plugins/install \
@@ -65,9 +65,9 @@ curl -X POST http://127.0.0.1:3100/api/plugins/install \
-d '{"packageName":"/absolute/path/to/your-plugin","isLocalPath":true}'
```
-## Supported alpha surface
+## 支持的 alpha 版本接口
-Worker:
+Worker:
- config
- events
@@ -89,16 +89,16 @@ Worker:
- metrics
- logger
-UI:
+UI:
- `usePluginData`
- `usePluginAction`
- `usePluginStream`
- `usePluginToast`
- `useHostContext`
-- typed slot props from `@paperclipai/plugin-sdk/ui`
+- 来自 `@paperclipai/plugin-sdk/ui` 的类型化插槽属性
-Mount surfaces currently wired in the host include:
+当前在宿主中已连接的挂载界面包括:
- `page`
- `settingsPage`
@@ -114,31 +114,31 @@ Mount surfaces currently wired in the host include:
- `commentAnnotation`
- `commentContextMenuItem`
-## Company routes
+## 公司路由
-Plugins may declare a `page` slot with `routePath` to own a company route like:
+插件可以声明带有 `routePath` 的 `page` 插槽来拥有一个公司路由,例如:
```text
/:companyPrefix/
```
-Rules:
+规则:
-- `routePath` must be a single lowercase slug
-- it cannot collide with reserved host routes
-- it cannot duplicate another installed plugin page route
+- `routePath` 必须是单个小写短横线分隔的标识符
+- 不能与保留的宿主路由冲突
+- 不能与其他已安装插件的页面路由重复
-## Publishing guidance
+## 发布指南
-- Use npm packages as the deployment artifact.
-- Treat repo-local example installs as a development workflow only.
-- Prefer keeping plugin UI self-contained inside the package.
-- Do not rely on host design-system components or undocumented app internals.
-- GitHub repository installs are not a first-class workflow today. For local development, use a checked-out local path. For production, publish to npm or a private npm-compatible registry.
+- 使用 npm 包作为部署产物。
+- 将仓库本地示例安装仅视为开发工作流。
+- 优先将插件 UI 自包含在包内。
+- 不要依赖宿主设计系统组件或未文档化的应用内部实现。
+- GitHub 仓库安装目前不是一等公民的工作流。对于本地开发,使用已检出的本地路径。对于生产环境,发布到 npm 或私有的 npm 兼容注册中心。
-## Verification before handoff
+## 交付前验证
-At minimum:
+至少执行以下操作:
```bash
pnpm --filter typecheck
@@ -146,7 +146,7 @@ pnpm --filter test
pnpm --filter build
```
-If you changed host integration too, also run:
+如果您同时更改了宿主集成,还需运行:
```bash
pnpm -r typecheck
diff --git a/doc/plugins/PLUGIN_SPEC.md b/doc/plugins/PLUGIN_SPEC.md
index f3ec64736b..f5547d9d32 100644
--- a/doc/plugins/PLUGIN_SPEC.md
+++ b/doc/plugins/PLUGIN_SPEC.md
@@ -1,245 +1,245 @@
-# Paperclip Plugin System Specification
+# Paperclip 插件系统规范
-Status: proposed complete spec for the post-V1 plugin system
+状态:V1 之后插件系统的完整拟议规范
-This document is the complete specification for Paperclip's plugin and extension architecture.
-It expands the brief plugin notes in [doc/SPEC.md](../SPEC.md) and should be read alongside the comparative analysis in [doc/plugins/ideas-from-opencode.md](./ideas-from-opencode.md).
+本文档是 Paperclip 插件与扩展架构的完整规范。
+它扩展了 [doc/SPEC.md](../SPEC.md) 中的简要插件说明,应与 [doc/plugins/ideas-from-opencode.md](./ideas-from-opencode.md) 中的比较分析一同阅读。
-This is not part of the V1 implementation contract in [doc/SPEC-implementation.md](../SPEC-implementation.md).
-It is the full target architecture for the plugin system that should follow V1.
+本文档不属于 [doc/SPEC-implementation.md](../SPEC-implementation.md) 中 V1 实施合同的范畴。
+它是 V1 之后插件系统的完整目标架构。
-## Current implementation caveats
+## 当前实现注意事项
-The code in this repo now includes an early plugin runtime and admin UI, but it does not yet deliver the full deployment model described in this spec.
+本仓库中的代码已包含早期插件运行时和管理界面,但尚未实现本规范所描述的完整部署模型。
-Today, the practical deployment model is:
+目前,实际部署模型为:
-- single-tenant
-- self-hosted
-- single-node or otherwise filesystem-persistent
+- 单租户
+- 自托管
+- 单节点或具有文件系统持久化
-Current limitations to keep in mind:
+当前需要注意的限制:
-- Plugin UI bundles currently run as same-origin JavaScript inside the main Paperclip app. Treat plugin UI as trusted code, not a sandboxed frontend capability boundary.
-- Manifest capabilities currently gate worker-side host RPC calls. They do not prevent plugin UI code from calling ordinary Paperclip HTTP APIs directly.
-- Runtime installs assume a writable local filesystem for the plugin package directory and plugin data directory.
-- Runtime npm installs assume `npm` is available in the running environment and that the host can reach the configured package registry.
-- Published npm packages are the intended install artifact for deployed plugins.
-- The repo example plugins under `packages/plugins/examples/` are development conveniences. They work from a source checkout and should not be assumed to exist in a generic published build unless they are explicitly shipped with that build.
-- Dynamic plugin install is not yet cloud-ready for horizontally scaled or ephemeral deployments. There is no shared artifact store, install coordination, or cross-node distribution layer yet.
-- The current runtime does not yet ship a real host-provided plugin UI component kit, and it does not support plugin asset uploads/reads. Treat those as future-scope ideas in this spec, not current implementation promises.
+- 插件 UI 包目前作为同源 JavaScript 在 Paperclip 主应用中运行。请将插件 UI 视为受信任代码,而非沙箱化的前端能力边界。
+- 清单(Manifest)能力目前仅对 worker 侧的主机 RPC 调用进行管控,无法阻止插件 UI 代码直接调用普通的 Paperclip HTTP API。
+- 运行时安装假定插件包目录和插件数据目录所在的本地文件系统可写。
+- 运行时 npm 安装假定运行环境中存在 `npm`,且主机能够访问配置的包注册表。
+- 已发布的 npm 包是已部署插件的预期安装产物。
+- `packages/plugins/examples/` 下的示例插件是开发便利工具,仅在源码检出时可用,不应假定其存在于通用发布构建中(除非该构建明确包含这些插件)。
+- 动态插件安装尚未针对水平扩展或临时部署的云环境做好准备。目前尚无共享制品存储、安装协调或跨节点分发层。
+- 当前运行时尚未提供真正由主机提供的插件 UI 组件套件,也不支持插件资产的上传/读取。请将这些内容视为本规范中的未来功能设想,而非当前实现承诺。
-In practice, that means the current implementation is a good fit for local development and self-hosted persistent deployments, but not yet for multi-instance cloud plugin distribution.
+实际上,当前实现适用于本地开发和自托管持久化部署,但尚不适用于多实例云端插件分发。
-## 1. Scope
+## 1. 范围
-This spec covers:
+本规范涵盖:
-- plugin packaging and installation
-- runtime model
-- trust model
-- capability system
-- UI extension surfaces
-- plugin settings UI
-- agent tool contributions
-- event, job, and webhook surfaces
-- plugin-to-plugin communication
-- local tooling approach for workspace plugins
-- Postgres persistence for extensions
-- uninstall and data lifecycle
-- plugin observability
-- plugin development and testing
-- operator workflows
-- hot plugin lifecycle (no server restart)
-- SDK versioning and compatibility rules
+- 插件打包与安装
+- 运行时模型
+- 信任模型
+- 能力系统
+- UI 扩展界面
+- 插件设置 UI
+- Agent 工具贡献
+- 事件、作业和 Webhook 界面
+- 插件间通信
+- 工作区插件的本地工具方法
+- 扩展的 Postgres 持久化
+- 卸载与数据生命周期
+- 插件可观测性
+- 插件开发与测试
+- 运营者工作流
+- 热插件生命周期(无需重启服务器)
+- SDK 版本管理与兼容性规则
-This spec does not cover:
+本规范不涵盖:
-- a public marketplace
-- cloud/SaaS multi-tenancy
-- arbitrary third-party schema migrations in the first plugin version
-- iframe-sandboxed plugin UI in the first plugin version (plugins render as ES modules in host extension slots)
+- 公共插件市场
+- 云端/SaaS 多租户
+- 第一个插件版本中的任意第三方 Schema 迁移
+- 第一个插件版本中基于 iframe 沙箱的插件 UI(插件以 ES 模块形式在主机扩展槽中渲染)
-## 2. Core Assumptions
+## 2. 核心假设
-Paperclip plugin design is based on the following assumptions:
+Paperclip 插件设计基于以下假设:
-1. Paperclip is single-tenant and self-hosted.
-2. Plugin installation is global to the instance.
-3. "Companies" remain core Paperclip business objects, but they are not plugin trust boundaries.
-4. Board governance, approval gates, budget hard-stops, and core task invariants remain owned by Paperclip core.
-5. Projects already have a real workspace model via `project_workspaces`, and local/runtime plugins should build on that instead of inventing a separate workspace abstraction.
+1. Paperclip 是单租户且自托管的。
+2. 插件安装对整个实例全局生效。
+3. "公司"仍是 Paperclip 的核心业务对象,但不是插件信任边界。
+4. 董事会治理、审批关卡、预算硬性限制以及核心任务不变量仍由 Paperclip 核心所有。
+5. 项目已通过 `project_workspaces` 拥有真实的工作区模型,本地/运行时插件应基于该模型构建,而不是另起一套工作区抽象。
-## 3. Goals
+## 3. 目标
-The plugin system must:
+插件系统必须:
-1. Let operators install global instance-wide plugins.
-2. Let plugins add major capabilities without editing Paperclip core.
-3. Keep core governance and auditing intact.
-4. Support both local/runtime plugins and external SaaS connectors.
-5. Support future plugin categories such as:
- - new agent adapters
- - revenue tracking
- - knowledge base
- - issue tracker sync
- - metrics/dashboards
- - file/project tooling
-6. Use simple, explicit, typed contracts.
-7. Keep failures isolated so one plugin does not crash the entire instance.
+1. 允许运营者安装全局实例范围的插件。
+2. 允许插件在不修改 Paperclip 核心的情况下添加重要功能。
+3. 保持核心治理与审计机制完整。
+4. 同时支持本地/运行时插件和外部 SaaS 连接器。
+5. 支持未来的插件类别,例如:
+ - 新的 Agent 适配器
+ - 收入追踪
+ - 知识库
+ - 问题追踪器同步
+ - 指标/仪表板
+ - 文件/项目工具
+6. 使用简单、明确、有类型的合约。
+7. 保持故障隔离,使单个插件不会导致整个实例崩溃。
-## 4. Non-Goals
+## 4. 非目标
-The first plugin system must not:
+第一个插件系统不得:
-1. Allow arbitrary plugins to override core routes or core invariants.
-2. Allow arbitrary plugins to mutate approval, auth, issue checkout, or budget enforcement logic.
-3. Allow arbitrary third-party plugins to run free-form DB migrations.
-4. Depend on project-local plugin folders such as `.paperclip/plugins`.
-5. Depend on automatic install-and-execute behavior at server startup from arbitrary config files.
+1. 允许任意插件覆盖核心路由或核心不变量。
+2. 允许任意插件修改审批、认证、问题签出或预算执行逻辑。
+3. 允许任意第三方插件运行自由格式的数据库迁移。
+4. 依赖项目本地插件文件夹(如 `.paperclip/plugins`)。
+5. 依赖服务器启动时从任意配置文件自动安装并执行的行为。
-## 5. Terminology
+## 5. 术语
-### 5.1 Instance
+### 5.1 实例(Instance)
-The single Paperclip deployment an operator installs and controls.
+运营者安装并管理的单个 Paperclip 部署。
-### 5.2 Company
+### 5.2 公司(Company)
-A first-class Paperclip business object inside the instance.
+实例内的 Paperclip 一等业务对象。
-### 5.3 Project Workspace
+### 5.3 项目工作区(Project Workspace)
-A workspace attached to a project through `project_workspaces`.
-Plugins resolve workspace paths from this model to locate local directories for file, terminal, git, and process operations.
+通过 `project_workspaces` 关联到项目的工作区。
+插件从该模型中解析工作区路径,以定位用于文件、终端、git 和进程操作的本地目录。
-### 5.4 Platform Module
+### 5.4 平台模块(Platform Module)
-A trusted in-process extension loaded directly by Paperclip core.
+由 Paperclip 核心直接加载的受信任进程内扩展。
-Examples:
+示例:
-- agent adapters
-- storage providers
-- secret providers
-- run-log backends
+- Agent 适配器
+- 存储提供者
+- 密钥提供者
+- 运行日志后端
-### 5.5 Plugin
+### 5.5 插件(Plugin)
-An installable instance-wide extension package loaded through the Paperclip plugin runtime.
+通过 Paperclip 插件运行时加载的、可安装的实例范围扩展包。
-Examples:
+示例:
-- Linear sync
-- GitHub Issues sync
-- Grafana widgets
-- Stripe revenue sync
-- file browser
-- terminal
-- git workflow
+- Linear 同步
+- GitHub Issues 同步
+- Grafana 小部件
+- Stripe 收入同步
+- 文件浏览器
+- 终端
+- git 工作流
-### 5.6 Plugin Worker
+### 5.6 插件 Worker(Plugin Worker)
-The runtime process used for a plugin.
-In this spec, third-party plugins run out-of-process by default.
+插件使用的运行时进程。
+在本规范中,第三方插件默认以进程外方式运行。
-### 5.7 Capability
+### 5.7 能力(Capability)
-A named permission the host grants to a plugin.
-Plugins may only call host APIs that are covered by granted capabilities.
+主机授予插件的命名权限。
+插件只能调用其获得授权的能力所覆盖的主机 API。
-## 6. Extension Classes
+## 6. 扩展类别
-Paperclip has two extension classes.
+Paperclip 有两种扩展类别。
-## 6.1 Platform Modules
+## 6.1 平台模块
-Platform modules are:
+平台模块具有以下特点:
-- trusted
-- in-process
-- host-integrated
-- low-level
+- 受信任
+- 进程内
+- 与主机集成
+- 底层
-They use explicit registries, not the general plugin worker protocol.
+它们使用显式注册表,而非通用插件 worker 协议。
-Platform module surfaces:
+平台模块界面:
- `registerAgentAdapter()`
- `registerStorageProvider()`
- `registerSecretProvider()`
- `registerRunLogStore()`
-Platform modules are the right place for:
+平台模块适用于:
-- new agent adapter packages
-- new storage backends
-- new secret backends
-- other host-internal systems that need direct process or DB integration
+- 新的 Agent 适配器包
+- 新的存储后端
+- 新的密钥后端
+- 其他需要直接进程或数据库集成的主机内部系统
-## 6.2 Plugins
+## 6.2 插件
-Plugins are:
+插件具有以下特点:
-- globally installed per instance
-- loaded through the plugin runtime
-- additive
-- capability-gated
-- isolated from core via a stable SDK and host protocol
+- 按实例全局安装
+- 通过插件运行时加载
+- 附加式(additive)
+- 能力管控
+- 通过稳定的 SDK 和主机协议与核心隔离
-Plugin categories:
+插件类别:
- `connector`
- `workspace`
- `automation`
- `ui`
-A plugin may declare more than one category.
+一个插件可以声明多个类别。
-## 7. Project Workspaces
+## 7. 项目工作区
-Paperclip already has a concrete workspace model:
+Paperclip 已拥有具体的工作区模型:
-- projects expose `workspaces`
-- projects expose `primaryWorkspace`
-- the database contains `project_workspaces`
-- project routes already manage workspaces
+- 项目暴露 `workspaces`
+- 项目暴露 `primaryWorkspace`
+- 数据库包含 `project_workspaces`
+- 项目路由已管理工作区
-Plugins that need local tooling (file browsing, git, terminals, process tracking) can resolve workspace paths through the project workspace APIs and then operate on the filesystem, spawn processes, and run git commands directly. The host does not wrap these operations — plugins own their own implementations.
+需要本地工具(文件浏览、git、终端、进程追踪)的插件可通过项目工作区 API 解析工作区路径,然后直接操作文件系统、生成进程并运行 git 命令。主机不对这些操作进行封装——插件自行拥有其实现。
-## 8. Installation Model
+## 8. 安装模型
-Plugin installation is global and operator-driven.
+插件安装是全局的,由运营者驱动。
-There is no per-company install table and no per-company enable/disable switch.
+不存在按公司维度的安装表,也没有按公司维度的启用/禁用开关。
-If a plugin needs business-object-specific mappings, those are stored as plugin configuration or plugin state.
+如果插件需要与业务对象相关的映射,这些映射将作为插件配置或插件状态存储。
-Examples:
+示例:
-- one global Linear plugin install
-- mappings from company A to Linear team X and company B to Linear team Y
-- one global git plugin install
-- per-project workspace state stored under `project_workspace`
+- 一个全局 Linear 插件安装
+- 公司 A 到 Linear 团队 X、公司 B 到 Linear 团队 Y 的映射
+- 一个全局 git 插件安装
+- 存储在 `project_workspace` 下的按项目工作区状态
-## 8.1 On-Disk Layout
+## 8.1 磁盘布局
-Plugins live under the Paperclip instance directory.
+插件位于 Paperclip 实例目录下。
-Suggested layout:
+建议布局:
- `~/.paperclip/instances/default/plugins/package.json`
- `~/.paperclip/instances/default/plugins/node_modules/`
- `~/.paperclip/instances/default/plugins/.cache/`
- `~/.paperclip/instances/default/data/plugins//`
-The package install directory and the plugin data directory are separate.
+包安装目录和插件数据目录是分开的。
-This on-disk model is the reason the current implementation expects a persistent writable host filesystem. Cloud-safe artifact replication is future work.
+这种磁盘模型是当前实现需要持久化可写主机文件系统的原因。云安全的制品复制是未来的工作。
-## 8.2 Operator Commands
+## 8.2 运营者命令
-Paperclip should add CLI commands:
+Paperclip 应添加以下 CLI 命令:
- `pnpm paperclipai plugin list`
- `pnpm paperclipai plugin install `
@@ -247,51 +247,51 @@ Paperclip should add CLI commands:
- `pnpm paperclipai plugin upgrade [version]`
- `pnpm paperclipai plugin doctor `
-These commands are instance-level operations.
+这些命令是实例级操作。
-## 8.3 Install Process
+## 8.3 安装流程
-The install process is:
+安装流程如下:
-1. Resolve npm package and version.
-2. Install into the instance plugin directory.
-3. Read and validate plugin manifest.
-4. Reject incompatible plugin API versions.
-5. Display requested capabilities to the operator.
-6. Persist install record in Postgres.
-7. Start plugin worker and run health/validation.
-8. Mark plugin `ready` or `error`.
+1. 解析 npm 包和版本。
+2. 安装到实例插件目录。
+3. 读取并验证插件清单。
+4. 拒绝不兼容的插件 API 版本。
+5. 向运营者显示所请求的能力。
+6. 在 Postgres 中持久化安装记录。
+7. 启动插件 worker 并运行健康/验证检查。
+8. 将插件标记为 `ready` 或 `error`。
-For the current implementation, this install flow should be read as a single-host workflow. A successful install writes packages to the local host, and other app nodes will not automatically receive that plugin unless a future shared distribution mechanism is added.
+对于当前实现,此安装流程应理解为单主机工作流。成功安装后包会写入本地主机,除非未来添加了共享分发机制,否则其他应用节点不会自动获得该插件。
-## 9. Load Order And Precedence
+## 9. 加载顺序与优先级
-Load order must be deterministic.
+加载顺序必须是确定性的。
-1. core platform modules
-2. built-in first-party plugins
-3. installed plugins sorted by:
- - explicit operator-configured order if present
- - otherwise manifest `id`
+1. 核心平台模块
+2. 内置第一方插件
+3. 已安装插件,排序方式为:
+ - 如有运营者显式配置的顺序,则优先使用
+ - 否则按清单 `id` 排序
-Rules:
+规则:
-- plugin contributions are additive by default
-- plugins may not override core routes or core actions by name collision
-- UI slot IDs are automatically namespaced by plugin ID (e.g. `@paperclip/plugin-linear:sync-health-widget`), so cross-plugin collisions are structurally impossible
-- if a single plugin declares duplicate slot IDs within its own manifest, the host must reject at install time
+- 插件贡献默认是附加式的
+- 插件不得通过名称冲突覆盖核心路由或核心动作
+- UI 槽 ID 会自动以插件 ID 命名空间化(例如 `@paperclip/plugin-linear:sync-health-widget`),因此跨插件冲突在结构上是不可能发生的
+- 如果单个插件在其清单中声明了重复的槽 ID,主机必须在安装时拒绝
-## 10. Package Contract
+## 10. 包合约
-Each plugin package must export a manifest, a worker entrypoint, and optionally a UI bundle.
+每个插件包必须导出一个清单、一个 worker 入口点,以及可选的 UI 包。
-Suggested package layout:
+建议的包布局:
- `dist/manifest.js`
- `dist/worker.js`
-- `dist/ui/` (optional, contains the plugin's frontend bundle)
+- `dist/ui/`(可选,包含插件的前端包)
-Suggested `package.json` keys:
+建议的 `package.json` 键:
```json
{
@@ -305,9 +305,9 @@ Suggested `package.json` keys:
}
```
-## 10.1 Manifest Shape
+## 10.1 清单结构
-Normative manifest shape:
+规范性清单结构:
```ts
export interface PaperclipPluginManifestV1 {
@@ -346,23 +346,23 @@ export interface PaperclipPluginManifestV1 {
}
```
-Rules:
+规则:
-- `id` must be globally unique
-- `id` should normally equal the npm package name
-- `apiVersion` must match the host-supported plugin API version
-- `capabilities` must be static and install-time visible
-- config schema must be JSON Schema compatible
-- `entrypoints.ui` points to the directory containing the built UI bundle
-- `ui.slots` declares which extension slots the plugin fills, so the host knows what to mount without loading the bundle eagerly; each slot references an `exportName` from the UI bundle
+- `id` 必须全局唯一
+- `id` 通常应等于 npm 包名
+- `apiVersion` 必须与主机支持的插件 API 版本匹配
+- `capabilities` 必须是静态的,并在安装时可见
+- 配置 schema 必须与 JSON Schema 兼容
+- `entrypoints.ui` 指向包含构建后 UI 包的目录
+- `ui.slots` 声明插件填充哪些扩展槽,使主机无需急于加载包即可知道挂载什么;每个槽引用 UI 包中的一个 `exportName`
-## 11. Agent Tools
+## 11. Agent 工具
-Plugins may contribute tools that Paperclip agents can use during runs.
+插件可以贡献 Paperclip Agent 在运行期间可使用的工具。
-### 11.1 Tool Declaration
+### 11.1 工具声明
-Plugins declare tools in their manifest:
+插件在其清单中声明工具:
```ts
tools?: Array<{
@@ -373,108 +373,108 @@ tools?: Array<{
}>;
```
-Tool names are automatically namespaced by plugin ID at runtime (e.g. `linear:search-issues`), so plugins cannot shadow core tools or each other's tools.
+工具名称在运行时会自动以插件 ID 命名空间化(例如 `linear:search-issues`),因此插件无法遮蔽核心工具或彼此的工具。
-### 11.2 Tool Execution
+### 11.2 工具执行
-When an agent invokes a plugin tool during a run, the host routes the call to the plugin worker via a `executeTool` RPC method:
+当 Agent 在运行期间调用插件工具时,主机通过 `executeTool` RPC 方法将调用路由到插件 worker:
-- `executeTool(input)` — receives tool name, parsed parameters, and run context (agent ID, run ID, company ID, project ID)
+- `executeTool(input)` — 接收工具名称、已解析的参数以及运行上下文(Agent ID、运行 ID、公司 ID、项目 ID)
-The worker executes the tool logic and returns a typed result. The host enforces capability gates — a plugin must declare `agent.tools.register` to contribute tools, and individual tools may require additional capabilities (e.g. `http.outbound` for tools that call external APIs).
+worker 执行工具逻辑并返回类型化结果。主机强制执行能力管控——插件必须声明 `agent.tools.register` 才能贡献工具,单个工具可能还需要额外的能力(例如调用外部 API 的工具需要 `http.outbound`)。
-### 11.3 Tool Availability
+### 11.3 工具可用性
-By default, plugin tools are available to all agents. The operator may restrict tool availability per agent or per project through plugin configuration.
+默认情况下,插件工具对所有 Agent 可用。运营者可以通过插件配置按 Agent 或按项目限制工具可用性。
-Plugin tools appear in the agent's tool list alongside core tools but are visually distinguished in the UI as plugin-contributed.
+插件工具与核心工具一同出现在 Agent 的工具列表中,但在 UI 中会被视觉上区分为插件贡献的工具。
-### 11.4 Constraints
+### 11.4 约束
-- Plugin tools must not override or shadow core tools by name.
-- Plugin tools must be idempotent where possible.
-- Tool execution is subject to the same timeout and resource limits as other plugin worker calls.
-- Tool results are included in run logs.
+- 插件工具不得通过名称覆盖或遮蔽核心工具。
+- 插件工具应尽可能保持幂等性。
+- 工具执行受到与其他插件 worker 调用相同的超时和资源限制。
+- 工具结果会包含在运行日志中。
-## 12. Runtime Model
+## 12. 运行时模型
-## 12.1 Process Model
+## 12.1 进程模型
-Third-party plugins run out-of-process by default.
+第三方插件默认以进程外方式运行。
-Default runtime:
+默认运行时:
-- Paperclip server starts one worker process per installed plugin
-- the worker process is a Node process
-- host and worker communicate over JSON-RPC on stdio
+- Paperclip 服务器为每个已安装的插件启动一个 worker 进程
+- worker 进程是 Node 进程
+- 主机和 worker 通过 stdio 上的 JSON-RPC 进行通信
-This design provides:
+该设计提供了:
-- failure isolation
-- clearer logging boundaries
-- easier resource limits
-- a cleaner trust boundary than arbitrary in-process execution
+- 故障隔离
+- 更清晰的日志边界
+- 更容易的资源限制
+- 比任意进程内执行更清晰的信任边界
-## 12.2 Host Responsibilities
+## 12.2 主机职责
-The host is responsible for:
+主机负责:
-- package install
-- manifest validation
-- capability enforcement
-- process supervision
-- job scheduling
-- webhook routing
-- activity log writes
-- secret resolution
-- UI route registration
+- 包安装
+- 清单验证
+- 能力执行
+- 进程监督
+- 作业调度
+- Webhook 路由
+- 活动日志写入
+- 密钥解析
+- UI 路由注册
-## 12.3 Worker Responsibilities
+## 12.3 Worker 职责
-The plugin worker is responsible for:
+插件 worker 负责:
-- validating its own config
-- handling domain events
-- handling scheduled jobs
-- handling webhooks
-- serving data and handling actions for the plugin's own UI via `getData` and `performAction`
-- invoking host services through the SDK
-- reporting health information
+- 验证其自身配置
+- 处理领域事件
+- 处理计划作业
+- 处理 Webhook
+- 通过 `getData` 和 `performAction` 为插件自身的 UI 提供数据并处理动作
+- 通过 SDK 调用主机服务
+- 报告健康信息
-## 12.4 Failure Policy
+## 12.4 故障策略
-If a worker fails:
+如果 worker 失败:
-- mark plugin status `error`
-- surface error in plugin health UI
-- keep the rest of the instance running
-- retry start with bounded backoff
-- do not drop other plugins or core services
+- 将插件状态标记为 `error`
+- 在插件健康 UI 中显示错误
+- 保持实例其余部分继续运行
+- 以有界退避重试启动
+- 不丢弃其他插件或核心服务
-## 12.5 Graceful Shutdown Policy
+## 12.5 优雅关闭策略
-When the host needs to stop a plugin worker (for upgrade, uninstall, or instance shutdown):
+当主机需要停止插件 worker 时(用于升级、卸载或实例关闭):
-1. The host sends `shutdown()` to the worker.
-2. The worker has 10 seconds to finish in-flight work and exit cleanly.
-3. If the worker does not exit within the deadline, the host sends SIGTERM.
-4. If the worker does not exit within 5 seconds after SIGTERM, the host sends SIGKILL.
-5. Any in-flight job runs are marked `cancelled` with a note indicating forced shutdown.
-6. Any in-flight `getData` or `performAction` calls return an error to the bridge.
+1. 主机向 worker 发送 `shutdown()`。
+2. worker 有 10 秒时间完成进行中的工作并干净退出。
+3. 如果 worker 在截止时间内未退出,主机发送 SIGTERM。
+4. 如果 worker 在 SIGTERM 后 5 秒内仍未退出,主机发送 SIGKILL。
+5. 所有进行中的作业运行将被标记为 `cancelled`,并附注说明是强制关闭。
+6. 所有进行中的 `getData` 或 `performAction` 调用向 bridge 返回错误。
-The shutdown deadline should be configurable per-plugin in plugin config for plugins that need longer drain periods.
+对于需要更长排空时间的插件,关闭截止时间应可在插件配置中按插件进行配置。
-## 13. Host-Worker Protocol
+## 13. 主机-Worker 协议
-The host must support the following worker RPC methods.
+主机必须支持以下 worker RPC 方法。
-Required methods:
+必须支持的方法:
- `initialize(input)`
- `health()`
- `shutdown()`
-Optional methods:
+可选方法:
- `validateConfig(input)`
- `configChanged(input)`
@@ -487,120 +487,120 @@ Optional methods:
### 13.1 `initialize`
-Called once on worker startup.
+在 worker 启动时调用一次。
-Input includes:
+输入包括:
-- plugin manifest
-- resolved plugin config
-- instance info
-- host API version
+- 插件清单
+- 已解析的插件配置
+- 实例信息
+- 主机 API 版本
### 13.2 `health`
-Returns:
+返回:
-- status
-- current error if any
-- optional plugin-reported diagnostics
+- 状态
+- 当前错误(如有)
+- 可选的插件报告诊断信息
### 13.3 `validateConfig`
-Runs after config changes and startup.
+在配置变更和启动后运行。
-Returns:
+返回:
- `ok`
-- warnings
-- errors
+- 警告
+- 错误
### 13.4 `configChanged`
-Called when the operator updates the plugin's instance config at runtime.
+当运营者在运行时更新插件的实例配置时调用。
-Input includes:
+输入包括:
-- new resolved config
+- 新的已解析配置
-If the worker implements this method, it applies the new config without restarting. If the worker does not implement this method, the host restarts the worker process with the new config (graceful shutdown then restart).
+如果 worker 实现了此方法,则无需重启即可应用新配置。如果 worker 未实现此方法,主机将以新配置重启 worker 进程(优雅关闭后重启)。
### 13.5 `onEvent`
-Receives one typed Paperclip domain event.
+接收一个类型化的 Paperclip 领域事件。
-Delivery semantics:
+投递语义:
-- at least once
-- plugin must be idempotent
-- no global ordering guarantee across all event types
-- per-entity ordering is best effort but not guaranteed after retries
+- 至少一次
+- 插件必须保持幂等性
+- 跨所有事件类型无全局排序保证
+- 按实体排序是尽力而为,重试后不保证
### 13.6 `runJob`
-Runs a declared scheduled job.
+运行一个已声明的计划作业。
-The host provides:
+主机提供:
-- job key
-- trigger source
-- run id
-- schedule metadata
+- 作业键
+- 触发来源
+- 运行 ID
+- 调度元数据
### 13.7 `handleWebhook`
-Receives inbound webhook payload routed by the host.
+接收由主机路由的入站 Webhook 载荷。
-The host provides:
+主机提供:
-- endpoint key
-- headers
-- raw body
-- parsed body if applicable
-- request id
+- 端点键
+- 请求头
+- 原始请求体
+- 已解析的请求体(如适用)
+- 请求 ID
### 13.8 `getData`
-Returns plugin data requested by the plugin's own UI components.
+返回插件自身 UI 组件所请求的插件数据。
-The plugin UI calls the host bridge, which forwards the request to the worker. The worker returns typed JSON that the plugin's own frontend components render.
+插件 UI 调用主机 bridge,bridge 将请求转发给 worker。worker 返回类型化 JSON,由插件自身的前端组件渲染。
-Input includes:
+输入包括:
-- data key (plugin-defined, e.g. `"sync-health"`, `"issue-detail"`)
-- context (company id, project id, entity id, etc.)
-- optional query parameters
+- 数据键(插件定义,例如 `"sync-health"`、`"issue-detail"`)
+- 上下文(公司 ID、项目 ID、实体 ID 等)
+- 可选的查询参数
### 13.9 `performAction`
-Runs an explicit plugin action initiated by the board UI.
+运行由看板 UI 发起的显式插件动作。
-Examples:
+示例:
-- "resync now"
-- "link GitHub issue"
-- "create branch from issue"
-- "restart process"
+- "立即重新同步"
+- "关联 GitHub Issue"
+- "从 Issue 创建分支"
+- "重启进程"
### 13.10 `executeTool`
-Runs a plugin-contributed agent tool during a run.
+在运行期间执行插件贡献的 Agent 工具。
-The host provides:
+主机提供:
-- tool name (without plugin namespace prefix)
-- parsed parameters matching the tool's declared schema
-- run context: agent ID, run ID, company ID, project ID
+- 工具名称(不含插件命名空间前缀)
+- 与工具声明 schema 匹配的已解析参数
+- 运行上下文:Agent ID、运行 ID、公司 ID、项目 ID
-The worker executes the tool and returns a typed result (string content, structured data, or error).
+worker 执行工具并返回类型化结果(字符串内容、结构化数据或错误)。
-## 14. SDK Surface
+## 14. SDK 界面
-Plugins do not talk to the DB directly.
-Plugins do not read raw secret material from persisted config.
+插件不直接与数据库通信。
+插件不从持久化配置中读取原始密钥材料。
-The SDK exposed to workers must provide typed host clients.
+暴露给 worker 的 SDK 必须提供类型化的主机客户端。
-Required SDK clients:
+必须提供的 SDK 客户端:
- `ctx.config`
- `ctx.events`
@@ -620,11 +620,11 @@ Required SDK clients:
- `ctx.tools`
- `ctx.logger`
-`ctx.data` and `ctx.actions` register handlers that the plugin's own UI calls through the host bridge. `ctx.data.register(key, handler)` backs `usePluginData(key)` on the frontend. `ctx.actions.register(key, handler)` backs `usePluginAction(key)`.
+`ctx.data` 和 `ctx.actions` 注册处理器,供插件自身的 UI 通过主机 bridge 调用。`ctx.data.register(key, handler)` 支持前端的 `usePluginData(key)`。`ctx.actions.register(key, handler)` 支持 `usePluginAction(key)`。
-Plugins that need filesystem, git, terminal, or process operations handle those directly using standard Node APIs or libraries. The host provides project workspace metadata through `ctx.projects` so plugins can resolve workspace paths, but the host does not proxy low-level OS operations.
+需要文件系统、git、终端或进程操作的插件使用标准 Node API 或库直接处理这些操作。主机通过 `ctx.projects` 提供项目工作区元数据,使插件可以解析工作区路径,但主机不代理底层 OS 操作。
-## 14.1 Example SDK Shape
+## 14.1 示例 SDK 结构
```ts
/** Top-level helper for defining a plugin with type checking */
@@ -680,16 +680,16 @@ export interface EventFilter {
}
```
-## 15. Capability Model
+## 15. 能力模型
-Capabilities are mandatory and static.
-Every plugin declares them up front.
+能力是强制性且静态的。
+每个插件必须预先声明它们。
-The host enforces capabilities in the SDK layer and refuses calls outside the granted set.
+主机在 SDK 层执行能力管控,并拒绝超出授权集合的调用。
-## 15.1 Capability Categories
+## 15.1 能力类别
-### Data Read
+### 数据读取
- `companies.read`
- `projects.read`
@@ -701,7 +701,7 @@ The host enforces capabilities in the SDK layer and refuses calls outside the gr
- `activity.read`
- `costs.read`
-### Data Write
+### 数据写入
- `issues.create`
- `issues.update`
@@ -711,12 +711,12 @@ The host enforces capabilities in the SDK layer and refuses calls outside the gr
- `activity.log.write`
- `metrics.write`
-### Plugin State
+### 插件状态
- `plugin.state.read`
- `plugin.state.write`
-### Runtime / Integration
+### 运行时 / 集成
- `events.subscribe`
- `events.emit`
@@ -725,7 +725,7 @@ The host enforces capabilities in the SDK layer and refuses calls outside the gr
- `http.outbound`
- `secrets.read-ref`
-### Agent Tools
+### Agent 工具
- `agent.tools.register`
@@ -738,29 +738,29 @@ The host enforces capabilities in the SDK layer and refuses calls outside the gr
- `ui.dashboardWidget.register`
- `ui.action.register`
-## 15.2 Forbidden Capabilities
+## 15.2 禁止的能力
-The host must not expose capabilities for:
+主机不得暴露以下能力:
-- approval decisions
-- budget override
-- auth bypass
-- issue checkout lock override
-- direct DB access
+- 审批决策
+- 预算覆盖
+- 认证绕过
+- 问题签出锁覆盖
+- 直接数据库访问
-## 15.3 Upgrade Rules
+## 15.3 升级规则
-If a plugin upgrade adds capabilities:
+如果插件升级添加了能力:
-1. the host must mark the plugin `upgrade_pending`
-2. the operator must explicitly approve the new capability set
-3. the new version does not become `ready` until approval completes
+1. 主机必须将插件标记为 `upgrade_pending`
+2. 运营者必须明确批准新的能力集合
+3. 在批准完成之前,新版本不会进入 `ready` 状态
-## 16. Event System
+## 16. 事件系统
-The host must emit typed domain events that plugins may subscribe to.
+主机必须发出类型化的领域事件,插件可以订阅这些事件。
-Minimum event set:
+最小事件集:
- `company.created`
- `company.updated`
@@ -784,32 +784,32 @@ Minimum event set:
- `cost_event.created`
- `activity.logged`
-Each event must include:
+每个事件必须包含:
-- event id
-- event type
-- occurred at
-- actor metadata when applicable
-- primary entity metadata
-- typed payload
+- 事件 ID
+- 事件类型
+- 发生时间
+- 适用时的操作者元数据
+- 主要实体元数据
+- 类型化载荷
-### 16.1 Event Filtering
+### 16.1 事件过滤
-Plugins may provide an optional filter when subscribing to events. The filter is evaluated by the host before dispatching to the worker, so filtered-out events never cross the process boundary.
+插件在订阅事件时可提供可选的过滤器。过滤器在分发给 worker 之前由主机评估,因此被过滤掉的事件永远不会跨越进程边界。
-Supported filter fields:
+支持的过滤字段:
-- `projectId` — only receive events for a specific project
-- `companyId` — only receive events for a specific company
-- `agentId` — only receive events for a specific agent
+- `projectId` — 仅接收特定项目的事件
+- `companyId` — 仅接收特定公司的事件
+- `agentId` — 仅接收特定 Agent 的事件
-Filters are optional. If omitted, the plugin receives all events of the subscribed type. Filters may be combined (e.g. filter by both company and project).
+过滤器是可选的。如果省略,插件将接收所订阅类型的所有事件。过滤器可以组合使用(例如同时按公司和项目过滤)。
-### 16.2 Plugin-to-Plugin Events
+### 16.2 插件间事件
-Plugins may emit custom events using `ctx.events.emit(name, payload)`. Plugin-emitted events use a namespaced event type: `plugin..`.
+插件可以使用 `ctx.events.emit(name, payload)` 发出自定义事件。插件发出的事件使用命名空间化的事件类型:`plugin..`。
-Other plugins may subscribe to these events using the same `ctx.events.on()` API:
+其他插件可以使用相同的 `ctx.events.on()` API 订阅这些事件:
```ts
ctx.events.on("plugin.@paperclip/plugin-git.push-detected", async (event) => {
diff --git a/doc/plugins/ideas-from-opencode.md b/doc/plugins/ideas-from-opencode.md
index fcef3c6265..c61d393a5f 100644
--- a/doc/plugins/ideas-from-opencode.md
+++ b/doc/plugins/ideas-from-opencode.md
@@ -1,48 +1,48 @@
-# Plugin Ideas From OpenCode
+# 来自 OpenCode 的插件想法
-Status: design report, not a V1 commitment
+状态:设计报告,非 V1 承诺
-Paperclip V1 explicitly excludes a plugin framework in [doc/SPEC-implementation.md](../SPEC-implementation.md), but the long-horizon spec says the architecture should leave room for extensions. This report studies the `opencode` plugin system and translates the useful patterns into a Paperclip-shaped design.
+Paperclip V1 在 [doc/SPEC-implementation.md](../SPEC-implementation.md) 中明确排除了插件框架,但长期规范指出架构应为扩展留有余地。本报告研究了 `opencode` 的插件系统,并将其有用的模式转化为适合 Paperclip 的设计。
-Assumption for this document: Paperclip is a single-tenant operator-controlled instance. Plugin installation should therefore be global across the instance. "Companies" are still first-class Paperclip objects, but they are organizational records, not tenant-isolation boundaries for plugin trust or installation.
+本文档的假设前提:Paperclip 是单租户、由运营商管控的实例。因此,插件安装应在整个实例范围内全局生效。"Companies" 仍是 Paperclip 的一等公民对象,但它们是组织记录,而非插件信任或安装的租户隔离边界。
-## Executive Summary
+## 执行摘要
-`opencode` has a real plugin system already. It is intentionally low-friction:
+`opencode` 已经拥有一套真实的插件系统,其设计刻意保持低摩擦:
-- plugins are plain JS/TS modules
-- they load from local directories and npm packages
-- they can hook many runtime events
-- they can add custom tools
-- they can extend provider auth flows
-- they run in-process and can mutate runtime behavior directly
+- 插件是普通的 JS/TS 模块
+- 可从本地目录和 npm 包加载
+- 可挂钩许多运行时事件
+- 可添加自定义工具
+- 可扩展提供商的认证流程
+- 在进程内运行,可直接修改运行时行为
-That model works well for a local coding tool. It should not be copied literally into Paperclip.
+该模型非常适合本地编码工具,但不应原样照搬到 Paperclip 中。
-The main conclusion is:
+主要结论:
-- Paperclip should copy `opencode`'s typed SDK, deterministic loading, low authoring friction, and clear extension surfaces.
-- Paperclip should not copy `opencode`'s trust model, project-local plugin loading, "override by name collision" behavior, or arbitrary in-process mutation hooks for core business logic.
-- Paperclip should use multiple extension classes instead of one generic plugin bag:
- - trusted in-process modules for low-level platform concerns like agent adapters, storage providers, secret providers, and possibly run-log backends
- - out-of-process plugins for most third-party integrations like Linear, GitHub Issues, Grafana, Stripe, and schedulers
- - plugin-contributed agent tools (namespaced, not override-by-collision)
- - plugin-shipped React UI loaded into host extension slots via a typed bridge
- - a typed event bus with server-side filtering and plugin-to-plugin events, plus scheduled jobs for automation
+- Paperclip 应借鉴 `opencode` 的类型化 SDK、确定性加载、低创作摩擦以及清晰的扩展接口。
+- Paperclip 不应照搬 `opencode` 的信任模型、项目级本地插件加载、"按名称冲突覆盖"行为,以及针对核心业务逻辑的任意进程内变更挂钩。
+- Paperclip 应使用多种扩展类别,而非一个通用插件包:
+ - 面向底层平台关注点(如 agent 适配器、存储提供商、密钥提供商,以及可能的运行日志后端)的受信任进程内模块
+ - 面向大多数第三方集成(如 Linear、GitHub Issues、Grafana、Stripe 及调度器)的进程外插件
+ - 插件贡献的 agent 工具(带命名空间,不允许覆盖碰撞)
+ - 通过类型化 bridge 加载到宿主扩展槽中的插件提供的 React UI
+ - 带服务端过滤和插件间事件的类型化事件总线,以及用于自动化的定时任务
-If Paperclip does this well, the examples you listed become straightforward:
+如果 Paperclip 能做好这一点,你列举的示例都将变得直接:
-- file browser / terminal / git workflow / child process tracking become workspace plugins that resolve paths from the host and handle OS operations directly
-- Linear / GitHub / Grafana / Stripe become connector plugins
-- future knowledge base and accounting features can also fit the same model
+- 文件浏览器 / 终端 / git 工作流 / 子进程追踪将成为从宿主解析路径、直接处理操作系统操作的工作区插件
+- Linear / GitHub / Grafana / Stripe 将成为连接器插件
+- 未来的知识库和会计功能也可以适配同一模型
-## Sources Examined
+## 参考来源
-I cloned `anomalyco/opencode` and reviewed commit:
+我克隆了 `anomalyco/opencode` 并审查了以下提交:
- `a965a062595403a8e0083e85770315d5dc9628ab`
-Primary files reviewed:
+主要审查的文件:
- `https://github.com/anomalyco/opencode/blob/a965a062595403a8e0083e85770315d5dc9628ab/packages/plugin/src/index.ts`
- `https://github.com/anomalyco/opencode/blob/a965a062595403a8e0083e85770315d5dc9628ab/packages/plugin/src/tool.ts`
@@ -54,7 +54,7 @@ Primary files reviewed:
- `https://github.com/anomalyco/opencode/blob/a965a062595403a8e0083e85770315d5dc9628ab/packages/web/src/content/docs/custom-tools.mdx`
- `https://github.com/anomalyco/opencode/blob/a965a062595403a8e0083e85770315d5dc9628ab/packages/web/src/content/docs/ecosystem.mdx`
-Relevant Paperclip files reviewed for current extension seams:
+审查了以下 Paperclip 相关文件,以了解当前的扩展接缝:
- [server/src/adapters/registry.ts](../../server/src/adapters/registry.ts)
- [ui/src/adapters/registry.ts](../../ui/src/adapters/registry.ts)
@@ -65,537 +65,531 @@ Relevant Paperclip files reviewed for current extension seams:
- [doc/SPEC.md](../SPEC.md)
- [doc/SPEC-implementation.md](../SPEC-implementation.md)
-## What OpenCode Actually Implements
+## OpenCode 实际实现的内容
-## 1. Plugin authoring API
+## 1. 插件创作 API
-`opencode` exposes a small package, `@opencode-ai/plugin`, with a typed `Plugin` function and a typed `tool()` helper.
+`opencode` 暴露了一个小型包 `@opencode-ai/plugin`,提供类型化的 `Plugin` 函数和类型化的 `tool()` 辅助函数。
-Core shape:
+核心结构:
-- a plugin is an async function that receives a context object
-- the plugin returns a `Hooks` object
-- hooks are optional
-- plugins can also contribute tools and auth providers
+- 插件是一个接收上下文对象的异步函数
+- 插件返回一个 `Hooks` 对象
+- 钩子是可选的
+- 插件还可以贡献工具和认证提供商
-The plugin init context includes:
+插件初始化上下文包含:
-- an SDK client
-- current project info
-- current directory
-- current git worktree
-- server URL
-- Bun shell access
+- 一个 SDK 客户端
+- 当前项目信息
+- 当前目录
+- 当前 git worktree
+- 服务器 URL
+- Bun shell 访问权限
-That is important: `opencode` gives plugins rich runtime power immediately, not a narrow capability API.
+这很重要:`opencode` 直接给予插件丰富的运行时能力,而非窄化的能力 API。
-## 2. Hook model
+## 2. 钩子模型
-The hook set is broad. It includes:
+钩子集合范围广泛,包括:
-- event subscription
-- config-time hook
-- message hooks
-- model parameter/header hooks
-- permission decision hooks
-- shell env injection
-- tool execution before/after hooks
-- tool definition mutation
-- compaction prompt customization
-- text completion transforms
+- 事件订阅
+- 配置时钩子
+- 消息钩子
+- 模型参数/请求头钩子
+- 权限决策钩子
+- shell 环境注入
+- 工具执行前后钩子
+- 工具定义变更
+- 压缩提示词自定义
+- 文本补全转换
-The implementation pattern is very simple:
+实现模式非常简单:
-- core code constructs an `output` object
-- each matching plugin hook runs sequentially
-- hooks mutate the `output`
-- final mutated output is used by core
+- 核心代码构造一个 `output` 对象
+- 每个匹配的插件钩子按顺序运行
+- 钩子修改 `output`
+- 最终修改后的输出被核心使用
-This is elegant and easy to extend.
+这种方式优雅且易于扩展。
-It is also extremely powerful. A plugin can change auth headers, model params, permission answers, tool inputs, tool descriptions, and shell environment.
+同时也极为强大。插件可以修改认证请求头、模型参数、权限答案、工具输入、工具描述和 shell 环境。
-## 3. Plugin discovery and load order
+## 3. 插件发现与加载顺序
-`opencode` supports two plugin sources:
+`opencode` 支持两种插件来源:
-- local files
-- npm packages
+- 本地文件
+- npm 包
-Local directories:
+本地目录:
- `~/.config/opencode/plugins/`
- `.opencode/plugins/`
-Npm plugins:
+npm 插件:
-- listed in config under `plugin: []`
+- 在配置中的 `plugin: []` 下列出
-Load order is deterministic and documented:
+加载顺序是确定性的,并有文档说明:
-1. global config
-2. project config
-3. global plugin directory
-4. project plugin directory
+1. 全局配置
+2. 项目配置
+3. 全局插件目录
+4. 项目插件目录
-Important details:
+重要细节:
-- config arrays are concatenated rather than replaced
-- duplicate plugin names are deduplicated with higher-precedence entries winning
-- internal first-party plugins and default plugins are also loaded through the plugin pipeline
+- 配置数组采用拼接而非替换
+- 重复的插件名称会去重,高优先级条目获胜
+- 内部一方插件和默认插件也通过插件管道加载
-This gives `opencode` a real precedence model rather than "whatever loaded last by accident."
+这使 `opencode` 拥有真实的优先级模型,而非"偶然最后加载的获胜"。
-## 4. Dependency handling
+## 4. 依赖处理
-For local config/plugin directories, `opencode` will:
+对于本地配置/插件目录,`opencode` 会:
-- ensure a `package.json` exists
-- inject `@opencode-ai/plugin`
-- run `bun install`
+- 确保存在 `package.json`
+- 注入 `@opencode-ai/plugin`
+- 运行 `bun install`
-That lets local plugins and local custom tools import dependencies.
+这让本地插件和本地自定义工具能够导入依赖项。
-This is excellent for local developer ergonomics.
+这对本地开发者体验而言非常出色。
-It is not a safe default for an operator-controlled control plane server.
+但对于运营商管控的控制面服务器来说,这不是安全的默认值。
-## 5. Error handling
+## 5. 错误处理
-Plugin load failures do not hard-crash the runtime by default.
+插件加载失败默认不会导致运行时崩溃。
-Instead, `opencode`:
+`opencode` 会:
-- logs the error
-- publishes a session error event
-- continues loading other plugins
+- 记录错误
+- 发布会话错误事件
+- 继续加载其他插件
-That is a good operational pattern. One bad plugin should not brick the entire product unless the operator has explicitly configured it as required.
+这是一个良好的运维模式。一个有问题的插件不应让整个产品崩溃,除非运营商明确将其配置为必需项。
-## 6. Tools are a first-class extension point
+## 6. 工具是一等扩展点
-`opencode` has two ways to add tools:
+`opencode` 有两种添加工具的方式:
-- export tools directly from a plugin via `hook.tool`
-- define local files in `.opencode/tools/` or global tools directories
+- 通过 `hook.tool` 直接从插件导出工具
+- 在 `.opencode/tools/` 或全局工具目录中定义本地文件
-The tool API is strong:
+工具 API 功能强大:
-- tools have descriptions
-- tools have Zod schemas
-- tool execution gets context like session ID, message ID, directory, and worktree
-- tools are merged into the same registry as built-in tools
-- tool definitions themselves can be mutated by a `tool.definition` hook
+- 工具有描述信息
+- 工具有 Zod schema
+- 工具执行时可获取会话 ID、消息 ID、目录和 worktree 等上下文
+- 工具与内置工具合并到同一注册表中
+- 工具定义本身可通过 `tool.definition` 钩子进行修改
-The most aggressive part of the design:
+设计中最激进的部分:
-- custom tools can override built-in tools by name
+- 自定义工具可以按名称覆盖内置工具
-That is very powerful for a local coding assistant.
-It is too dangerous for Paperclip core actions.
+这对本地编码助手来说非常强大。
+但对 Paperclip 的核心操作而言过于危险。
-However, the concept of plugins contributing agent-usable tools is very valuable for Paperclip — as long as plugin tools are namespaced (cannot shadow core tools) and capability-gated.
+然而,插件为 agent 贡献可用工具的概念对 Paperclip 而言极具价值——只要插件工具带有命名空间(不能遮蔽核心工具)且受能力限制。
-## 7. Auth is also a plugin surface
+## 7. 认证也是插件接口
-`opencode` allows plugins to register auth methods for providers.
+`opencode` 允许插件为提供商注册认证方法。
-A plugin can contribute:
+插件可以贡献:
-- auth method metadata
-- prompt flows
-- OAuth flows
-- API key flows
-- request loaders that adapt provider behavior after auth succeeds
+- 认证方法元数据
+- 提示流程
+- OAuth 流程
+- API key 流程
+- 在认证成功后调整提供商行为的请求加载器
-This is a strong pattern worth copying. Integrations often need custom auth UX and token handling.
+这是一个值得借鉴的强大模式。集成通常需要自定义的认证 UX 和令牌处理。
-## 8. Ecosystem evidence
+## 8. 生态系统证明
-The ecosystem page is the best proof that the model is working in practice.
-Community plugins already cover:
+生态系统页面是该模型在实践中有效的最佳佐证。
+社区插件已覆盖:
-- sandbox/workspace systems
-- auth providers
-- session headers / telemetry
-- memory/context features
-- scheduling
-- notifications
-- worktree helpers
-- background agents
-- monitoring
+- 沙箱/工作区系统
+- 认证提供商
+- 会话请求头 / 遥测
+- 记忆/上下文功能
+- 调度
+- 通知
+- worktree 辅助工具
+- 后台 agent
+- 监控
-That validates the main thesis: a simple typed plugin API can create real ecosystem velocity.
+这验证了核心论点:一个简单的类型化插件 API 可以创造真正的生态速度。
-## What OpenCode Gets Right
+## OpenCode 做得对的地方
-## 1. Separate plugin SDK from host runtime
+## 1. 将插件 SDK 与宿主运行时分离
-This is one of the best parts of the design.
+这是设计中最出色的部分之一。
-- plugin authors code against a clean public package
-- host internals can evolve behind the loader
-- runtime code and plugin code have a clean contract boundary
+- 插件作者基于一个干净的公共包编码
+- 宿主内部可以在加载器之后独立演进
+- 运行时代码和插件代码之间有清晰的契约边界
-Paperclip should absolutely do this.
+Paperclip 绝对应该这样做。
-## 2. Deterministic loading and precedence
+## 2. 确定性加载和优先级
-`opencode` is explicit about:
+`opencode` 明确规定了:
-- where plugins come from
-- how config merges
-- what order wins
+- 插件来自哪里
+- 配置如何合并
+- 哪个顺序获胜
-Paperclip should copy this discipline.
+Paperclip 应该借鉴这种严谨性。
-## 3. Low-ceremony authoring
+## 3. 低仪式感的创作方式
-A plugin author does not have to learn a giant framework.
+插件作者无需学习一个庞大的框架。
-- export async function
-- return hooks
-- optionally export tools
+- 导出异步函数
+- 返回钩子
+- 可选导出工具
-That simplicity matters.
+这种简洁性至关重要。
-## 4. Typed tool definitions
+## 4. 类型化的工具定义
-The `tool()` helper is excellent:
+`tool()` 辅助函数非常出色:
-- typed
-- schema-based
-- easy to document
-- easy for runtime validation
+- 类型化
+- 基于 schema
+- 易于文档化
+- 便于运行时验证
-Paperclip should adopt this style for plugin actions, automations, and UI schemas.
+Paperclip 应该为插件操作、自动化和 UI schema 采用这种风格。
-## 5. Built-in features and plugins use similar shapes
+## 5. 内置功能与插件使用相似的结构
-`opencode` uses the same hook system for internal and external plugin-style behavior in several places.
-That reduces special cases.
+`opencode` 在多处为内部和外部的插件式行为使用相同的钩子系统。
+这减少了特殊情况。
-Paperclip can benefit from that with adapters, secret backends, storage providers, and connector modules.
+Paperclip 在适配器、密钥后端、存储提供商和连接器模块方面可以从中受益。
-## 6. Incremental extension, not giant abstraction upfront
+## 6. 增量扩展,而非预先设计庞大抽象
-`opencode` did not design a giant marketplace platform first.
-It added concrete extension points that real features needed.
+`opencode` 没有先设计一个庞大的市场平台。
+它是针对真实功能所需的具体扩展点逐步添加的。
-That is the correct mindset for Paperclip too.
+这也是 Paperclip 应有的正确心态。
-## What Paperclip Should Not Copy Directly
+## Paperclip 不应直接照搬的内容
-## 1. In-process arbitrary plugin code as the default
+## 1. 将进程内任意插件代码作为默认方式
-`opencode` is basically a local agent runtime, so unsandboxed plugin execution is acceptable for its audience.
+`opencode` 本质上是一个本地 agent 运行时,因此对其受众而言,无沙箱的插件执行是可以接受的。
-Paperclip is a control plane for an operator-managed instance with company objects.
-The risk profile is different:
+Paperclip 是一个拥有 company 对象、由运营商管理的实例的控制面。
+风险状况有所不同:
-- secrets matter
-- approval gates matter
-- budgets matter
-- mutating actions require auditability
+- 密钥至关重要
+- 审批关卡至关重要
+- 预算至关重要
+- 变更操作需要可审计性
-Default third-party plugins should not run with unrestricted in-process access to server memory, DB handles, and secrets.
+默认的第三方插件不应以不受限制的进程内方式访问服务器内存、数据库句柄和密钥。
-## 2. Project-local plugin loading
+## 2. 项目级本地插件加载
-`opencode` has project-local plugin folders because the tool is centered around a codebase.
+`opencode` 拥有项目级本地插件文件夹,因为该工具以代码库为中心。
-Paperclip is not project-scoped. It is instance-scoped.
-The comparable unit is:
+Paperclip 不是项目范围的,而是实例范围的。
+可对比的单元是:
-- instance-installed plugin package
+- 实例安装的插件包
-Paperclip should not auto-load arbitrary code from a workspace repo like `.paperclip/plugins` or project directories.
+Paperclip 不应从工作区仓库(如 `.paperclip/plugins` 或项目目录)自动加载任意代码。
-## 3. Arbitrary mutation hooks on core business decisions
+## 3. 对核心业务决策的任意变更钩子
-Hooks like:
+以下钩子在 `opencode` 中是合理的:
- `permission.ask`
- `tool.execute.before`
- `chat.headers`
- `shell.env`
-make sense in `opencode`.
+但对于 Paperclip,等价的钩子挂入以下逻辑将是错误的:
-For Paperclip, equivalent hooks into:
+- 审批决策
+- issue 检出语义
+- 活动日志行为
+- 预算执行
-- approval decisions
-- issue checkout semantics
-- activity log behavior
-- budget enforcement
+核心不变量应保留在核心代码中,而不是变成可被钩子重写的内容。
-would be a mistake.
+## 4. 按名称冲突覆盖
-Core invariants should stay in core code, not become hook-rewritable.
+在本地 agent 产品中,允许插件按名称替换内置工具很有用。
-## 4. Override-by-name collision
+Paperclip 不应允许插件静默替换:
-Allowing a plugin to replace a built-in tool by name is useful in a local agent product.
+- 核心路由
+- 核心变更操作
+- 认证行为
+- 权限评估器
+- 预算逻辑
+- 审计逻辑
-Paperclip should not allow plugins to silently replace:
+扩展应是附加的或明确委托的,绝不允许意外遮蔽。
-- core routes
-- core mutating actions
-- auth behaviors
-- permission evaluators
-- budget logic
-- audit logic
+## 5. 从用户配置自动安装并执行
-Extension should be additive or explicitly delegated, never accidental shadowing.
+`opencode` 的"启动时安装依赖"流程很符合人体工程学。
+对于 Paperclip 而言这将带来风险,因为它将以下操作组合在控制面服务器启动路径中:
-## 5. Auto-install and execute from user config
+- 包安装
+- 代码加载
+- 执行
-`opencode`'s "install dependencies at startup" flow is ergonomic.
-For Paperclip it would be risky because it combines:
+Paperclip 应要求一个明确的运营商安装步骤。
-- package installation
-- code loading
-- execution
+## 为什么 Paperclip 需要不同的架构形态
-inside the control-plane server startup path.
+两个产品解决的是不同的问题。
-Paperclip should require an explicit operator install step.
-
-## Why Paperclip Needs A Different Shape
-
-The products are solving different problems.
-
-| Topic | OpenCode | Paperclip |
+| 主题 | OpenCode | Paperclip |
|---|---|---|
-| Primary unit | local project/worktree | single-tenant operator instance with company objects |
-| Trust assumption | local power user on own machine | operator managing one trusted Paperclip instance |
-| Failure blast radius | local session/runtime | entire company control plane |
-| Extension style | mutate runtime behavior freely | preserve governance and auditability |
-| UI model | local app can load local behavior | board UI must stay coherent and safe |
-| Security model | host-trusted local plugins | needs capability boundaries and auditability |
+| 主要单元 | 本地项目/worktree | 带有 company 对象的单租户运营商实例 |
+| 信任假设 | 本机上的本地高级用户 | 管理一个受信任 Paperclip 实例的运营商 |
+| 故障影响范围 | 本地会话/运行时 | 整个公司控制面 |
+| 扩展风格 | 自由修改运行时行为 | 保持治理性和可审计性 |
+| UI 模型 | 本地应用可加载本地行为 | board UI 必须保持连贯和安全 |
+| 安全模型 | 宿主信任的本地插件 | 需要能力边界和可审计性 |
-That means Paperclip should borrow the good ideas from `opencode` but use a stricter architecture.
+这意味着 Paperclip 应借鉴 `opencode` 的好想法,但采用更严格的架构。
-## Paperclip Already Has Useful Pre-Plugin Seams
+## Paperclip 已有有用的预插件接缝
-Paperclip has several extension-like seams already:
+Paperclip 已经拥有多个类扩展的接缝:
-- server adapter registry: [server/src/adapters/registry.ts](../../server/src/adapters/registry.ts)
-- UI adapter registry: [ui/src/adapters/registry.ts](../../ui/src/adapters/registry.ts)
-- storage provider registry: [server/src/storage/provider-registry.ts](../../server/src/storage/provider-registry.ts)
-- secret provider registry: [server/src/secrets/provider-registry.ts](../../server/src/secrets/provider-registry.ts)
-- pluggable run-log store seam: [server/src/services/run-log-store.ts](../../server/src/services/run-log-store.ts)
-- activity log and live event emission: [server/src/services/activity-log.ts](../../server/src/services/activity-log.ts)
+- 服务端适配器注册表:[server/src/adapters/registry.ts](../../server/src/adapters/registry.ts)
+- UI 适配器注册表:[ui/src/adapters/registry.ts](../../ui/src/adapters/registry.ts)
+- 存储提供商注册表:[server/src/storage/provider-registry.ts](../../server/src/storage/provider-registry.ts)
+- 密钥提供商注册表:[server/src/secrets/provider-registry.ts](../../server/src/secrets/provider-registry.ts)
+- 可插拔的运行日志存储接缝:[server/src/services/run-log-store.ts](../../server/src/services/run-log-store.ts)
+- 活动日志和实时事件发射:[server/src/services/activity-log.ts](../../server/src/services/activity-log.ts)
-This is good news.
-Paperclip does not need to invent extensibility from scratch.
-It needs to unify and harden existing seams.
+这是个好消息。
+Paperclip 不需要从零发明可扩展性。
+它需要统一并加固现有的接缝。
-## Recommended Paperclip Plugin Model
+## 推荐的 Paperclip 插件模型
-## 1. Use multiple extension classes
+## 1. 使用多种扩展类别
-Do not create one giant `hooks` object for everything.
+不要为所有事物创建一个庞大的 `hooks` 对象。
-Use distinct plugin classes with different trust models.
+使用具有不同信任模型的独立插件类别。
-| Extension class | Examples | Runtime model | Trust level | Why |
+| 扩展类别 | 示例 | 运行时模型 | 信任级别 | 原因 |
|---|---|---|---|---|
-| Platform module | agent adapters, storage providers, secret providers, run-log backends | in-process | highly trusted | tight integration, performance, low-level APIs |
-| Connector plugin | Linear, GitHub Issues, Grafana, Stripe | out-of-process worker or sidecar | medium | external sync, safer isolation, clearer failure boundary |
-| Workspace plugin | file browser, terminal, git workflow, child process/server tracking | out-of-process, direct OS access | medium | resolves workspace paths from host, owns filesystem/git/PTY/process logic directly |
-| UI contribution | dashboard widgets, settings forms, company panels | plugin-shipped React bundles in host extension slots via bridge | medium | plugins own their rendering; host controls slot placement and bridge access |
-| Automation plugin | alerts, schedulers, sync jobs, webhook processors | out-of-process | medium | event-driven automation is a natural plugin fit |
+| 平台模块 | agent 适配器、存储提供商、密钥提供商、运行日志后端 | 进程内 | 高度信任 | 紧密集成、性能、底层 API |
+| 连接器插件 | Linear、GitHub Issues、Grafana、Stripe | 进程外工作进程或 sidecar | 中等 | 外部同步、更安全的隔离、更清晰的故障边界 |
+| 工作区插件 | 文件浏览器、终端、git 工作流、子进程/服务器追踪 | 进程外,直接操作系统访问 | 中等 | 从宿主解析工作区路径,直接拥有文件系统/git/PTY/进程逻辑 |
+| UI 贡献 | 仪表板小部件、设置表单、company 面板 | 插件提供的 React bundle,通过 bridge 挂载到宿主扩展槽中 | 中等 | 插件拥有其渲染;宿主控制槽位和 bridge 访问 |
+| 自动化插件 | 告警、调度器、同步任务、webhook 处理器 | 进程外 | 中等 | 事件驱动的自动化是插件的天然场景 |
-This split is the most important design recommendation in this report.
+这种划分是本报告中最重要的设计建议。
-## 2. Keep low-level modules separate from third-party plugins
+## 2. 将底层模块与第三方插件分开
-Paperclip already has this pattern implicitly:
+Paperclip 已隐式具备这种模式:
-- adapters are one thing
-- storage providers are another
-- secret providers are another
+- 适配器是一类
+- 存储提供商是另一类
+- 密钥提供商是再另一类
-Keep that separation.
+保持这种分离。
-I would formalize it like this:
+我建议将其正式化如下:
-- `module` means trusted code loaded by the host for low-level runtime services
-- `plugin` means integration code that talks to Paperclip through a typed plugin protocol and capability model
+- `module` 指由宿主为底层运行时服务加载的受信任代码
+- `plugin` 指通过类型化插件协议和能力模型与 Paperclip 通信的集成代码
-This avoids trying to force Stripe, a PTY terminal, and a new agent adapter into the same abstraction.
+这避免了将 Stripe、PTY 终端和新的 agent 适配器强行放入同一抽象的尴尬。
-## 3. Prefer event-driven extensions over core-logic mutation
+## 3. 优先使用事件驱动扩展,而非核心逻辑变更
-For third-party plugins, the primary API should be:
+对于第三方插件,主要 API 应为:
-- subscribe to typed domain events (with optional server-side filtering)
-- emit plugin-namespaced events for cross-plugin communication
-- read instance state, including company-bound business records when relevant
-- register webhooks
-- run scheduled jobs
-- contribute tools that agents can use during runs
-- write plugin-owned state
-- add additive UI surfaces
-- invoke explicit Paperclip actions through the API
+- 订阅类型化领域事件(可选服务端过滤)
+- 发射插件命名空间事件以实现跨插件通信
+- 读取实例状态,包括相关时的 company 绑定业务记录
+- 注册 webhook
+- 运行定时任务
+- 贡献 agent 在运行期间可使用的工具
+- 写入插件自有状态
+- 添加附加的 UI 界面
+- 通过 API 调用明确的 Paperclip 操作
-Do not make third-party plugins responsible for:
+不要让第三方插件负责:
-- deciding whether an approval passes
-- intercepting issue checkout semantics
-- rewriting activity log behavior
-- overriding budget hard-stops
+- 决定审批是否通过
+- 拦截 issue 检出语义
+- 重写活动日志行为
+- 覆盖预算硬限制
-Those are core invariants.
+这些是核心不变量。
-## 4. Plugins ship their own UI
+## 4. 插件提供自有 UI
-Plugins ship their own React UI as a bundled module inside `dist/ui/`. The host loads plugin components into designated **extension slots** (pages, tabs, widgets, sidebar entries) and provides a **bridge** for the plugin frontend to talk to its own worker backend and to access host context.
+插件将自己的 React UI 作为 `dist/ui/` 中的捆绑模块提供。宿主将插件组件加载到指定的**扩展槽**(页面、标签页、小部件、侧边栏条目)中,并提供一个 **bridge**,让插件前端可与其自身的工作进程后端通信并访问宿主上下文。
-**How it works:**
+**工作原理:**
-1. The plugin's UI exports named components for each slot it fills (e.g. `DashboardWidget`, `IssueDetailTab`, `SettingsPage`).
-2. The host mounts the plugin component into the correct slot, passing a bridge object with hooks like `usePluginData(key, params)` and `usePluginAction(key)`.
-3. The plugin component fetches data from its own worker via the bridge and renders it however it wants.
-4. The host enforces capability gates through the bridge — if the worker doesn't have a capability, the bridge rejects the call.
+1. 插件 UI 为其填充的每个槽位导出具名组件(例如 `DashboardWidget`、`IssueDetailTab`、`SettingsPage`)。
+2. 宿主将插件组件挂载到正确的槽位,传递带有 `usePluginData(key, params)` 和 `usePluginAction(key)` 等钩子的 bridge 对象。
+3. 插件组件通过 bridge 从其自身的工作进程获取数据并按自己的方式渲染。
+4. 宿主通过 bridge 执行能力门控——如果工作进程没有某项能力,bridge 将拒绝该调用。
-**What the host controls:** where plugin components appear, the bridge API, capability enforcement, and shared UI primitives (`@paperclipai/plugin-sdk/ui`) with design tokens and common components.
+**宿主控制的内容:** 插件组件的显示位置、bridge API、能力执行,以及带设计令牌和通用组件的共享 UI 原语(`@paperclipai/plugin-sdk/ui`)。
-**What the plugin controls:** how to render its data, what data to fetch, what actions to expose, and whether to use the host's shared components or build entirely custom UI.
+**插件控制的内容:** 如何渲染其数据、获取哪些数据、暴露哪些操作,以及是否使用宿主的共享组件或完全自定义 UI。
-First version extension slots:
+第一版扩展槽:
-- dashboard widgets
-- settings pages
-- detail-page tabs (project, issue, agent, goal, run)
-- sidebar entries
-- company-context plugin pages
+- 仪表板小部件
+- 设置页面
+- 详情页标签页(project、issue、agent、goal、run)
+- 侧边栏条目
+- company 上下文插件页面
-The host SDK ships shared components (MetricCard, DataTable, StatusBadge, LogView, etc.) for visual consistency, but these are optional.
+宿主 SDK 提供共享组件(MetricCard、DataTable、StatusBadge、LogView 等)以保持视觉一致性,但这些是可选的。
-Later, if untrusted third-party plugins become common, the host can move to iframe-based isolation without changing the plugin's source code (the bridge API stays the same).
+以后若不受信任的第三方插件变得普遍,宿主可以迁移到基于 iframe 的隔离,而无需更改插件源代码(bridge API 保持不变)。
-## 5. Make installation global and keep mappings/config separate
+## 5. 使安装全局化,并将映射/配置分开存储
-`opencode` is mostly user-level local config.
-Paperclip should treat plugin installation as a global instance-level action.
+`opencode` 主要是用户级本地配置。
+Paperclip 应将插件安装视为全局实例级操作。
-Examples:
+示例:
-- install `@paperclip/plugin-linear` once
-- make it available everywhere immediately
-- optionally store mappings over Paperclip objects if one company maps to a different Linear team than another
+- 安装一次 `@paperclip/plugin-linear`
+- 立即在所有地方可用
+- 可选地在 Paperclip 对象上存储映射,如果一个 company 映射到与另一个 company 不同的 Linear team
-## 6. Use project workspaces as the primary anchor for local tooling
+## 6. 以项目工作区作为本地工具的主要锚点
-Paperclip already has a concrete workspace model for projects:
+Paperclip 已经为项目提供了具体的工作区模型:
-- projects expose `workspaces` and `primaryWorkspace`
-- the database already has `project_workspaces`
-- project routes already support creating, updating, and deleting workspaces
-- heartbeat resolution already prefers project workspaces before falling back to task-session or agent-home workspaces
+- 项目暴露 `workspaces` 和 `primaryWorkspace`
+- 数据库中已有 `project_workspaces`
+- 项目路由已支持创建、更新和删除工作区
+- 心跳解析已优先选择项目工作区,然后才回退到任务会话或 agent 主目录工作区
-That means local/runtime plugins should generally anchor themselves to projects first, not invent a parallel workspace model.
+这意味着本地/运行时插件通常应首先锚定到项目,而不是发明一个并行的工作区模型。
-Practical guidance:
+实践指导:
-- file browser should browse project workspaces first
-- terminal sessions should be launchable from a project workspace
-- git should treat the project workspace as the repo root anchor
-- dev server and child-process tracking should attach to project workspaces
-- issue and agent views can still deep-link into the relevant project workspace context
+- 文件浏览器应首先浏览项目工作区
+- 终端会话应可从项目工作区启动
+- git 应将项目工作区视为仓库根目录的锚点
+- 开发服务器和子进程追踪应附加到项目工作区
+- issue 和 agent 视图仍可深度链接到相关的项目工作区上下文
-In other words:
+换句话说:
-- `project` is the business object
-- `project_workspace` is the local runtime anchor
-- plugins should build on that instead of creating an unrelated workspace model first
+- `project` 是业务对象
+- `project_workspace` 是本地运行时锚点
+- 插件应基于此构建,而不是首先创建一个无关的工作区模型
-## 7. Let plugins contribute agent tools
+## 7. 让插件贡献 agent 工具
-`opencode` makes tools a first-class extension point. This is one of the highest-value surfaces for Paperclip too.
+`opencode` 将工具视为一等扩展点。对于 Paperclip 而言,这也是价值最高的接口之一。
-A Linear plugin should be able to contribute a `search-linear-issues` tool that agents use during runs. A git plugin should contribute `create-branch` and `get-diff`. A file browser plugin should contribute `read-file` and `list-directory`.
+Linear 插件应能贡献一个 `search-linear-issues` 工具供 agent 在运行期间使用。git 插件应贡献 `create-branch` 和 `get-diff`。文件浏览器插件应贡献 `read-file` 和 `list-directory`。
-The key constraints:
+关键约束:
-- plugin tools are namespaced by plugin ID (e.g. `linear:search-issues`) so they cannot shadow core tools
-- plugin tools require the `agent.tools.register` capability
-- tool execution goes through the same worker RPC boundary as everything else
-- tool results appear in run logs
+- 插件工具按插件 ID 命名空间(例如 `linear:search-issues`),因此不能遮蔽核心工具
+- 插件工具需要 `agent.tools.register` 能力
+- 工具执行通过与其他一切相同的工作进程 RPC 边界进行
+- 工具结果出现在运行日志中
-This is a natural fit — the plugin already has the SDK context, the external API credentials, and the domain logic. Wrapping that in a tool definition is minimal additional work for the plugin author.
+这是天然的契合——插件已经拥有 SDK 上下文、外部 API 凭据和领域逻辑。将其包装为工具定义对插件作者来说是最少的额外工作。
-## 8. Support plugin-to-plugin events
+## 8. 支持插件间事件
-Plugins should be able to emit custom events that other plugins can subscribe to. For example, the git plugin detects a push and emits `plugin.@paperclip/plugin-git.push-detected`. The GitHub Issues plugin subscribes to that event and updates PR links.
+插件应能够发射其他插件可以订阅的自定义事件。例如,git 插件检测到推送并发射 `plugin.@paperclip/plugin-git.push-detected`。GitHub Issues 插件订阅该事件并更新 PR 链接。
-This avoids plugins needing to coordinate through shared state or external channels. The host routes plugin events through the same event bus with the same delivery semantics as core events.
+这避免了插件通过共享状态或外部渠道进行协调。宿主通过与核心事件相同的事件总线和相同的交付语义路由插件事件。
-Plugin events use a `plugin..*` namespace so they cannot collide with core events.
+插件事件使用 `plugin..*` 命名空间,因此不会与核心事件冲突。
-## 9. Auto-generate settings UI from config schema
+## 9. 从配置 schema 自动生成设置 UI
-Plugins that declare an `instanceConfigSchema` should get an auto-generated settings form for free. The host renders text inputs, dropdowns, toggles, arrays, and secret-ref pickers directly from the JSON Schema.
+声明了 `instanceConfigSchema` 的插件应免费获得一个自动生成的设置表单。宿主直接从 JSON Schema 渲染文本输入框、下拉框、开关、数组和密钥引用选择器。
-For plugins that need richer settings UX, they can declare a `settingsPage` extension slot and ship a custom React component. Both approaches coexist.
+对于需要更丰富设置 UX 的插件,可以声明 `settingsPage` 扩展槽并提供自定义 React 组件。两种方式可以共存。
-This matters because settings forms are boilerplate that every plugin needs. Auto-generating them from the schema that already exists removes a significant chunk of authoring friction.
+这很重要,因为设置表单是每个插件都需要的样板代码。从已存在的 schema 自动生成它们可以消除相当大的创作摩擦。
-## 10. Design for graceful shutdown and upgrade
+## 10. 为优雅停机和升级进行设计
-The spec should be explicit about what happens when a plugin worker stops — during upgrades, uninstalls, or instance restarts.
+规范应明确规定当插件工作进程停止时会发生什么——在升级、卸载或实例重启期间。
-The recommended policy:
+推荐策略:
-- send `shutdown()` with a configurable deadline (default 10 seconds)
-- SIGTERM after deadline, SIGKILL after 5 more seconds
-- in-flight jobs marked `cancelled`
-- in-flight bridge calls return structured errors to the UI
+- 发送 `shutdown()`,带可配置的截止时间(默认 10 秒)
+- 超过截止时间后发送 SIGTERM,再等 5 秒后发送 SIGKILL
+- 进行中的任务标记为 `cancelled`
+- 进行中的 bridge 调用向 UI 返回结构化错误
-For upgrades specifically: the old worker drains, the new worker starts. If the new version adds capabilities, it enters `upgrade_pending` until the operator approves.
+对于升级特别而言:旧工作进程排空,新工作进程启动。如果新版本添加了能力,它进入 `upgrade_pending` 状态,直到运营商批准。
-## 11. Define uninstall data lifecycle
+## 11. 定义卸载数据生命周期
-When a plugin is uninstalled, its data (`plugin_state`, `plugin_entities`, `plugin_jobs`, etc.) should be retained for a grace period (default 30 days), not immediately deleted. The operator can reinstall within the grace period and recover state, or force-purge via CLI.
+当插件被卸载时,其数据(`plugin_state`、`plugin_entities`、`plugin_jobs` 等)应在宽限期内保留(默认 30 天),而不是立即删除。运营商可以在宽限期内重新安装并恢复状态,或通过 CLI 强制清除。
-This matters because accidental uninstalls should not cause irreversible data loss.
+这很重要,因为意外卸载不应导致不可逆的数据丢失。
-## 12. Invest in plugin observability
+## 12. 投资于插件可观测性
-Plugin logs via `ctx.logger` should be stored and queryable from the plugin settings page. The host should also capture raw `stdout`/`stderr` from the worker process as fallback.
+通过 `ctx.logger` 记录的插件日志应被存储,并可从插件设置页面查询。宿主还应捕获工作进程的原始 `stdout`/`stderr` 作为备用。
-The plugin health dashboard should show: worker status, uptime, recent logs, job success/failure rates, webhook delivery rates, and resource usage. The host should emit internal events (`plugin.health.degraded`, `plugin.worker.crashed`) that other plugins or dashboards can consume.
+插件健康仪表板应显示:工作进程状态、正常运行时间、最近日志、任务成功/失败率、webhook 交付率和资源使用情况。宿主应发射内部事件(`plugin.health.degraded`、`plugin.worker.crashed`),供其他插件或仪表板消费。
-This is critical for operators. Without observability, debugging plugin issues requires SSH access and manual log tailing.
+这对运营商至关重要。没有可观测性,调试插件问题需要 SSH 访问和手动日志追踪。
-## 13. Ship a test harness and starter template
+## 13. 提供测试工具和入门模板
-A `@paperclipai/plugin-test-harness` package should provide a mock host with in-memory stores, synthetic event emission, and `getData`/`performAction`/`executeTool` simulation. Plugin authors should be able to write unit tests without a running Paperclip instance.
+`@paperclipai/plugin-test-harness` 包应提供一个带内存存储、合成事件发射和 `getData`/`performAction`/`executeTool` 模拟的 mock 宿主。插件作者应能在没有运行中的 Paperclip 实例的情况下编写单元测试。
-A `create-paperclip-plugin` CLI should scaffold a working plugin with manifest, worker, UI bundle, test file, and build config.
+`create-paperclip-plugin` CLI 应脚手架一个带 manifest、worker、UI bundle、测试文件和构建配置的可工作插件。
-Low authoring friction was called out as one of `opencode`'s best qualities. The test harness and starter template are how Paperclip achieves the same.
+低创作摩擦被称为 `opencode` 最出色的品质之一。测试工具和入门模板是 Paperclip 实现同等品质的方式。
-## 14. Support hot plugin lifecycle
+## 14. 支持插件热生命周期
-Plugin install, uninstall, upgrade, and config changes should take effect without restarting the Paperclip server. This is critical for developer workflow and operator experience.
+插件安装、卸载、升级和配置更改应在不重启 Paperclip 服务器的情况下生效。这对开发者工作流和运营商体验至关重要。
-The out-of-process worker architecture makes this natural:
+进程外工作进程架构使这变得自然:
-- **Hot install**: spawn a new worker, register its event subscriptions, job schedules, webhook endpoints, and agent tools in live routing tables, load its UI bundle into the extension slot registry.
-- **Hot uninstall**: graceful shutdown of the worker, remove all registrations from routing tables, unmount UI components, start data retention grace period.
-- **Hot upgrade**: shut down old worker, start new worker, atomically swap routing table entries, invalidate UI bundle cache so the frontend loads the updated bundle.
-- **Hot config change**: write new config to `plugin_config`, notify the running worker via IPC (`configChanged`). The worker applies the change without restarting. If it doesn't handle `configChanged`, the host restarts just that worker.
+- **热安装**:启动新工作进程,在实时路由表中注册其事件订阅、任务计划、webhook 端点和 agent 工具,将其 UI bundle 加载到扩展槽注册表中。
+- **热卸载**:工作进程优雅停机,从路由表中删除所有注册,卸载 UI 组件,开始数据保留宽限期。
+- **热升级**:关闭旧工作进程,启动新工作进程,原子地交换路由表条目,使 UI bundle 缓存失效,以便前端加载更新后的 bundle。
+- **热配置更改**:将新配置写入 `plugin_config`,通过 IPC(`configChanged`)通知运行中的工作进程。工作进程在不重启的情况下应用更改。如果它不处理 `configChanged`,宿主只重启该工作进程。
-Frontend cache invalidation uses versioned or content-hashed bundle URLs and a `plugin.ui.updated` event that triggers re-import without a full page reload.
+前端缓存失效使用版本化或内容哈希的 bundle URL 以及触发重新导入而无需整页重载的 `plugin.ui.updated` 事件。
-Each worker process is independent — starting, stopping, or replacing one worker never affects any other plugin or the host itself.
+每个工作进程都是独立的——启动、停止或替换一个工作进程永远不会影响任何其他插件或宿主本身。
-## 15. Define SDK versioning and compatibility
+## 15. 定义 SDK 版本控制和兼容性
-`opencode` does not have a formal SDK versioning story because plugins run in-process and are effectively pinned to the current runtime. Paperclip's out-of-process model means plugins may be built against one SDK version and run on a host that has moved forward. This needs explicit rules.
+`opencode` 没有正式的 SDK 版本控制方案,因为插件在进程内运行,实际上固定在当前运行时。Paperclip 的进程外模型意味着插件可能是针对一个 SDK 版本构建的,但在已向前演进的宿主上运行。这需要明确的规则。
Recommended approach:
diff --git a/doc/spec/agent-runs.md b/doc/spec/agent-runs.md
index f0d0227540..244a5e8e7b 100644
--- a/doc/spec/agent-runs.md
+++ b/doc/spec/agent-runs.md
@@ -1,120 +1,120 @@
-# Agent Runs Subsystem Spec
+# Agent Runs 子系统规格说明
-Status: Draft
-Date: 2026-02-17
-Audience: Product + Engineering
-Scope: Agent execution runtime, adapter protocol, wakeup orchestration, and live status delivery
+状态:草稿
+日期:2026-02-17
+受众:产品 + 工程
+范围:Agent 执行运行时、适配器协议、唤醒编排及实时状态推送
-## 1. Document Role
+## 1. 文档定位
-This spec defines how Paperclip actually runs agents while staying runtime-agnostic.
+本规格说明定义了 Paperclip 如何在保持运行时无关性的前提下实际运行 agents。
-- `doc/SPEC-implementation.md` remains the V1 baseline contract.
-- This document adds concrete subsystem detail for agent execution, including local CLI adapters, runtime state persistence, wakeup scheduling, and browser live updates.
-- If this doc conflicts with current runtime behavior in code, this doc is the target behavior for upcoming implementation.
+- `doc/SPEC-implementation.md` 仍为 V1 基线合约。
+- 本文档为 agent 执行新增了具体的子系统细节,包括本地 CLI 适配器、运行时状态持久化、唤醒调度以及浏览器实时更新。
+- 若本文档与代码中的当前运行时行为存在冲突,以本文档为即将实现的目标行为。
-## 2. Captured Intent (From Request)
+## 2. 意图记录(来自需求)
-The following intentions are explicitly preserved in this spec:
+以下意图在本规格说明中被明确保留:
-1. Paperclip is adapter-agnostic. The key is a protocol, not a specific runtime.
-2. We still need default built-ins to make the system useful immediately.
-3. First two built-ins are `claude-local` and `codex-local`.
-4. Those adapters run local CLIs directly on the host machine, unsandboxed.
-5. Agent config includes working directory and initial/default prompt.
-6. Heartbeats run the configured adapter process, Paperclip manages lifecycle, and on exit Paperclip parses JSON output and updates state.
-7. Session IDs and token usage must be persisted so later heartbeats can resume.
-8. Adapters should support status updates (short message + color) and optional streaming logs.
-9. UI should support prompt template "pills" for variable insertion.
-10. CLI errors must be visible in full (or as much as possible) in the UI.
-11. Status changes must live-update across task and agent views via server push.
-12. Wakeup triggers should be centralized by a heartbeat/wakeup service with at least:
- - timer interval
- - wake on task assignment
- - explicit ping/request
+1. Paperclip 与适配器无关。核心是一套协议,而非特定的运行时。
+2. 仍需提供默认内置项,使系统能立即投入使用。
+3. 前两个内置项为 `claude-local` 和 `codex-local`。
+4. 这些适配器直接在宿主机上运行本地 CLI,无沙盒隔离。
+5. Agent 配置包含工作目录和初始/默认提示词。
+6. Heartbeat 运行已配置的适配器进程,Paperclip 管理其生命周期,进程退出后 Paperclip 解析 JSON 输出并更新状态。
+7. Session ID 和 token 用量必须持久化,以便后续 heartbeat 可以恢复。
+8. 适配器应支持状态更新(短消息 + 颜色)以及可选的流式日志。
+9. UI 应支持提示词模板"pills"用于变量插入。
+10. CLI 错误必须在 UI 中完整显示(或尽可能多地显示)。
+11. 状态变更必须通过服务端推送在任务视图和 agent 视图中实时更新。
+12. 唤醒触发器应由一个 heartbeat/wakeup 服务集中管理,至少支持:
+ - 定时器间隔
+ - 任务分配时唤醒
+ - 显式 ping/请求
-## 3. Goals and Non-Goals
+## 3. 目标与非目标
-### 3.1 Goals
+### 3.1 目标
-1. Define a stable adapter protocol that supports multiple runtimes.
-2. Ship production-usable local adapters for Claude CLI and Codex CLI.
-3. Persist adapter runtime state (session IDs, token/cost usage, last errors).
-4. Centralize wakeup decisions and queueing in one service.
-5. Provide realtime run/task/agent updates to the browser.
-6. Support deployment-specific full-log storage without bloating Postgres.
-7. Preserve company scoping and existing governance invariants.
+1. 定义一套支持多运行时的稳定适配器协议。
+2. 交付可用于生产环境的 Claude CLI 和 Codex CLI 本地适配器。
+3. 持久化适配器运行时状态(session ID、token/费用用量、最近错误)。
+4. 在单一服务中集中管理唤醒决策与队列。
+5. 向浏览器提供运行/任务/agent 的实时更新。
+6. 在不使 Postgres 膨胀的前提下,支持特定部署的完整日志存储。
+7. 保留公司作用域及现有治理不变量。
-### 3.2 Non-Goals (for this subsystem phase)
+### 3.2 非目标(本子系统阶段)
-1. Distributed execution workers across multiple hosts.
-2. Third-party adapter marketplace/plugin SDK.
-3. Perfect cost accounting for providers that do not emit cost.
-4. Long-term log archival strategy beyond basic retention.
+1. 跨多主机的分布式执行 worker。
+2. 第三方适配器市场/插件 SDK。
+3. 对不发出费用数据的 provider 进行完美费用核算。
+4. 超出基本保留期的长期日志归档策略。
-## 4. Baseline and Gaps (As of 2026-02-17)
+## 4. 基线与差距(截至 2026-02-17)
-Current code already has:
+当前代码已具备:
-- `agents` with `adapterType` + `adapterConfig`.
-- `heartbeat_runs` with basic status tracking.
-- in-process `heartbeatService` that invokes `process` and `http`.
-- cancellation endpoints for active runs.
+- 带有 `adapterType` + `adapterConfig` 的 `agents`。
+- 带有基本状态跟踪的 `heartbeat_runs`。
+- 进程内 `heartbeatService`,可调用 `process` 和 `http`。
+- 活跃运行的取消端点。
-Current gaps this spec addresses:
+本规格说明所解决的当前差距:
-1. No persistent per-agent runtime state for session resume.
-2. No queue/wakeup abstraction (invoke is immediate).
-3. No assignment-triggered or timer-triggered centralized wakeups.
-4. No websocket/SSE push path to browser.
-5. No persisted run event timeline or external full-log storage contract.
-6. No typed local adapter contracts for Claude/Codex session and usage extraction.
-7. No prompt-template variable/pill system in agent setup.
-8. No deployment-aware adapter for full run log storage (disk/object store/etc).
+1. 缺少用于 session 恢复的按 agent 持久化运行时状态。
+2. 缺少队列/唤醒抽象(调用为即时触发)。
+3. 缺少分配触发或定时器触发的集中式唤醒。
+4. 缺少向浏览器的 websocket/SSE 推送路径。
+5. 缺少持久化的运行事件时间线或外部完整日志存储合约。
+6. 缺少用于 Claude/Codex session 和用量提取的类型化本地适配器合约。
+7. Agent 设置中缺少提示词模板变量/pill 系统。
+8. 缺少感知部署环境的完整运行日志存储适配器(磁盘/对象存储等)。
-## 5. Architecture Overview
+## 5. 架构概览
-The subsystem introduces six cooperating components:
+该子系统引入六个协同组件:
-1. `Adapter Registry`
- - Maps `adapter_type` to implementation.
- - Exposes capability metadata and config validation.
+1. `Adapter Registry`(适配器注册表)
+ - 将 `adapter_type` 映射到具体实现。
+ - 暴露能力元数据及配置校验。
-2. `Wakeup Coordinator`
- - Single entrypoint for all wakeups (`timer`, `assignment`, `on_demand`, `automation`).
- - Applies dedupe/coalescing and queue rules.
+2. `Wakeup Coordinator`(唤醒协调器)
+ - 所有唤醒的单一入口(`timer`、`assignment`、`on_demand`、`automation`)。
+ - 应用去重/合并与队列规则。
-3. `Run Executor`
- - Claims queued wakeups.
- - Creates `heartbeat_runs`.
- - Spawns/monitors child processes for local adapters.
- - Handles timeout/cancel/graceful kill.
+3. `Run Executor`(运行执行器)
+ - 认领队列中的唤醒请求。
+ - 创建 `heartbeat_runs`。
+ - 为本地适配器派生/监控子进程。
+ - 处理超时/取消/优雅终止。
-4. `Runtime State Store`
- - Persists resumable adapter state per agent.
- - Persists run usage summaries and lightweight run-event timeline.
+4. `Runtime State Store`(运行时状态存储)
+ - 按 agent 持久化可恢复的适配器状态。
+ - 持久化运行用量摘要及轻量运行事件时间线。
-5. `Run Log Store`
- - Persists full stdout/stderr streams via pluggable storage adapter.
- - Returns stable `logRef` for retrieval (local path, object key, or DB reference).
+5. `Run Log Store`(运行日志存储)
+ - 通过可插拔存储适配器持久化完整的 stdout/stderr 流。
+ - 返回用于检索的稳定 `logRef`(本地路径、对象键或 DB 引用)。
-6. `Realtime Event Hub`
- - Publishes run/agent/task updates over websocket.
- - Supports selective subscription by company.
+6. `Realtime Event Hub`(实时事件中心)
+ - 通过 websocket 发布运行/agent/任务更新。
+ - 支持按公司进行选择性订阅。
-Control flow (happy path):
+控制流(正常路径):
-1. Trigger arrives (`timer`, `assignment`, `on_demand`, or `automation`).
-2. Wakeup coordinator enqueues/merges wake request.
-3. Executor claims request, creates run row, marks agent `running`.
-4. Adapter executes, emits status/log/usage events.
-5. Full logs stream to `RunLogStore`; metadata/events are persisted to DB and pushed to websocket subscribers.
-6. Process exits, output parser updates run result + runtime state.
-7. Agent returns to `idle` or `error`; UI updates in real time.
+1. 触发器到达(`timer`、`assignment`、`on_demand` 或 `automation`)。
+2. 唤醒协调器将唤醒请求入队/合并。
+3. 执行器认领请求,创建运行行,将 agent 标记为 `running`。
+4. 适配器执行,发出 status/log/usage 事件。
+5. 完整日志流入 `RunLogStore`;元数据/事件持久化到 DB 并推送至 websocket 订阅者。
+6. 进程退出,输出解析器更新运行结果 + 运行时状态。
+7. Agent 返回 `idle` 或 `error`;UI 实时更新。
-## 6. Agent Run Protocol (Version `agent-run/v1`)
+## 6. Agent 运行协议(版本 `agent-run/v1`)
-This protocol is runtime-agnostic and implemented by all adapters.
+本协议与运行时无关,由所有适配器实现。
```ts
type RunOutcome = "succeeded" | "failed" | "cancelled" | "timed_out";
@@ -177,21 +177,21 @@ interface AgentRunAdapter {
}
```
-### 6.1 Required Behavior
+### 6.1 必要行为
-1. `validateConfig` runs before saving or invoking.
-2. `invoke` must be deterministic for a given config + runtime state + prompt.
-3. Adapter must not mutate DB directly; it returns data via result/events only.
-4. Adapter must emit enough context for errors to be debuggable.
-5. If `invoke` throws, executor records run as `failed` with captured error text.
+1. `validateConfig` 在保存或调用之前运行。
+2. 对于给定的 config + 运行时状态 + 提示词,`invoke` 必须具有确定性。
+3. 适配器不得直接修改 DB;它仅通过 result/events 返回数据。
+4. 适配器必须输出足够的上下文以便错误可调试。
+5. 若 `invoke` 抛出异常,执行器将运行记录为 `failed` 并捕获错误文本。
-### 6.2 Optional Behavior
+### 6.2 可选行为
-Adapters may omit status/log hooks. If omitted, runtime still emits system lifecycle statuses (`queued`, `running`, `finished`).
+适配器可以省略 status/log hooks。若省略,运行时仍会发出系统生命周期状态(`queued`、`running`、`finished`)。
-### 6.3 Run log storage protocol
+### 6.3 运行日志存储协议
-Full run logs are managed by a separate pluggable store (not by the agent adapter).
+完整运行日志由独立的可插拔存储管理(而非由 agent 适配器管理)。
```ts
type RunLogStoreType = "local_file" | "object_store" | "postgres";
@@ -219,30 +219,30 @@ interface RunLogStore {
}
```
-V1 deployment defaults:
+V1 部署默认值:
-1. Dev/local default: `local_file` (write to `data/run-logs/...`).
-2. Cloud/serverless default: `object_store` (S3/R2/GCS compatible).
-3. Optional fallback: `postgres` with strict size caps.
+1. 开发/本地默认:`local_file`(写入 `data/run-logs/...`)。
+2. 云/无服务器默认:`object_store`(兼容 S3/R2/GCS)。
+3. 可选后备:带严格大小限制的 `postgres`。
-### 6.4 Adapter identity and compatibility
+### 6.4 适配器标识与兼容性
-For V1 rollout, adapter identity is explicit:
+V1 发布时,适配器标识为显式:
- `claude_local`
- `codex_local`
-- `process` (generic existing behavior)
-- `http` (generic existing behavior)
+- `process`(通用现有行为)
+- `http`(通用现有行为)
-`claude_local` and `codex_local` are not wrappers around arbitrary `process`; they are typed adapters with known parser/resume semantics.
+`claude_local` 和 `codex_local` 不是对任意 `process` 的包装;它们是具有已知解析器/恢复语义的类型化适配器。
-## 7. Built-in Adapters (Phase 1)
+## 7. 内置适配器(第一阶段)
## 7.1 `claude-local`
-Runs local `claude` CLI directly.
+直接运行本地 `claude` CLI。
-### Config
+### 配置
```json
{
@@ -258,28 +258,28 @@ Runs local `claude` CLI directly.
}
```
-### Invocation
+### 调用方式
-- Base command: `claude --print --output-format json`
-- Resume: add `--resume ` when runtime state has session ID
-- Unsandboxed mode: add `--dangerously-skip-permissions` when enabled
+- 基础命令:`claude --print --output-format json`
+- 恢复:当运行时状态包含 session ID 时添加 `--resume `
+- 非沙盒模式:启用时添加 `--dangerously-skip-permissions`
-### Output parsing
+### 输出解析
-1. Parse stdout JSON object.
-2. Extract `session_id` for resume.
-3. Extract usage fields:
+1. 解析 stdout JSON 对象。
+2. 提取 `session_id` 用于恢复。
+3. 提取用量字段:
- `usage.input_tokens`
- - `usage.cache_read_input_tokens` (if present)
+ - `usage.cache_read_input_tokens`(如存在)
- `usage.output_tokens`
-4. Extract `total_cost_usd` when present.
-5. On non-zero exit: still attempt parse; if parse succeeds keep extracted state and mark run failed unless adapter explicitly reports success.
+4. 存在时提取 `total_cost_usd`。
+5. 非零退出时:仍尝试解析;若解析成功则保留提取的状态,并将运行标记为失败,除非适配器明确报告成功。
## 7.2 `codex-local`
-Runs local `codex` CLI directly.
+直接运行本地 `codex` CLI。
-### Config
+### 配置
```json
{
@@ -295,52 +295,52 @@ Runs local `codex` CLI directly.
}
```
-### Invocation
+### 调用方式
-- Base command: `codex exec --json `
-- Resume form: `codex exec --json resume `
-- Unsandboxed mode: add `--dangerously-bypass-approvals-and-sandbox` when enabled
-- Optional search mode: add `--search`
+- 基础命令:`codex exec --json `
+- 恢复形式:`codex exec --json resume `
+- 非沙盒模式:启用时添加 `--dangerously-bypass-approvals-and-sandbox`
+- 可选搜索模式:添加 `--search`
-### Output parsing
+### 输出解析
-Codex emits JSONL events. Parse line-by-line and extract:
+Codex 输出 JSONL 事件。逐行解析并提取:
1. `thread.started.thread_id` -> session ID
-2. `item.completed` where item type is `agent_message` -> output text
-3. `turn.completed.usage`:
+2. `item.completed`(item 类型为 `agent_message`)-> 输出文本
+3. `turn.completed.usage`:
- `input_tokens`
- `cached_input_tokens`
- `output_tokens`
-Codex JSONL currently may not include cost; store token usage and leave cost null/unknown unless available.
+Codex JSONL 当前可能不包含费用;存储 token 用量,除非有数据否则费用留为 null/未知。
-## 7.3 Common local adapter process handling
+## 7.3 本地适配器通用进程处理
-Both local adapters must:
+两个本地适配器均须:
-1. Use `spawn(command, args, { shell: false, stdio: "pipe" })`.
-2. Capture stdout/stderr in stream chunks and forward to `RunLogStore`.
-3. Maintain rolling stdout/stderr tail excerpts in memory for DB diagnostic fields.
-4. Emit live log events to websocket subscribers (optional to throttle/chunk).
-5. Support graceful cancel: `SIGTERM`, then `SIGKILL` after `graceSec`.
-6. Enforce timeout using adapter `timeoutSec`.
-7. Return exit code + parsed result + diagnostic stderr.
+1. 使用 `spawn(command, args, { shell: false, stdio: "pipe" })`。
+2. 以流块形式捕获 stdout/stderr 并转发至 `RunLogStore`。
+3. 在内存中维护滚动的 stdout/stderr 尾部摘录,用于 DB 诊断字段。
+4. 向 websocket 订阅者发出实时日志事件(可选择节流/分块)。
+5. 支持优雅取消:`SIGTERM`,然后在 `graceSec` 后发送 `SIGKILL`。
+6. 使用适配器 `timeoutSec` 强制执行超时。
+7. 返回退出码 + 解析结果 + 诊断 stderr。
-## 8. Heartbeat and Wakeup Coordinator
+## 8. Heartbeat 与唤醒协调器
-## 8.1 Wakeup sources
+## 8.1 唤醒来源
-Supported sources:
+支持的来源:
-1. `timer`: periodic heartbeat per agent.
-2. `assignment`: issue assigned/reassigned to agent.
-3. `on_demand`: explicit wake request path (board/manual click or API ping).
-4. `automation`: non-interactive wake path (external callback or internal system automation).
+1. `timer`:按 agent 周期性 heartbeat。
+2. `assignment`:issue 被分配/重新分配给 agent。
+3. `on_demand`:显式唤醒请求路径(看板/手动点击或 API ping)。
+4. `automation`:非交互式唤醒路径(外部回调或内部系统自动化)。
-## 8.2 Central API
+## 8.2 中央 API
-All sources call one internal service:
+所有来源调用同一个内部服务:
```ts
enqueueWakeup({
@@ -355,22 +355,22 @@ enqueueWakeup({
})
```
-No source invokes adapters directly.
+所有来源均不直接调用适配器。
-## 8.3 Queue semantics
+## 8.3 队列语义
-1. Max active run per agent remains `1`.
-2. If agent already has `queued`/`running` run:
- - coalesce duplicate wakeups
- - increment `coalescedCount`
- - preserve latest reason/source metadata
-3. Queue is DB-backed for restart safety.
-4. Coordinator uses FIFO by `requested_at`, with optional priority:
+1. 每个 agent 的最大活跃运行数保持为 `1`。
+2. 若 agent 已有 `queued`/`running` 运行:
+ - 合并重复唤醒
+ - 递增 `coalescedCount`
+ - 保留最新的 reason/source 元数据
+3. 队列有 DB 支撑以保证重启安全性。
+4. 协调器按 `requested_at` 使用 FIFO,带可选优先级:
- `on_demand` > `assignment` > `timer`/`automation`
-## 8.4 Agent heartbeat policy fields
+## 8.4 Agent heartbeat 策略字段
-Agent-level control-plane settings (not adapter-specific):
+Agent 级控制平面设置(非适配器专属):
```json
{
@@ -385,43 +385,43 @@ Agent-level control-plane settings (not adapter-specific):
}
```
-Defaults:
+默认值:
- `enabled: true`
-- `intervalSec: null` (no timer until explicitly set) or product default `300` if desired globally
+- `intervalSec: null`(显式设置前无定时器),若全局需要则产品默认为 `300`
- `wakeOnAssignment: true`
- `wakeOnOnDemand: true`
- `wakeOnAutomation: true`
-## 8.5 Trigger integration rules
+## 8.5 触发器集成规则
-1. Timer checks run on server worker interval and enqueue due agents.
-2. Issue assignment mutation enqueues wakeup when assignee changes and target agent has `wakeOnAssignment=true`.
-3. On-demand endpoint enqueues wakeup with `source=on_demand` and `triggerDetail=manual|ping` when `wakeOnOnDemand=true`.
-4. Callback/system automations enqueue wakeup with `source=automation` and `triggerDetail=callback|system` when `wakeOnAutomation=true`.
-5. Paused/terminated agents do not receive new wakeups.
-6. Hard budget-stopped agents do not receive new wakeups.
+1. 定时器检查在服务端 worker 间隔运行,并将到期的 agents 加入队列。
+2. Issue 分配变更时,若目标 agent 的 `wakeOnAssignment=true`,则将唤醒入队。
+3. 按需端点在 `wakeOnOnDemand=true` 时,以 `source=on_demand` 和 `triggerDetail=manual|ping` 将唤醒入队。
+4. 回调/系统自动化在 `wakeOnAutomation=true` 时,以 `source=automation` 和 `triggerDetail=callback|system` 将唤醒入队。
+5. 已暂停/已终止的 agents 不接收新唤醒。
+6. 已因预算强制停止的 agents 不接收新唤醒。
-## 9. Persistence Model
+## 9. 持久化模型
-All tables remain company-scoped.
+所有表均保持公司作用域。
-## 9.0 Changes to `agents`
+## 9.0 对 `agents` 的变更
-1. Extend `adapter_type` domain to include `claude_local` and `codex_local` (alongside existing `process`, `http`).
-2. Keep `adapter_config` as adapter-owned config (CLI flags, cwd, prompt templates, env overrides).
-3. Add `runtime_config` jsonb for control-plane scheduling policy:
- - heartbeat enable/interval
+1. 将 `adapter_type` 域扩展为包含 `claude_local` 和 `codex_local`(与现有的 `process`、`http` 并列)。
+2. 保持 `adapter_config` 作为适配器自有配置(CLI 标志、cwd、提示词模板、env 覆盖)。
+3. 为控制平面调度策略添加 `runtime_config` jsonb:
+ - heartbeat 启用/间隔
- wake-on-assignment
- wake-on-on-demand
- wake-on-automation
- - cooldown
+ - 冷却时间
-This separation keeps adapter config runtime-agnostic while allowing the heartbeat service to apply consistent scheduling logic.
+此分离使适配器配置保持运行时无关性,同时允许 heartbeat 服务应用一致的调度逻辑。
-## 9.1 New table: `agent_runtime_state`
+## 9.1 新表:`agent_runtime_state`
-One row per agent for aggregate runtime counters and legacy compatibility.
+每个 agent 一行,用于聚合运行时计数器和向后兼容。
- `agent_id` uuid pk fk `agents.id`
- `company_id` uuid fk not null
@@ -437,40 +437,40 @@ One row per agent for aggregate runtime counters and legacy compatibility.
- `last_error` text null
- `updated_at` timestamptz not null
-Invariant: exactly one runtime state row per agent.
+不变量:每个 agent 恰好一行运行时状态。
-## 9.1.1 New table: `agent_task_sessions`
+## 9.1.1 新表:`agent_task_sessions`
-One row per `(company_id, agent_id, adapter_type, task_key)` for resumable session state.
+每个 `(company_id, agent_id, adapter_type, task_key)` 一行,用于可恢复的 session 状态。
- `id` uuid pk
- `company_id` uuid fk not null
- `agent_id` uuid fk not null
- `adapter_type` text not null
- `task_key` text not null
-- `session_params_json` jsonb null (adapter-defined shape)
-- `session_display_id` text null (for UI/debug)
+- `session_params_json` jsonb null(适配器定义的结构)
+- `session_display_id` text null(用于 UI/调试)
- `last_run_id` uuid fk `heartbeat_runs.id` null
- `last_error` text null
- `created_at` timestamptz not null
- `updated_at` timestamptz not null
-Invariant: unique `(company_id, agent_id, adapter_type, task_key)`.
+不变量:`(company_id, agent_id, adapter_type, task_key)` 唯一。
-## 9.2 New table: `agent_wakeup_requests`
+## 9.2 新表:`agent_wakeup_requests`
-Queue + audit for wakeups.
+唤醒的队列 + 审计。
- `id` uuid pk
- `company_id` uuid fk not null
- `agent_id` uuid fk not null
-- `source` text not null (`timer|assignment|on_demand|automation`)
-- `trigger_detail` text null (`manual|ping|callback|system`)
+- `source` text not null(`timer|assignment|on_demand|automation`)
+- `trigger_detail` text null(`manual|ping|callback|system`)
- `reason` text null
- `payload` jsonb null
-- `status` text not null (`queued|claimed|coalesced|skipped|completed|failed|cancelled`)
+- `status` text not null(`queued|claimed|coalesced|skipped|completed|failed|cancelled`)
- `coalesced_count` int not null default `0`
-- `requested_by_actor_type` text null (`user|agent|system`)
+- `requested_by_actor_type` text null(`user|agent|system`)
- `requested_by_actor_id` text null
- `idempotency_key` text null
- `run_id` uuid fk `heartbeat_runs.id` null
@@ -479,26 +479,26 @@ Queue + audit for wakeups.
- `finished_at` timestamptz null
- `error` text null
-## 9.3 New table: `heartbeat_run_events`
+## 9.3 新表:`heartbeat_run_events`
-Append-only per-run lightweight event timeline (no full raw log chunks).
+按运行追加的轻量事件时间线(不含完整原始日志块)。
- `id` bigserial pk
- `company_id` uuid fk not null
- `run_id` uuid fk `heartbeat_runs.id` not null
- `agent_id` uuid fk `agents.id` not null
- `seq` int not null
-- `event_type` text not null (`lifecycle|status|usage|error|structured`)
-- `stream` text null (`system|stdout|stderr`) (summarized events only, not full stream chunks)
-- `level` text null (`info|warn|error`)
+- `event_type` text not null(`lifecycle|status|usage|error|structured`)
+- `stream` text null(`system|stdout|stderr`)(仅摘要事件,非完整流块)
+- `level` text null(`info|warn|error`)
- `color` text null
- `message` text null
- `payload` jsonb null
- `created_at` timestamptz not null
-## 9.4 Changes to `heartbeat_runs`
+## 9.4 对 `heartbeat_runs` 的变更
-Add fields required for result and diagnostics:
+添加结果与诊断所需的字段:
- `wakeup_request_id` uuid fk `agent_wakeup_requests.id` null
- `exit_code` int null
@@ -507,8 +507,8 @@ Add fields required for result and diagnostics:
- `result_json` jsonb null
- `session_id_before` text null
- `session_id_after` text null
-- `log_store` text null (`local_file|object_store|postgres`)
-- `log_ref` text null (opaque provider reference; path/key/uri/row id)
+- `log_store` text null(`local_file|object_store|postgres`)
+- `log_ref` text null(不透明 provider 引用;path/key/uri/row id)
- `log_bytes` bigint null
- `log_sha256` text null
- `log_compressed` boolean not null default false
@@ -516,11 +516,11 @@ Add fields required for result and diagnostics:
- `stdout_excerpt` text null
- `error_code` text null
-This keeps per-run diagnostics queryable without storing full logs in Postgres.
+这使得按运行的诊断信息可查询,同时无需在 Postgres 中存储完整日志。
-## 9.5 Log storage adapter configuration
+## 9.5 日志存储适配器配置
-Runtime log storage is deployment-configured (not per-agent by default).
+运行时日志存储由部署配置(默认非按 agent)。
```json
{
@@ -535,21 +535,21 @@ Runtime log storage is deployment-configured (not per-agent by default).
}
```
-Rules:
+规则:
-1. `log_ref` must be opaque and provider-neutral at API boundaries.
-2. UI/API must not assume local filesystem semantics.
-3. Provider-specific secrets/credentials stay in server config, never in agent config.
+1. 在 API 边界处,`log_ref` 必须是不透明且 provider 中立的。
+2. UI/API 不得假设本地文件系统语义。
+3. Provider 专属的密钥/凭据保留在服务端配置中,绝不放入 agent 配置。
-## 10. Prompt Template and Pill System
+## 10. 提示词模板与 Pill 系统
-## 10.1 Template format
+## 10.1 模板格式
-- Mustache-style placeholders: `{{path.to.value}}`
-- No arbitrary code execution.
-- Unknown variable on save = validation error.
+- Mustache 风格占位符:`{{path.to.value}}`
+- 不允许任意代码执行。
+- 保存时遇到未知变量 = 校验错误。
-## 10.2 Initial variable catalog
+## 10.2 初始变量目录
- `company.id`
- `company.name`
@@ -561,37 +561,37 @@ Rules:
- `run.source`
- `run.startedAt`
- `heartbeat.reason`
-- `paperclip.skill` (shared Paperclip skill text block)
+- `paperclip.skill`(共享的 Paperclip skill 文本块)
- `credentials.apiBaseUrl`
-- `credentials.apiKey` (optional, sensitive)
+- `credentials.apiKey`(可选,敏感)
-## 10.3 Prompt fields
+## 10.3 提示词字段
1. `promptTemplate`
- - Used on every wakeup (first run and resumed runs).
- - Can include run source/reason pills.
+ - 每次唤醒时使用(首次运行及恢复运行)。
+ - 可包含运行来源/原因 pills。
-## 10.4 UI requirements
+## 10.4 UI 要求
-1. Agent setup/edit form includes prompt editors with pill insertion.
-2. Variables are shown as clickable pills for fast insertion.
-3. Save-time validation indicates unknown/missing variables.
-4. Sensitive pills (`credentials.*`) show explicit warning badge.
+1. Agent 设置/编辑表单包含带 pill 插入功能的提示词编辑器。
+2. 变量显示为可点击的 pills 以便快速插入。
+3. 保存时校验提示未知/缺失的变量。
+4. 敏感 pills(`credentials.*`)显示明确的警告徽章。
-## 10.5 Security notes for credentials
+## 10.5 凭据安全说明
-1. Credentials in prompt are allowed for initial simplicity but discouraged.
-2. Preferred transport is env vars (`PAPERCLIP_*`) injected at runtime.
-3. Prompt preview and logs must redact sensitive values.
+1. 提示词中包含凭据在初期为方便而允许,但不建议使用。
+2. 首选传输方式是在运行时注入的 env vars(`PAPERCLIP_*`)。
+3. 提示词预览和日志必须对敏感值进行脱敏处理。
-## 11. Realtime Status Delivery
+## 11. 实时状态推送
-## 11.1 Transport
+## 11.1 传输方式
-Primary transport: websocket channel per company.
+主要传输方式:按公司的 websocket 通道。
-- Endpoint: `GET /api/companies/:companyId/events/ws`
-- Auth: board session or agent API key (company-bound)
+- 端点:`GET /api/companies/:companyId/events/ws`
+- 认证:看板 session 或 agent API key(公司绑定)
## 11.2 Event envelope
@@ -607,28 +607,28 @@ Primary transport: websocket channel per company.
}
```
-## 11.3 Required event types
+## 11.3 必需的事件类型
1. `agent.status.changed`
2. `heartbeat.run.queued`
3. `heartbeat.run.started`
-4. `heartbeat.run.status` (short color+message updates)
-5. `heartbeat.run.log` (optional live chunk stream; full persistence handled by `RunLogStore`)
+4. `heartbeat.run.status`(短颜色+消息更新)
+5. `heartbeat.run.log`(可选的实时块流;完整持久化由 `RunLogStore` 处理)
6. `heartbeat.run.finished`
7. `issue.updated`
8. `issue.comment.created`
9. `activity.appended`
-## 11.4 UI behavior
+## 11.4 UI 行为
-1. Agent detail view updates run timeline live.
-2. Task board reflects assignment/status/comment changes from agent activity without refresh.
-3. Org/agent list reflects status changes live.
-4. If websocket disconnects, client falls back to short polling until reconnect.
+1. Agent 详情视图实时更新运行时间线。
+2. 任务看板无需刷新即可反映来自 agent 活动的分配/状态/评论变更。
+3. 组织/agent 列表实时反映状态变更。
+4. 若 websocket 断开,客户端回退到短轮询直到重新连接。
-## 12. Error Handling and Diagnostics
+## 12. 错误处理与诊断
-## 12.1 Error classes
+## 12.1 错误类型
- `adapter_not_installed`
- `invalid_working_directory`
@@ -640,54 +640,54 @@ Primary transport: websocket channel per company.
- `resume_session_invalid`
- `budget_blocked`
-## 12.2 Logging requirements
+## 12.2 日志记录要求
-1. Persist full stdout/stderr stream to configured `RunLogStore`.
-2. Persist only lightweight run metadata/events in Postgres (`heartbeat_runs`, `heartbeat_run_events`).
-3. Persist bounded `stdout_excerpt` and `stderr_excerpt` in Postgres for quick diagnostics.
-4. Mark truncation explicitly when excerpts are capped.
-5. Redact secrets from logs, excerpts, and websocket payloads.
+1. 将完整的 stdout/stderr 流持久化到已配置的 `RunLogStore`。
+2. 仅将轻量运行元数据/事件持久化到 Postgres(`heartbeat_runs`、`heartbeat_run_events`)。
+3. 将有界的 `stdout_excerpt` 和 `stderr_excerpt` 持久化到 Postgres 以便快速诊断。
+4. 摘录被截断时明确标记。
+5. 从日志、摘录和 websocket 负载中脱敏密钥。
-## 12.3 Log retention and lifecycle
+## 12.3 日志保留与生命周期
-1. `RunLogStore` retention is configurable by deployment (for example 7/30/90 days).
-2. Postgres run metadata can outlive full log objects.
-3. Deletion/pruning jobs must handle orphaned metadata/log-object references safely.
-4. If full log object is gone, APIs still return metadata and excerpts with `log_unavailable` status.
+1. `RunLogStore` 保留期可按部署配置(例如 7/30/90 天)。
+2. Postgres 运行元数据可在完整日志对象之后继续存在。
+3. 删除/清理任务必须安全处理孤立的元数据/日志对象引用。
+4. 若完整日志对象已删除,API 仍返回元数据和摘录,状态为 `log_unavailable`。
-## 12.4 Restart recovery
+## 12.4 重启恢复
-On server startup:
+服务端启动时:
-1. Find stale `queued`/`running` runs.
-2. Mark as `failed` with `error_code=control_plane_restart`.
-3. Set affected non-paused/non-terminated agents to `error` (or `idle` based on policy).
-4. Emit recovery events to websocket and activity log.
+1. 查找过期的 `queued`/`running` 运行。
+2. 以 `error_code=control_plane_restart` 标记为 `failed`。
+3. 将受影响的非暂停/非终止 agents 设置为 `error`(或按策略为 `idle`)。
+4. 向 websocket 和活动日志发出恢复事件。
-## 13. API Surface Changes
+## 13. API 接口变更
-## 13.1 New/updated endpoints
+## 13.1 新增/更新端点
1. `POST /agents/:agentId/wakeup`
- - enqueue wakeup with source/reason
+ - 以 source/reason 将唤醒入队
2. `POST /agents/:agentId/heartbeat/invoke`
- - backward-compatible alias to wakeup API
+ - 向唤醒 API 的向后兼容别名
3. `GET /agents/:agentId/runtime-state`
- - board-only debug view
+ - 仅看板可访问的调试视图
4. `GET /agents/:agentId/task-sessions`
- - board-only list of task-scoped adapter sessions
+ - 仅看板可访问的任务范围适配器 session 列表
5. `POST /agents/:agentId/runtime-state/reset-session`
- - clears all task sessions for the agent, or one when `taskKey` is provided
+ - 清除 agent 的所有任务 session,或在提供 `taskKey` 时清除单个
6. `GET /heartbeat-runs/:runId/events?afterSeq=:n`
- - fetch persisted lightweight timeline
+ - 获取已持久化的轻量时间线
7. `GET /heartbeat-runs/:runId/log`
- - reads full log stream via `RunLogStore` (or redirects/presigned URL for object store)
+ - 通过 `RunLogStore` 读取完整日志流(或对象存储的重定向/预签名 URL)
8. `GET /api/companies/:companyId/events/ws`
- - websocket stream
+ - websocket 流
-## 13.2 Mutation logging
+## 13.2 变更日志记录
-All wakeup/run state mutations must create `activity_log` entries:
+所有唤醒/运行状态变更必须创建 `activity_log` 条目:
- `wakeup.requested`
- `wakeup.coalesced`
@@ -697,60 +697,60 @@ All wakeup/run state mutations must create `activity_log` entries:
- `heartbeat.cancelled`
- `runtime_state.updated`
-## 14. Heartbeat Service Implementation Plan
+## 14. Heartbeat 服务实施计划
-## Phase 1: Contracts and schema
+## 第一阶段:合约与 schema
-1. Add new DB tables/columns (`agent_runtime_state`, `agent_wakeup_requests`, `heartbeat_run_events`, `heartbeat_runs.log_*` fields).
-2. Add `RunLogStore` interface and configuration wiring.
-3. Add shared types/constants/validators.
-4. Keep existing routes functional during migration.
+1. 添加新 DB 表/列(`agent_runtime_state`、`agent_wakeup_requests`、`heartbeat_run_events`、`heartbeat_runs.log_*` 字段)。
+2. 添加 `RunLogStore` 接口及配置连接。
+3. 添加共享类型/常量/校验器。
+4. 迁移期间保持现有路由可用。
-## Phase 2: Wakeup coordinator
+## 第二阶段:唤醒协调器
-1. Implement DB-backed wakeup queue.
-2. Convert invoke/wake routes to enqueue with `source=on_demand` and appropriate `triggerDetail`.
-3. Add worker loop to claim and execute queued wakeups.
+1. 实现 DB 支撑的唤醒队列。
+2. 将 invoke/wake 路由转换为以 `source=on_demand` 和相应 `triggerDetail` 入队。
+3. 添加认领并执行排队唤醒的 worker 循环。
-## Phase 3: Local adapters
+## 第三阶段:本地适配器
-1. Implement `claude-local` adapter.
-2. Implement `codex-local` adapter.
-3. Parse and persist session IDs and token usage.
-4. Wire cancel/timeout/grace behavior.
+1. 实现 `claude-local` 适配器。
+2. 实现 `codex-local` 适配器。
+3. 解析并持久化 session ID 和 token 用量。
+4. 连接取消/超时/优雅停止行为。
-## Phase 4: Realtime push
+## 第四阶段:实时推送
-1. Implement company websocket hub.
-2. Publish run/agent/issue events.
-3. Update UI pages to subscribe and invalidate/update relevant data.
+1. 实现公司 websocket hub。
+2. 发布运行/agent/issue 事件。
+3. 更新 UI 页面以订阅并使相关数据失效/更新。
-## Phase 5: Prompt pills and config UX
+## 第五阶段:提示词 pills 与配置 UX
-1. Add adapter-specific config editor with prompt templates.
-2. Add pill insertion and variable validation.
-3. Add sensitive-variable warnings and redaction.
+1. 添加带提示词模板的适配器专属配置编辑器。
+2. 添加 pill 插入和变量校验。
+3. 添加敏感变量警告与脱敏。
-## Phase 6: Hardening
+## 第六阶段:加固
-1. Add failure/restart recovery sweeps.
-2. Add metadata/full-log retention policies and pruning jobs.
-3. Add integration/e2e coverage for wakeup triggers and live updates.
+1. 添加失败/重启恢复扫描。
+2. 添加元数据/完整日志保留策略和清理任务。
+3. 添加对唤醒触发器和实时更新的集成/端到端覆盖。
-## 15. Acceptance Criteria
+## 15. 验收标准
-1. Agent with `claude-local` or `codex-local` can run, exit, and persist run result.
-2. Session parameters are persisted per task scope and reused automatically for same-task resumes.
-3. Token usage is persisted per run and accumulated per agent runtime state.
-4. Timer, assignment, on-demand, and automation wakeups all enqueue through one coordinator.
-5. Pause/terminate interrupts running local process and prevents new wakeups.
-6. Browser receives live websocket updates for run status/logs and task/agent changes.
-7. Failed runs expose rich CLI diagnostics in UI with excerpts immediately available and full log retrievable via `RunLogStore`.
-8. All actions remain company-scoped and auditable.
+1. 带有 `claude-local` 或 `codex-local` 的 agent 可以运行、退出并持久化运行结果。
+2. Session 参数按任务范围持久化,并在同任务恢复时自动复用。
+3. Token 用量按运行持久化,并按 agent 运行时状态累计。
+4. 定时器、分配、按需和自动化唤醒均通过一个协调器入队。
+5. 暂停/终止会中断正在运行的本地进程并阻止新唤醒。
+6. 浏览器接收关于运行状态/日志以及任务/agent 变更的实时 websocket 更新。
+7. 失败的运行在 UI 中暴露丰富的 CLI 诊断信息,摘录可立即获取,完整日志可通过 `RunLogStore` 检索。
+8. 所有操作保持公司作用域且可审计。
-## 16. Open Questions
+## 16. 待解问题
-1. Should timer default be `null` (off until enabled) or `300` seconds by default?
-2. What should the default retention policy be for full log objects vs Postgres metadata?
-3. Should agent API credentials be allowed in prompt templates by default, or require explicit opt-in toggle?
-4. Should websocket be the only realtime channel, or should we also expose SSE for simpler clients?
+1. 定时器默认值应为 `null`(启用前关闭)还是默认 `300` 秒?
+2. 完整日志对象与 Postgres 元数据的默认保留策略应如何?
+3. Agent API 凭据是否默认允许在提示词模板中使用,还是需要显式的选择性启用开关?
+4. Websocket 是否为唯一的实时通道,还是也应为更简单的客户端暴露 SSE?
diff --git a/doc/spec/agents-runtime.md b/doc/spec/agents-runtime.md
index 3efeaee287..900337d301 100644
--- a/doc/spec/agents-runtime.md
+++ b/doc/spec/agents-runtime.md
@@ -1,172 +1,172 @@
-# Agent Runtime Guide
+# 智能体运行时指南
-Status: User-facing guide
-Last updated: 2026-02-17
-Audience: Operators setting up and running agents in Paperclip
+状态:面向用户的指南
+最后更新:2026-02-17
+受众:在 Paperclip 中设置和运行智能体的运维人员
-## 1. What this system does
+## 1. 系统功能概述
-Agents in Paperclip do not run continuously.
-They run in **heartbeats**: short execution windows triggered by a wakeup.
+Paperclip 中的智能体不会持续运行。
+它们以**心跳**方式运行:由唤醒触发的短暂执行窗口。
-Each heartbeat:
+每次心跳:
-1. Starts the configured agent adapter (for example, Claude CLI or Codex CLI)
-2. Gives it the current prompt/context
-3. Lets it work until it exits, times out, or is cancelled
-4. Stores results (status, token usage, errors, logs)
-5. Updates the UI live
+1. 启动配置的智能体适配器(例如 Claude CLI 或 Codex CLI)
+2. 向其提供当前提示词/上下文
+3. 让其工作直到退出、超时或被取消
+4. 存储结果(状态、token 用量、错误、日志)
+5. 实时更新 UI
-## 2. When an agent wakes up
+## 2. 智能体何时被唤醒
-An agent can be woken up in four ways:
+智能体可以通过四种方式被唤醒:
-- `timer`: scheduled interval (for example every 5 minutes)
-- `assignment`: when work is assigned/checked out to that agent
-- `on_demand`: manual wakeup (button/API)
-- `automation`: system-triggered wakeup for future automations
+- `timer`:定时调度(例如每 5 分钟)
+- `assignment`:当工作被分配/签出给该智能体时
+- `on_demand`:手动唤醒(按钮/API)
+- `automation`:系统触发的唤醒,用于未来的自动化
-If an agent is already running, new wakeups are merged (coalesced) instead of launching duplicate runs.
+如果智能体已在运行,新的唤醒请求会被合并(合并去重),而不是启动重复的运行。
-## 3. What to configure per agent
+## 3. 每个智能体需要配置什么
-## 3.1 Adapter choice
+## 3.1 适配器选择
-Common choices:
+常见选择:
-- `claude_local`: runs your local `claude` CLI
-- `codex_local`: runs your local `codex` CLI
-- `process`: generic shell command adapter
-- `http`: calls an external HTTP endpoint
+- `claude_local`:运行本地的 `claude` CLI
+- `codex_local`:运行本地的 `codex` CLI
+- `process`:通用 shell 命令适配器
+- `http`:调用外部 HTTP 端点
-For `claude_local` and `codex_local`, Paperclip assumes the CLI is already installed and authenticated on the host machine.
+对于 `claude_local` 和 `codex_local`,Paperclip 假设 CLI 已在主机上安装并完成认证。
-## 3.2 Runtime behavior
+## 3.2 运行时行为
-In agent runtime settings, configure heartbeat policy:
+在智能体运行时设置中,配置心跳策略:
-- `enabled`: allow scheduled heartbeats
-- `intervalSec`: timer interval (0 = disabled)
-- `wakeOnAssignment`: wake when assigned work
-- `wakeOnOnDemand`: allow ping-style on-demand wakeups
-- `wakeOnAutomation`: allow system automation wakeups
+- `enabled`:允许定时心跳
+- `intervalSec`:定时间隔(0 = 禁用)
+- `wakeOnAssignment`:分配工作时唤醒
+- `wakeOnOnDemand`:允许按需即时唤醒
+- `wakeOnAutomation`:允许系统自动化唤醒
-## 3.3 Working directory and execution limits
+## 3.3 工作目录和执行限制
-For local adapters, set:
+对于本地适配器,设置:
-- `cwd` (working directory)
-- `timeoutSec` (max runtime per heartbeat)
-- `graceSec` (time before force-kill after timeout/cancel)
-- optional env vars and extra CLI args
+- `cwd`(工作目录)
+- `timeoutSec`(每次心跳的最大运行时间)
+- `graceSec`(超时/取消后强制终止前的等待时间)
+- 可选的环境变量和额外 CLI 参数
-## 3.4 Prompt templates
+## 3.4 提示词模板
-You can set:
+可以设置:
-- `promptTemplate`: used for every run (first run and resumed sessions)
+- `promptTemplate`:用于每次运行(首次运行和恢复的会话)
-Templates support variables like `{{agent.id}}`, `{{agent.name}}`, and run context values.
+模板支持 `{{agent.id}}`、`{{agent.name}}` 等变量以及运行上下文值。
-## 4. Session resume behavior
+## 4. 会话恢复行为
-Paperclip stores resumable session state per `(agent, taskKey, adapterType)`.
-`taskKey` is derived from wakeup context (`taskKey`, `taskId`, or `issueId`).
+Paperclip 按 `(agent, taskKey, adapterType)` 存储可恢复的会话状态。
+`taskKey` 从唤醒上下文(`taskKey`、`taskId` 或 `issueId`)派生。
-- A heartbeat for the same task key reuses the previous session for that task.
-- Different task keys for the same agent keep separate session state.
-- If restore fails, adapters should retry once with a fresh session and continue.
-- You can reset all sessions for an agent or reset one task session by task key.
+- 相同任务键的心跳会复用该任务之前的会话。
+- 同一智能体的不同任务键保持独立的会话状态。
+- 如果恢复失败,适配器应使用新会话重试一次并继续。
+- 可以重置智能体的所有会话,或按任务键重置单个任务会话。
-Use session reset when:
+在以下情况使用会话重置:
-- you significantly changed prompt strategy
-- the agent is stuck in a bad loop
-- you want a clean restart
+- 显著更改了提示词策略
+- 智能体陷入了错误循环
+- 需要全新重启
-## 5. Logs, status, and run history
+## 5. 日志、状态和运行历史
-For each heartbeat run you get:
+每次心跳运行都会获得:
-- run status (`queued`, `running`, `succeeded`, `failed`, `timed_out`, `cancelled`)
-- error text and stderr/stdout excerpts
-- token usage/cost when available from the adapter
-- full logs (stored outside core run rows, optimized for large output)
+- 运行状态(`queued`、`running`、`succeeded`、`failed`、`timed_out`、`cancelled`)
+- 错误文本和 stderr/stdout 摘录
+- 适配器提供的 token 用量/成本(如有)
+- 完整日志(存储在核心运行记录之外,针对大量输出进行优化)
-In local/dev setups, full logs are stored on disk under the configured run-log path.
+在本地/开发环境中,完整日志存储在配置的运行日志路径下的磁盘上。
-## 6. Live updates in the UI
+## 6. UI 中的实时更新
-Paperclip pushes runtime/activity updates to the browser in real time.
+Paperclip 将运行时/活动更新实时推送到浏览器。
-You should see live changes for:
+应该能看到以下内容的实时变化:
-- agent status
-- heartbeat run status
-- task/activity updates caused by agent work
-- dashboard/cost/activity panels as relevant
+- 智能体状态
+- 心跳运行状态
+- 智能体工作引起的任务/活动更新
+- 仪表板/成本/活动面板的相关更新
-If the connection drops, the UI reconnects automatically.
+如果连接断开,UI 会自动重连。
-## 7. Common operating patterns
+## 7. 常见运行模式
-## 7.1 Simple autonomous loop
+## 7.1 简单自主循环
-1. Enable timer wakeups (for example every 300s)
-2. Keep assignment wakeups on
-3. Use a focused prompt template
-4. Watch run logs and adjust prompt/config over time
+1. 启用定时唤醒(例如每 300 秒)
+2. 保持分配唤醒开启
+3. 使用聚焦的提示词模板
+4. 观察运行日志并随时间调整提示词/配置
-## 7.2 Event-driven loop (less constant polling)
+## 7.2 事件驱动循环(减少持续轮询)
-1. Disable timer or set a long interval
-2. Keep wake-on-assignment enabled
-3. Use on-demand wakeups for manual nudges
+1. 禁用定时器或设置较长间隔
+2. 保持分配唤醒启用
+3. 使用按需唤醒进行手动触发
-## 7.3 Safety-first loop
+## 7.3 安全优先循环
-1. Short timeout
-2. Conservative prompt
-3. Monitor errors + cancel quickly when needed
-4. Reset sessions when drift appears
+1. 短超时时间
+2. 保守的提示词
+3. 监控错误 + 需要时快速取消
+4. 出现偏差时重置会话
-## 8. Troubleshooting
+## 8. 故障排除
-If runs fail repeatedly:
+如果运行反复失败:
-1. Check adapter command availability (`claude`/`codex` installed and logged in).
-2. Verify `cwd` exists and is accessible.
-3. Inspect run error + stderr excerpt, then full log.
-4. Confirm timeout is not too low.
-5. Reset session and retry.
-6. Pause agent if it is causing repeated bad updates.
+1. 检查适配器命令可用性(`claude`/`codex` 已安装并登录)。
+2. 验证 `cwd` 存在且可访问。
+3. 检查运行错误 + stderr 摘录,然后查看完整日志。
+4. 确认超时时间不会太低。
+5. 重置会话并重试。
+6. 如果智能体持续产生错误更新,暂停智能体。
-Typical failure causes:
+典型失败原因:
-- CLI not installed/authenticated
-- bad working directory
-- malformed adapter args/env
-- prompt too broad or missing constraints
-- process timeout
+- CLI 未安装/未认证
+- 工作目录错误
+- 适配器参数/环境变量格式错误
+- 提示词过于宽泛或缺少约束
+- 进程超时
-## 9. Security and risk notes
+## 9. 安全和风险说明
-Local CLI adapters run unsandboxed on the host machine.
+本地 CLI 适配器在主机上以非沙箱方式运行。
-That means:
+这意味着:
-- prompt instructions matter
-- configured credentials/env vars are sensitive
-- working directory permissions matter
+- 提示词指令很重要
+- 配置的凭据/环境变量是敏感信息
+- 工作目录权限很重要
-Start with least privilege where possible, and avoid exposing secrets in broad reusable prompts unless intentionally required.
+尽可能从最小权限开始,除非有意为之,否则避免在广泛复用的提示词中暴露密钥。
-## 10. Minimal setup checklist
+## 10. 最小化设置清单
-1. Choose adapter (`claude_local` or `codex_local`).
-2. Set `cwd` to the target workspace.
-3. Add bootstrap + normal prompt templates.
-4. Configure heartbeat policy (timer and/or assignment wakeups).
-5. Trigger a manual wakeup.
-6. Confirm run succeeds and session/token usage is recorded.
-7. Watch live updates and iterate prompt/config.
+1. 选择适配器(`claude_local` 或 `codex_local`)。
+2. 将 `cwd` 设置为目标工作区。
+3. 添加引导 + 常规提示词模板。
+4. 配置心跳策略(定时和/或分配唤醒)。
+5. 触发一次手动唤醒。
+6. 确认运行成功且会话/token 用量已记录。
+7. 观察实时更新并迭代提示词/配置。
diff --git a/doc/spec/ui.md b/doc/spec/ui.md
index c2ffdb7c02..eab7b28b7c 100644
--- a/doc/spec/ui.md
+++ b/doc/spec/ui.md
@@ -1,59 +1,59 @@
-# Paperclip UI Spec
+# Paperclip UI 规范
-Status: Draft
-Date: 2026-02-17
+状态:草稿
+日期:2026-02-17
-## 1. Design Philosophy
+## 1. 设计理念
-Paperclip's UI is a professional-grade control plane, not a toy dashboard. It should feel like the kind of tool you live in all day — fast, keyboard-driven, information-dense without being cluttered, dark-themed by default. Every pixel should earn its place.
+Paperclip 的 UI 是专业级控制平面,而非玩具式仪表板。它应该像一种整天都在使用的工具——快速、以键盘驱动、信息密集却不杂乱,默认深色主题。每一个像素都应物尽其用。
-Design principles:
+设计原则:
-- **Dense but scannable.** Show maximum information without requiring clicks to reveal it. Use whitespace to separate, not to pad.
-- **Keyboard-first.** Global shortcuts for search (Cmd+K), new issue (C), navigation. Power users should rarely touch the mouse.
-- **Contextual, not modal.** Inline editing over dialog boxes. Dropdowns over page navigations. The user's mental context should never be broken unnecessarily.
-- **Dark theme default.** Neutral grays, not pure black. Accent colors used sparingly for status and priority. Text is the primary visual element.
+- **密集但易于扫读。** 无需点击即可展示最多信息。使用留白来分隔,而非填充。
+- **键盘优先。** 全局快捷键用于搜索(Cmd+K)、新建 issue(C)、导航。高级用户应极少需要使用鼠标。
+- **情境化,非模态化。** 内联编辑优先于对话框,下拉菜单优先于页面跳转。用户的操作上下文不应被无谓地打断。
+- **默认深色主题。** 中性灰色,而非纯黑色。强调色仅用于状态和优先级。文本是主要视觉元素。
-### Color System
+### 颜色系统
-- **Background:** `hsl(220, 13%, 10%)` (dark charcoal, not pure black)
-- **Surface/Card:** `hsl(220, 13%, 13%)`
-- **Border:** `hsl(220, 10%, 18%)`
-- **Text primary:** `hsl(220, 10%, 90%)`
-- **Text secondary:** `hsl(220, 10%, 55%)`
-- **Accent (interactive):** `hsl(220, 80%, 60%)` (muted blue)
+- **背景色(Background):** `hsl(220, 13%, 10%)`(深炭灰,非纯黑)
+- **表面/卡片(Surface/Card):** `hsl(220, 13%, 13%)`
+- **边框(Border):** `hsl(220, 10%, 18%)`
+- **主文本(Text primary):** `hsl(220, 10%, 90%)`
+- **次要文本(Text secondary):** `hsl(220, 10%, 55%)`
+- **强调色(Accent,可交互):** `hsl(220, 80%, 60%)`(柔和蓝)
-Status colors (consistent across all entities):
-- **Backlog:** gray `hsl(220, 10%, 45%)`
-- **Todo:** gray-blue `hsl(220, 20%, 55%)`
-- **In Progress:** yellow `hsl(45, 90%, 55%)`
-- **In Review:** violet `hsl(270, 60%, 60%)`
-- **Done:** green `hsl(140, 60%, 50%)`
-- **Cancelled:** gray `hsl(220, 10%, 40%)`
-- **Blocked:** amber `hsl(25, 90%, 55%)`
+状态颜色(在所有实体中保持一致):
+- **Backlog(积压):** 灰色 `hsl(220, 10%, 45%)`
+- **Todo(待办):** 灰蓝色 `hsl(220, 20%, 55%)`
+- **In Progress(进行中):** 黄色 `hsl(45, 90%, 55%)`
+- **In Review(审核中):** 紫罗兰色 `hsl(270, 60%, 60%)`
+- **Done(已完成):** 绿色 `hsl(140, 60%, 50%)`
+- **Cancelled(已取消):** 灰色 `hsl(220, 10%, 40%)`
+- **Blocked(被阻塞):** 琥珀色 `hsl(25, 90%, 55%)`
-Priority indicators:
-- **Critical:** red circle, filled
-- **High:** orange circle, half-filled
-- **Medium:** yellow circle, outline
-- **Low:** gray circle, outline, dashed
+优先级指示器:
+- **Critical(紧急):** 红色实心圆
+- **High(高):** 橙色半填充圆
+- **Medium(中):** 黄色空心圆
+- **Low(低):** 灰色虚线空心圆
-### Typography
+### 字体排印
-- **Font:** System font stack (Inter if loaded, else `-apple-system, BlinkMacSystemFont, 'Segoe UI'`)
-- **Body:** 13px / 1.5 line-height
-- **Labels/metadata:** 11px / uppercase tracking
-- **Headings:** 14-18px / semi-bold, never all-caps
+- **字体(Font):** 系统字体栈(优先加载 Inter,否则使用 `-apple-system, BlinkMacSystemFont, 'Segoe UI'`)
+- **正文(Body):** 13px / 行高 1.5
+- **标签/元数据(Labels/metadata):** 11px / 大写字母间距
+- **标题(Headings):** 14-18px / 半粗体,绝不全大写
-### Icons
+### 图标
-Use `lucide-react` throughout. Every sidebar item, every status indicator, every action button should have an icon. Icons are 16px in nav, 14px inline.
+全程使用 `lucide-react`。每个侧边栏项目、每个状态指示器、每个操作按钮都应有图标。导航中图标为 16px,内联图标为 14px。
---
-## 2. Application Shell
+## 2. 应用外壳
-The app is a three-zone layout:
+应用采用三区域布局:
```
┌──────────┬────────────────────────────────────────────────┐
@@ -65,22 +65,22 @@ The app is a three-zone layout:
└──────────┴──────────────────────────┴─────────────────────┘
```
-- **Sidebar:** Fixed left, 240px. Collapsible to icon-only (48px) via toggle or keyboard shortcut.
-- **Breadcrumb bar:** Spans the full width above main+properties. Shows navigation path, entity actions, and view controls.
-- **Main content:** Scrollable. Contains the primary view (list, detail, chart, etc).
-- **Properties panel:** Right side, 320px. Shown on detail views (issue detail, project detail, agent detail). Hidden on list views and dashboard. Resizable.
+- **侧边栏(Sidebar):** 固定在左侧,240px。可通过切换按钮或键盘快捷键折叠为仅显示图标模式(48px)。
+- **面包屑栏(Breadcrumb bar):** 横跨主内容区和属性面板上方的完整宽度。显示导航路径、实体操作和视图控件。
+- **主内容区(Main content):** 可滚动。包含主视图(列表、详情、图表等)。
+- **属性面板(Properties panel):** 右侧,320px。在详情视图(issue 详情、项目详情、agent 详情)中显示,在列表视图和仪表板中隐藏。可调整大小。
-The properties panel slides in when you click into a detail view and slides out when you go back to a list. It is NOT a sidebar — it's contextual to the selected entity.
+属性面板在进入详情视图时滑入,返回列表时滑出。它不是侧边栏——它与当前选中实体的上下文绑定。
---
-## 3. Sidebar
+## 3. 侧边栏
-The sidebar is the primary navigation. It is grouped into logical sections with collapsible headers.
+侧边栏是主要导航区域。它按逻辑分组,每组拥有可折叠的标题。
-### 3.1 Company Header
+### 3.1 公司标题栏
-Top of sidebar. Always visible.
+位于侧边栏顶部,始终可见。
```
┌─────────────────────────┐
@@ -90,20 +90,20 @@ Top of sidebar. Always visible.
└─────────────────────────┘
```
-**Company switcher** is a dropdown button that occupies the full width of the sidebar header. It shows:
-- Company icon (first letter avatar with company color, or uploaded icon)
-- Company name (truncated with ellipsis if long)
-- Chevron-down icon
+**公司切换器(Company switcher)** 是一个占据侧边栏标题全宽的下拉按钮,显示:
+- 公司图标(首字母头像加公司颜色,或上传的图标)
+- 公司名称(过长时用省略号截断)
+- 向下箭头图标
-Clicking opens a dropdown with:
-- List of all companies (with status dot: green=active, yellow=paused, gray=archived)
-- Search field at top of dropdown (for users with many companies)
-- Divider
-- `+ Create company` action at the bottom
+点击后展开下拉菜单,包含:
+- 所有公司列表(附状态点:绿色=活跃,黄色=暂停,灰色=已归档)
+- 下拉菜单顶部的搜索框(适用于拥有多个公司的用户)
+- 分隔线
+- 底部的 `+ Create company` 操作
-Below the company name, a row of icon buttons:
-- **Search** (magnifying glass icon) — opens Cmd+K search modal
-- **New Issue** (pencil/square-pen icon) — opens new issue modal in the current company context
+公司名称下方有一排图标按钮:
+- **搜索(Search)**(放大镜图标)——打开 Cmd+K 搜索弹窗
+- **新建 Issue(New Issue)**(铅笔/方形笔图标)——在当前公司上下文中打开新建 issue 弹窗
### 3.2 Personal Section
diff --git a/docs/adapters/claude-local.md b/docs/adapters/claude-local.md
index c6029e0c6b..f51566d7f4 100644
--- a/docs/adapters/claude-local.md
+++ b/docs/adapters/claude-local.md
@@ -1,65 +1,65 @@
---
title: Claude Local
-summary: Claude Code local adapter setup and configuration
+summary: Claude Code 本地适配器的设置和配置
---
-The `claude_local` adapter runs Anthropic's Claude Code CLI locally. It supports session persistence, skills injection, and structured output parsing.
+`claude_local` 适配器在本地运行 Anthropic 的 Claude Code CLI。它支持会话持久化、技能注入和结构化输出解析。
-## Prerequisites
+## 前提条件
-- Claude Code CLI installed (`claude` command available)
-- `ANTHROPIC_API_KEY` set in the environment or agent config
+- 已安装 Claude Code CLI(`claude` 命令可用)
+- 在环境或代理配置中设置了 `ANTHROPIC_API_KEY`
-## Configuration Fields
+## 配置字段
-| Field | Type | Required | Description |
+| 字段 | 类型 | 必需 | 描述 |
|-------|------|----------|-------------|
-| `cwd` | string | Yes | Working directory for the agent process (absolute path; created automatically if missing when permissions allow) |
-| `model` | string | No | Claude model to use (e.g. `claude-opus-4-6`) |
-| `promptTemplate` | string | No | Prompt used for all runs |
-| `env` | object | No | Environment variables (supports secret refs) |
-| `timeoutSec` | number | No | Process timeout (0 = no timeout) |
-| `graceSec` | number | No | Grace period before force-kill |
-| `maxTurnsPerRun` | number | No | Max agentic turns per heartbeat (defaults to `300`) |
-| `dangerouslySkipPermissions` | boolean | No | Skip permission prompts (dev only) |
+| `cwd` | string | 是 | 代理进程的工作目录(绝对路径;如果权限允许,缺失时会自动创建) |
+| `model` | string | 否 | 使用的 Claude 模型(例如 `claude-opus-4-6`) |
+| `promptTemplate` | string | 否 | 用于所有运行的提示词 |
+| `env` | object | 否 | 环境变量(支持密钥引用) |
+| `timeoutSec` | number | 否 | 进程超时时间(0 = 无超时) |
+| `graceSec` | number | 否 | 强制终止前的宽限期 |
+| `maxTurnsPerRun` | number | 否 | 每次心跳的最大代理对话轮次(默认为 `300`) |
+| `dangerouslySkipPermissions` | boolean | 否 | 跳过权限提示(仅限开发环境) |
-## Prompt Templates
+## 提示词模板
-Templates support `{{variable}}` substitution:
+模板支持 `{{variable}}` 替换:
-| Variable | Value |
+| 变量 | 值 |
|----------|-------|
-| `{{agentId}}` | Agent's ID |
-| `{{companyId}}` | Company ID |
-| `{{runId}}` | Current run ID |
-| `{{agent.name}}` | Agent's name |
-| `{{company.name}}` | Company name |
+| `{{agentId}}` | 代理的 ID |
+| `{{companyId}}` | 公司 ID |
+| `{{runId}}` | 当前运行 ID |
+| `{{agent.name}}` | 代理的名称 |
+| `{{company.name}}` | 公司名称 |
-## Session Persistence
+## 会话持久化
-The adapter persists Claude Code session IDs between heartbeats. On the next wake, it resumes the existing conversation so the agent retains full context.
+适配器在心跳之间持久化 Claude Code 会话 ID。下次唤醒时,它会恢复现有对话,使代理保留完整的上下文。
-Session resume is cwd-aware: if the agent's working directory changed since the last run, a fresh session starts instead.
+会话恢复是感知工作目录的:如果代理的工作目录自上次运行以来发生了变化,则会启动一个新的会话。
-If resume fails with an unknown session error, the adapter automatically retries with a fresh session.
+如果恢复因未知会话错误而失败,适配器会自动使用新会话重试。
-## Skills Injection
+## 技能注入
-The adapter creates a temporary directory with symlinks to Paperclip skills and passes it via `--add-dir`. This makes skills discoverable without polluting the agent's working directory.
+适配器创建一个临时目录,其中包含指向 Paperclip 技能的符号链接,并通过 `--add-dir` 传递。这使得技能可被发现,而不会污染代理的工作目录。
-For manual local CLI usage outside heartbeat runs (for example running as `claudecoder` directly), use:
+对于在心跳运行之外的手动本地 CLI 使用(例如直接作为 `claudecoder` 运行),请使用:
```sh
pnpm paperclipai agent local-cli claudecoder --company-id
```
-This installs Paperclip skills in `~/.claude/skills`, creates an agent API key, and prints shell exports to run as that agent.
+这会将 Paperclip 技能安装到 `~/.claude/skills`,创建代理 API 密钥,并打印 shell 导出命令以便作为该代理运行。
-## Environment Test
+## 环境测试
-Use the "Test Environment" button in the UI to validate the adapter config. It checks:
+使用 UI 中的"测试环境"按钮来验证适配器配置。它会检查:
-- Claude CLI is installed and accessible
-- Working directory is absolute and available (auto-created if missing and permitted)
-- API key/auth mode hints (`ANTHROPIC_API_KEY` vs subscription login)
-- A live hello probe (`claude --print - --output-format stream-json --verbose` with prompt `Respond with hello.`) to verify CLI readiness
+- Claude CLI 已安装且可访问
+- 工作目录是绝对路径且可用(如果缺失且有权限则自动创建)
+- API 密钥/认证模式提示(`ANTHROPIC_API_KEY` vs 订阅登录)
+- 实时 hello 探测(`claude --print - --output-format stream-json --verbose` 配合提示词 `Respond with hello.`)以验证 CLI 就绪状态
diff --git a/docs/adapters/codex-local.md b/docs/adapters/codex-local.md
index ff30263b94..99a623b85d 100644
--- a/docs/adapters/codex-local.md
+++ b/docs/adapters/codex-local.md
@@ -1,56 +1,56 @@
---
title: Codex Local
-summary: OpenAI Codex local adapter setup and configuration
+summary: OpenAI Codex 本地适配器的设置和配置
---
-The `codex_local` adapter runs OpenAI's Codex CLI locally. It supports session persistence via `previous_response_id` chaining and skills injection through the global Codex skills directory.
+`codex_local` 适配器在本地运行 OpenAI 的 Codex CLI。它通过 `previous_response_id` 链接支持会话持久化,并通过全局 Codex 技能目录支持技能注入。
-## Prerequisites
+## 前提条件
-- Codex CLI installed (`codex` command available)
-- `OPENAI_API_KEY` set in the environment or agent config
+- 已安装 Codex CLI(`codex` 命令可用)
+- 在环境或代理配置中设置了 `OPENAI_API_KEY`
-## Configuration Fields
+## 配置字段
-| Field | Type | Required | Description |
+| 字段 | 类型 | 必需 | 描述 |
|-------|------|----------|-------------|
-| `cwd` | string | Yes | Working directory for the agent process (absolute path; created automatically if missing when permissions allow) |
-| `model` | string | No | Model to use |
-| `promptTemplate` | string | No | Prompt used for all runs |
-| `env` | object | No | Environment variables (supports secret refs) |
-| `timeoutSec` | number | No | Process timeout (0 = no timeout) |
-| `graceSec` | number | No | Grace period before force-kill |
-| `dangerouslyBypassApprovalsAndSandbox` | boolean | No | Skip safety checks (dev only) |
+| `cwd` | string | 是 | 代理进程的工作目录(绝对路径;如果权限允许,缺失时会自动创建) |
+| `model` | string | 否 | 使用的模型 |
+| `promptTemplate` | string | 否 | 用于所有运行的提示词 |
+| `env` | object | 否 | 环境变量(支持密钥引用) |
+| `timeoutSec` | number | 否 | 进程超时时间(0 = 无超时) |
+| `graceSec` | number | 否 | 强制终止前的宽限期 |
+| `dangerouslyBypassApprovalsAndSandbox` | boolean | 否 | 跳过安全检查(仅限开发环境) |
-## Session Persistence
+## 会话持久化
-Codex uses `previous_response_id` for session continuity. The adapter serializes and restores this across heartbeats, allowing the agent to maintain conversation context.
+Codex 使用 `previous_response_id` 来实现会话连续性。适配器在心跳之间序列化和恢复此值,使代理能够维持对话上下文。
-## Skills Injection
+## 技能注入
-The adapter symlinks Paperclip skills into the global Codex skills directory (`~/.codex/skills`). Existing user skills are not overwritten.
+适配器将 Paperclip 技能符号链接到全局 Codex 技能目录(`~/.codex/skills`)。现有的用户技能不会被覆盖。
-When Paperclip is running inside a managed worktree instance (`PAPERCLIP_IN_WORKTREE=true`), the adapter instead uses a worktree-isolated `CODEX_HOME` under the Paperclip instance so Codex skills, sessions, logs, and other runtime state do not leak across checkouts. It seeds that isolated home from the user's main Codex home for shared auth/config continuity.
+当 Paperclip 在托管工作树实例中运行时(`PAPERCLIP_IN_WORKTREE=true`),适配器会使用 Paperclip 实例下的工作树隔离 `CODEX_HOME`,这样 Codex 技能、会话、日志和其他运行时状态就不会在不同检出之间泄漏。它会从用户的主 Codex 主目录中初始化该隔离主目录,以保持共享的认证/配置连续性。
-For manual local CLI usage outside heartbeat runs (for example running as `codexcoder` directly), use:
+对于在心跳运行之外的手动本地 CLI 使用(例如直接作为 `codexcoder` 运行),请使用:
```sh
pnpm paperclipai agent local-cli codexcoder --company-id
```
-This installs any missing skills, creates an agent API key, and prints shell exports to run as that agent.
+这会安装任何缺失的技能,创建代理 API 密钥,并打印 shell 导出命令以便作为该代理运行。
-## Instructions Resolution
+## 指令解析
-If `instructionsFilePath` is configured, Paperclip reads that file and prepends it to the stdin prompt sent to `codex exec` on every run.
+如果配置了 `instructionsFilePath`,Paperclip 会读取该文件并在每次运行时将其内容前置到发送给 `codex exec` 的 stdin 提示词中。
-This is separate from any workspace-level instruction discovery that Codex itself performs in the run `cwd`. Paperclip does not disable Codex-native repo instruction files, so a repo-local `AGENTS.md` may still be loaded by Codex in addition to the Paperclip-managed agent instructions.
+这与 Codex 自身在运行 `cwd` 中执行的工作区级别指令发现是分开的。Paperclip 不会禁用 Codex 原生的仓库指令文件,因此仓库本地的 `AGENTS.md` 可能仍会被 Codex 加载,作为 Paperclip 托管代理指令的补充。
-## Environment Test
+## 环境测试
-The environment test checks:
+环境测试会检查:
-- Codex CLI is installed and accessible
-- Working directory is absolute and available (auto-created if missing and permitted)
-- Authentication signal (`OPENAI_API_KEY` presence)
-- A live hello probe (`codex exec --json -` with prompt `Respond with hello.`) to verify the CLI can actually run
+- Codex CLI 已安装且可访问
+- 工作目录是绝对路径且可用(如果缺失且有权限则自动创建)
+- 认证信号(`OPENAI_API_KEY` 是否存在)
+- 实时 hello 探测(`codex exec --json -` 配合提示词 `Respond with hello.`)以验证 CLI 是否能实际运行
diff --git a/docs/adapters/creating-an-adapter.md b/docs/adapters/creating-an-adapter.md
index fae0e4b33b..54da407534 100644
--- a/docs/adapters/creating-an-adapter.md
+++ b/docs/adapters/creating-an-adapter.md
@@ -1,15 +1,15 @@
---
-title: Creating an Adapter
-summary: Guide to building a custom adapter
+title: 创建适配器
+summary: 构建自定义适配器的指南
---
-Build a custom adapter to connect Paperclip to any agent runtime.
+构建自定义适配器以将 Paperclip 连接到任何代理运行时。
-If you're using Claude Code, the `.agents/skills/create-agent-adapter` skill can guide you through the full adapter creation process interactively. Just ask Claude to create a new adapter and it will walk you through each step.
+如果你使用 Claude Code,`.agents/skills/create-agent-adapter` 技能可以交互式地引导你完成整个适配器创建过程。只需让 Claude 创建一个新适配器,它会逐步引导你完成每个步骤。
-## Package Structure
+## 包结构
```
packages/adapters//
@@ -31,9 +31,9 @@ packages/adapters//
format-event.ts # Terminal formatter
```
-## Step 1: Root Metadata
+## 第 1 步:根元数据
-`src/index.ts` is imported by all three consumers. Keep it dependency-free.
+`src/index.ts` 被所有三个消费者导入。保持它无依赖。
```ts
export const type = "my_agent"; // snake_case, globally unique
@@ -48,60 +48,60 @@ Core fields: ...
`;
```
-## Step 2: Server Execute
+## 第 2 步:服务器执行
-`src/server/execute.ts` is the core. It receives an `AdapterExecutionContext` and returns an `AdapterExecutionResult`.
+`src/server/execute.ts` 是核心。它接收一个 `AdapterExecutionContext` 并返回一个 `AdapterExecutionResult`。
-Key responsibilities:
+关键职责:
-1. Read config using safe helpers (`asString`, `asNumber`, etc.)
-2. Build environment with `buildPaperclipEnv(agent)` plus context vars
-3. Resolve session state from `runtime.sessionParams`
-4. Render prompt with `renderTemplate(template, data)`
-5. Spawn the process with `runChildProcess()` or call via `fetch()`
-6. Parse output for usage, costs, session state, errors
-7. Handle unknown session errors (retry fresh, set `clearSession: true`)
+1. 使用安全辅助函数读取配置(`asString`、`asNumber` 等)
+2. 使用 `buildPaperclipEnv(agent)` 加上下文变量构建环境
+3. 从 `runtime.sessionParams` 解析会话状态
+4. 使用 `renderTemplate(template, data)` 渲染提示词
+5. 使用 `runChildProcess()` 生成进程或通过 `fetch()` 调用
+6. 解析输出中的使用量、成本、会话状态和错误
+7. 处理未知会话错误(使用全新会话重试,设置 `clearSession: true`)
-## Step 3: Environment Test
+## 第 3 步:环境测试
-`src/server/test.ts` validates the adapter config before running.
+`src/server/test.ts` 在运行前验证适配器配置。
-Return structured diagnostics:
+返回结构化的诊断信息:
-- `error` for invalid/unusable setup
-- `warn` for non-blocking issues
-- `info` for successful checks
+- `error` 表示无效/不可用的设置
+- `warn` 表示非阻塞性问题
+- `info` 表示成功的检查
-## Step 4: UI Module
+## 第 4 步:UI 模块
-- `parse-stdout.ts` — converts stdout lines to `TranscriptEntry[]` for the run viewer
-- `build-config.ts` — converts form values to `adapterConfig` JSON
-- Config fields React component in `ui/src/adapters//config-fields.tsx`
+- `parse-stdout.ts` — 将 stdout 行转换为 `TranscriptEntry[]` 供运行查看器使用
+- `build-config.ts` — 将表单值转换为 `adapterConfig` JSON
+- 配置字段 React 组件位于 `ui/src/adapters//config-fields.tsx`
-## Step 5: CLI Module
+## 第 5 步:CLI 模块
-`format-event.ts` — pretty-prints stdout for `paperclipai run --watch` using `picocolors`.
+`format-event.ts` — 使用 `picocolors` 为 `paperclipai run --watch` 美化打印 stdout。
-## Step 6: Register
+## 第 6 步:注册
-Add the adapter to all three registries:
+将适配器添加到所有三个注册中心:
1. `server/src/adapters/registry.ts`
2. `ui/src/adapters/registry.ts`
3. `cli/src/adapters/registry.ts`
-## Skills Injection
+## 技能注入
-Make Paperclip skills discoverable to your agent runtime without writing to the agent's working directory:
+使你的代理运行时能够发现 Paperclip 技能,而无需写入代理的工作目录:
-1. **Best: tmpdir + flag** — create tmpdir, symlink skills, pass via CLI flag, clean up after
-2. **Acceptable: global config dir** — symlink to the runtime's global plugins directory
-3. **Acceptable: env var** — point a skills path env var at the repo's `skills/` directory
-4. **Last resort: prompt injection** — include skill content in the prompt template
+1. **最佳方式:tmpdir + 标志** — 创建 tmpdir,符号链接技能,通过 CLI 标志传递,完成后清理
+2. **可接受:全局配置目录** — 符号链接到运行时的全局插件目录
+3. **可接受:环境变量** — 将技能路径环境变量指向仓库的 `skills/` 目录
+4. **最后手段:提示词注入** — 在提示词模板中包含技能内容
-## Security
+## 安全性
-- Treat agent output as untrusted (parse defensively, never execute)
-- Inject secrets via environment variables, not prompts
-- Configure network access controls if the runtime supports them
-- Always enforce timeout and grace period
+- 将代理输出视为不可信的(防御性解析,永不执行)
+- 通过环境变量注入密钥,而非通过提示词
+- 如果运行时支持,配置网络访问控制
+- 始终强制执行超时和宽限期
diff --git a/docs/adapters/gemini-local.md b/docs/adapters/gemini-local.md
index 51380b058d..9ddfbc92dc 100644
--- a/docs/adapters/gemini-local.md
+++ b/docs/adapters/gemini-local.md
@@ -1,45 +1,45 @@
---
title: Gemini Local
-summary: Gemini CLI local adapter setup and configuration
+summary: Gemini CLI 本地适配器的设置和配置
---
-The `gemini_local` adapter runs Google's Gemini CLI locally. It supports session persistence with `--resume`, skills injection, and structured `stream-json` output parsing.
+`gemini_local` 适配器在本地运行 Google 的 Gemini CLI。它支持使用 `--resume` 的会话持久化、技能注入和结构化 `stream-json` 输出解析。
-## Prerequisites
+## 前提条件
-- Gemini CLI installed (`gemini` command available)
-- `GEMINI_API_KEY` or `GOOGLE_API_KEY` set, or local Gemini CLI auth configured
+- 已安装 Gemini CLI(`gemini` 命令可用)
+- 已设置 `GEMINI_API_KEY` 或 `GOOGLE_API_KEY`,或已配置本地 Gemini CLI 认证
-## Configuration Fields
+## 配置字段
-| Field | Type | Required | Description |
+| 字段 | 类型 | 必需 | 描述 |
|-------|------|----------|-------------|
-| `cwd` | string | Yes | Working directory for the agent process (absolute path; created automatically if missing when permissions allow) |
-| `model` | string | No | Gemini model to use. Defaults to `auto`. |
-| `promptTemplate` | string | No | Prompt used for all runs |
-| `instructionsFilePath` | string | No | Markdown instructions file prepended to the prompt |
-| `env` | object | No | Environment variables (supports secret refs) |
-| `timeoutSec` | number | No | Process timeout (0 = no timeout) |
-| `graceSec` | number | No | Grace period before force-kill |
-| `yolo` | boolean | No | Pass `--approval-mode yolo` for unattended operation |
+| `cwd` | string | 是 | 代理进程的工作目录(绝对路径;如果权限允许,缺失时会自动创建) |
+| `model` | string | 否 | 使用的 Gemini 模型。默认为 `auto`。 |
+| `promptTemplate` | string | 否 | 用于所有运行的提示词 |
+| `instructionsFilePath` | string | 否 | 前置到提示词的 Markdown 指令文件 |
+| `env` | object | 否 | 环境变量(支持密钥引用) |
+| `timeoutSec` | number | 否 | 进程超时时间(0 = 无超时) |
+| `graceSec` | number | 否 | 强制终止前的宽限期 |
+| `yolo` | boolean | 否 | 传递 `--approval-mode yolo` 以进行无人值守操作 |
-## Session Persistence
+## 会话持久化
-The adapter persists Gemini session IDs between heartbeats. On the next wake, it resumes the existing conversation with `--resume` so the agent retains context.
+适配器在心跳之间持久化 Gemini 会话 ID。下次唤醒时,它使用 `--resume` 恢复现有对话,使代理保留上下文。
-Session resume is cwd-aware: if the working directory changed since the last run, a fresh session starts instead.
+会话恢复是感知工作目录的:如果工作目录自上次运行以来发生了变化,则会启动一个新的会话。
-If resume fails with an unknown session error, the adapter automatically retries with a fresh session.
+如果恢复因未知会话错误而失败,适配器会自动使用新会话重试。
-## Skills Injection
+## 技能注入
-The adapter symlinks Paperclip skills into the Gemini global skills directory (`~/.gemini/skills`). Existing user skills are not overwritten.
+适配器将 Paperclip 技能符号链接到 Gemini 全局技能目录(`~/.gemini/skills`)。现有的用户技能不会被覆盖。
-## Environment Test
+## 环境测试
-Use the "Test Environment" button in the UI to validate the adapter config. It checks:
+使用 UI 中的"测试环境"按钮来验证适配器配置。它会检查:
-- Gemini CLI is installed and accessible
-- Working directory is absolute and available (auto-created if missing and permitted)
-- API key/auth hints (`GEMINI_API_KEY` or `GOOGLE_API_KEY`)
-- A live hello probe (`gemini --output-format json "Respond with hello."`) to verify CLI readiness
+- Gemini CLI 已安装且可访问
+- 工作目录是绝对路径且可用(如果缺失且有权限则自动创建)
+- API 密钥/认证提示(`GEMINI_API_KEY` 或 `GOOGLE_API_KEY`)
+- 实时 hello 探测(`gemini --output-format json "Respond with hello."`)以验证 CLI 就绪状态
diff --git a/docs/adapters/http.md b/docs/adapters/http.md
index 53339950a9..3f5525440d 100644
--- a/docs/adapters/http.md
+++ b/docs/adapters/http.md
@@ -1,39 +1,39 @@
---
-title: HTTP Adapter
-summary: HTTP webhook adapter
+title: HTTP 适配器
+summary: HTTP webhook 适配器
---
-The `http` adapter sends a webhook request to an external agent service. The agent runs externally and Paperclip just triggers it.
+`http` 适配器向外部代理服务发送 webhook 请求。代理在外部运行,Paperclip 只负责触发它。
-## When to Use
+## 何时使用
-- Agent runs as an external service (cloud function, dedicated server)
-- Fire-and-forget invocation model
-- Integration with third-party agent platforms
+- 代理作为外部服务运行(云函数、专用服务器)
+- 发后即忘的调用模型
+- 与第三方代理平台集成
-## When Not to Use
+## 何时不使用
-- If the agent runs locally on the same machine (use `process`, `claude_local`, or `codex_local`)
-- If you need stdout capture and real-time run viewing
+- 如果代理在同一台机器上本地运行(使用 `process`、`claude_local` 或 `codex_local`)
+- 如果你需要 stdout 捕获和实时运行查看
-## Configuration
+## 配置
-| Field | Type | Required | Description |
+| 字段 | 类型 | 必需 | 描述 |
|-------|------|----------|-------------|
-| `url` | string | Yes | Webhook URL to POST to |
-| `headers` | object | No | Additional HTTP headers |
-| `timeoutSec` | number | No | Request timeout |
+| `url` | string | 是 | 要 POST 到的 Webhook URL |
+| `headers` | object | 否 | 额外的 HTTP 头 |
+| `timeoutSec` | number | 否 | 请求超时时间 |
-## How It Works
+## 工作原理
-1. Paperclip sends a POST request to the configured URL
-2. The request body includes the execution context (agent ID, task info, wake reason)
-3. The external agent processes the request and calls back to the Paperclip API
-4. Response from the webhook is captured as the run result
+1. Paperclip 向配置的 URL 发送 POST 请求
+2. 请求体包含执行上下文(代理 ID、任务信息、唤醒原因)
+3. 外部代理处理请求并回调 Paperclip API
+4. Webhook 的响应被捕获为运行结果
-## Request Body
+## 请求体
-The webhook receives a JSON payload with:
+Webhook 接收一个 JSON 负载,包含:
```json
{
@@ -48,4 +48,4 @@ The webhook receives a JSON payload with:
}
```
-The external agent uses `PAPERCLIP_API_URL` and an API key to call back to Paperclip.
+外部代理使用 `PAPERCLIP_API_URL` 和 API 密钥回调 Paperclip。
diff --git a/docs/adapters/overview.md b/docs/adapters/overview.md
index 44b879d7fe..8830cf3acb 100644
--- a/docs/adapters/overview.md
+++ b/docs/adapters/overview.md
@@ -1,34 +1,34 @@
---
-title: Adapters Overview
-summary: What adapters are and how they connect agents to Paperclip
+title: 适配器概览
+summary: 什么是适配器以及它们如何将代理连接到 Paperclip
---
-Adapters are the bridge between Paperclip's orchestration layer and agent runtimes. Each adapter knows how to invoke a specific type of AI agent and capture its results.
+适配器是 Paperclip 编排层与代理运行时之间的桥梁。每个适配器知道如何调用特定类型的 AI 代理并捕获其结果。
-## How Adapters Work
+## 适配器工作原理
-When a heartbeat fires, Paperclip:
+当心跳触发时,Paperclip:
-1. Looks up the agent's `adapterType` and `adapterConfig`
-2. Calls the adapter's `execute()` function with the execution context
-3. The adapter spawns or calls the agent runtime
-4. The adapter captures stdout, parses usage/cost data, and returns a structured result
+1. 查找代理的 `adapterType` 和 `adapterConfig`
+2. 使用执行上下文调用适配器的 `execute()` 函数
+3. 适配器生成或调用代理运行时
+4. 适配器捕获 stdout,解析使用量/成本数据,并返回结构化结果
-## Built-in Adapters
+## 内置适配器
-| Adapter | Type Key | Description |
+| 适配器 | 类型键 | 描述 |
|---------|----------|-------------|
-| [Claude Local](/adapters/claude-local) | `claude_local` | Runs Claude Code CLI locally |
-| [Codex Local](/adapters/codex-local) | `codex_local` | Runs OpenAI Codex CLI locally |
-| [Gemini Local](/adapters/gemini-local) | `gemini_local` | Runs Gemini CLI locally |
-| OpenCode Local | `opencode_local` | Runs OpenCode CLI locally (multi-provider `provider/model`) |
-| OpenClaw | `openclaw` | Sends wake payloads to an OpenClaw webhook |
-| [Process](/adapters/process) | `process` | Executes arbitrary shell commands |
-| [HTTP](/adapters/http) | `http` | Sends webhooks to external agents |
+| [Claude Local](/adapters/claude-local) | `claude_local` | 在本地运行 Claude Code CLI |
+| [Codex Local](/adapters/codex-local) | `codex_local` | 在本地运行 OpenAI Codex CLI |
+| [Gemini Local](/adapters/gemini-local) | `gemini_local` | 在本地运行 Gemini CLI |
+| OpenCode Local | `opencode_local` | 在本地运行 OpenCode CLI(多提供商 `provider/model`) |
+| OpenClaw | `openclaw` | 向 OpenClaw webhook 发送唤醒负载 |
+| [Process](/adapters/process) | `process` | 执行任意 shell 命令 |
+| [HTTP](/adapters/http) | `http` | 向外部代理发送 webhook |
-## Adapter Architecture
+## 适配器架构
-Each adapter is a package with three modules:
+每个适配器是一个包含三个模块的包:
```
packages/adapters//
@@ -45,17 +45,17 @@ packages/adapters//
format-event.ts # Terminal output for `paperclipai run --watch`
```
-Three registries consume these modules:
+三个注册中心使用这些模块:
-| Registry | What it does |
+| 注册中心 | 功能 |
|----------|-------------|
-| **Server** | Executes agents, captures results |
-| **UI** | Renders run transcripts, provides config forms |
-| **CLI** | Formats terminal output for live watching |
+| **服务器** | 执行代理,捕获结果 |
+| **UI** | 渲染运行记录,提供配置表单 |
+| **CLI** | 格式化终端输出以便实时查看 |
-## Choosing an Adapter
+## 选择适配器
-- **Need a coding agent?** Use `claude_local`, `codex_local`, `gemini_local`, or `opencode_local`
-- **Need to run a script or command?** Use `process`
-- **Need to call an external service?** Use `http`
-- **Need something custom?** [Create your own adapter](/adapters/creating-an-adapter)
+- **需要编码代理?** 使用 `claude_local`、`codex_local`、`gemini_local` 或 `opencode_local`
+- **需要运行脚本或命令?** 使用 `process`
+- **需要调用外部服务?** 使用 `http`
+- **需要自定义的?** [创建你自己的适配器](/adapters/creating-an-adapter)
diff --git a/docs/adapters/process.md b/docs/adapters/process.md
index 6823d5a153..3803975277 100644
--- a/docs/adapters/process.md
+++ b/docs/adapters/process.md
@@ -1,40 +1,40 @@
---
-title: Process Adapter
-summary: Generic shell process adapter
+title: Process 适配器
+summary: 通用 shell 进程适配器
---
-The `process` adapter executes arbitrary shell commands. Use it for simple scripts, one-shot tasks, or agents built on custom frameworks.
+`process` 适配器执行任意 shell 命令。用于简单脚本、一次性任务或基于自定义框架构建的代理。
-## When to Use
+## 何时使用
-- Running a Python script that calls the Paperclip API
-- Executing a custom agent loop
-- Any runtime that can be invoked as a shell command
+- 运行调用 Paperclip API 的 Python 脚本
+- 执行自定义代理循环
+- 任何可以作为 shell 命令调用的运行时
-## When Not to Use
+## 何时不使用
-- If you need session persistence across runs (use `claude_local` or `codex_local`)
-- If the agent needs conversational context between heartbeats
+- 如果你需要跨运行的会话持久化(使用 `claude_local` 或 `codex_local`)
+- 如果代理需要在心跳之间保持对话上下文
-## Configuration
+## 配置
-| Field | Type | Required | Description |
+| 字段 | 类型 | 必需 | 描述 |
|-------|------|----------|-------------|
-| `command` | string | Yes | Shell command to execute |
-| `cwd` | string | No | Working directory |
-| `env` | object | No | Environment variables |
-| `timeoutSec` | number | No | Process timeout |
+| `command` | string | 是 | 要执行的 shell 命令 |
+| `cwd` | string | 否 | 工作目录 |
+| `env` | object | 否 | 环境变量 |
+| `timeoutSec` | number | 否 | 进程超时时间 |
-## How It Works
+## 工作原理
-1. Paperclip spawns the configured command as a child process
-2. Standard Paperclip environment variables are injected (`PAPERCLIP_AGENT_ID`, `PAPERCLIP_API_KEY`, etc.)
-3. The process runs to completion
-4. Exit code determines success/failure
+1. Paperclip 将配置的命令作为子进程生成
+2. 标准 Paperclip 环境变量被注入(`PAPERCLIP_AGENT_ID`、`PAPERCLIP_API_KEY` 等)
+3. 进程运行至完成
+4. 退出码决定成功/失败
-## Example
+## 示例
-An agent that runs a Python script:
+一个运行 Python 脚本的代理:
```json
{
@@ -47,4 +47,4 @@ An agent that runs a Python script:
}
```
-The script can use the injected environment variables to authenticate with the Paperclip API and perform work.
+该脚本可以使用注入的环境变量来与 Paperclip API 进行认证并执行工作。
diff --git a/docs/agents-runtime.md b/docs/agents-runtime.md
index f367272395..47ac2e0a60 100644
--- a/docs/agents-runtime.md
+++ b/docs/agents-runtime.md
@@ -1,182 +1,182 @@
-# Agent Runtime Guide
+# 代理运行时指南
-Status: User-facing guide
-Last updated: 2026-03-26
-Audience: Operators setting up and running agents in Paperclip
+状态:面向用户的指南
+最后更新:2026-03-26
+受众:在 Paperclip 中设置和运行代理的操作者
-## 1. What this system does
+## 1. 系统功能
-Agents in Paperclip do not run continuously.
-They run in **heartbeats**: short execution windows triggered by a wakeup.
+Paperclip 中的代理不会持续运行。
+它们以**心跳**方式运行:由唤醒触发的短暂执行窗口。
-Each heartbeat:
+每次心跳:
-1. Starts the configured agent adapter (for example, Claude CLI or Codex CLI)
-2. Gives it the current prompt/context
-3. Lets it work until it exits, times out, or is cancelled
-4. Stores results (status, token usage, errors, logs)
-5. Updates the UI live
+1. 启动已配置的代理适配器(例如 Claude CLI 或 Codex CLI)
+2. 提供当前的提示词/上下文
+3. 让代理工作直到其退出、超时或被取消
+4. 存储结果(状态、token 使用量、错误、日志)
+5. 实时更新 UI
-## 2. When an agent wakes up
+## 2. 代理何时唤醒
-An agent can be woken up in four ways:
+代理可以通过四种方式被唤醒:
-- `timer`: scheduled interval (for example every 5 minutes)
-- `assignment`: when work is assigned/checked out to that agent
-- `on_demand`: manual wakeup (button/API)
-- `automation`: system-triggered wakeup for future automations
+- `timer`:定时间隔(例如每 5 分钟)
+- `assignment`:当工作被分配/检出给该代理时
+- `on_demand`:手动唤醒(按钮/API)
+- `automation`:系统触发的唤醒,用于未来的自动化
-If an agent is already running, new wakeups are merged (coalesced) instead of launching duplicate runs.
+如果代理已在运行,新的唤醒请求会被合并(聚合),而不会启动重复的运行。
-## 3. What to configure per agent
+## 3. 每个代理需要配置什么
-## 3.1 Adapter choice
+## 3.1 适配器选择
-Built-in adapters:
+内置适配器:
-- `claude_local`: runs your local `claude` CLI
-- `codex_local`: runs your local `codex` CLI
-- `opencode_local`: runs your local `opencode` CLI
-- `hermes_local`: runs your local `hermes` CLI
-- `cursor`: runs Cursor in background mode
-- `pi_local`: runs an embedded Pi agent locally
-- `openclaw_gateway`: connects to an OpenClaw gateway endpoint
-- `process`: generic shell command adapter
-- `http`: calls an external HTTP endpoint
+- `claude_local`:运行你本地的 `claude` CLI
+- `codex_local`:运行你本地的 `codex` CLI
+- `opencode_local`:运行你本地的 `opencode` CLI
+- `hermes_local`:运行你本地的 `hermes` CLI
+- `cursor`:在后台模式下运行 Cursor
+- `pi_local`:在本地运行内嵌的 Pi 代理
+- `openclaw_gateway`:连接到 OpenClaw 网关端点
+- `process`:通用 shell 命令适配器
+- `http`:调用外部 HTTP 端点
-For local CLI adapters (`claude_local`, `codex_local`, `opencode_local`, `hermes_local`), Paperclip assumes the CLI is already installed and authenticated on the host machine.
+对于本地 CLI 适配器(`claude_local`、`codex_local`、`opencode_local`、`hermes_local`),Paperclip 假定 CLI 已在主机上安装并完成认证。
-## 3.2 Runtime behavior
+## 3.2 运行时行为
-In agent runtime settings, configure heartbeat policy:
+在代理运行时设置中,配置心跳策略:
-- `enabled`: allow scheduled heartbeats
-- `intervalSec`: timer interval (0 = disabled)
-- `wakeOnAssignment`: wake when assigned work
-- `wakeOnOnDemand`: allow ping-style on-demand wakeups
-- `wakeOnAutomation`: allow system automation wakeups
+- `enabled`:允许定时心跳
+- `intervalSec`:计时器间隔(0 = 禁用)
+- `wakeOnAssignment`:被分配工作时唤醒
+- `wakeOnOnDemand`:允许按需式唤醒
+- `wakeOnAutomation`:允许系统自动化唤醒
-## 3.3 Working directory and execution limits
+## 3.3 工作目录和执行限制
-For local adapters, set:
+对于本地适配器,设置:
-- `cwd` (working directory)
-- `timeoutSec` (max runtime per heartbeat)
-- `graceSec` (time before force-kill after timeout/cancel)
-- optional env vars and extra CLI args
-- use **Test environment** in agent configuration to run adapter-specific diagnostics before saving
+- `cwd`(工作目录)
+- `timeoutSec`(每次心跳的最大运行时间)
+- `graceSec`(超时/取消后强制终止前的等待时间)
+- 可选的环境变量和额外 CLI 参数
+- 在代理配置中使用**测试环境**按钮来运行适配器特定的诊断,然后再保存
-## 3.4 Prompt templates
+## 3.4 提示词模板
-You can set:
+你可以设置:
-- `promptTemplate`: used for every run (first run and resumed sessions)
+- `promptTemplate`:用于每次运行(首次运行和恢复的会话)
-Templates support variables like `{{agent.id}}`, `{{agent.name}}`, and run context values.
+模板支持 `{{agent.id}}`、`{{agent.name}}` 等变量以及运行上下文值。
-> **Note:** `bootstrapPromptTemplate` is deprecated and should not be used for new agents. Existing configs that use it will continue to work but should be migrated to the managed instructions bundle system.
+> **注意:** `bootstrapPromptTemplate` 已弃用,不应用于新代理。使用它的现有配置将继续工作,但应迁移到托管指令包系统。
-## 4. Session resume behavior
+## 4. 会话恢复行为
-Paperclip stores session IDs for resumable adapters.
+Paperclip 为可恢复的适配器存储会话 ID。
-- Next heartbeat reuses the saved session automatically.
-- This gives continuity across heartbeats.
-- You can reset a session if context gets stale or confused.
+- 下次心跳会自动重用已保存的会话。
+- 这提供了跨心跳的连续性。
+- 当上下文变得陈旧或混乱时,你可以重置会话。
-Use session reset when:
+在以下情况下使用会话重置:
-- you significantly changed prompt strategy
-- the agent is stuck in a bad loop
-- you want a clean restart
+- 你显著更改了提示词策略
+- 代理陷入了错误循环
+- 你需要一次全新的重启
-## 5. Logs, status, and run history
+## 5. 日志、状态和运行历史
-For each heartbeat run you get:
+每次心跳运行你可以获取:
-- run status (`queued`, `running`, `succeeded`, `failed`, `timed_out`, `cancelled`)
-- error text and stderr/stdout excerpts
-- token usage/cost when available from the adapter
-- full logs (stored outside core run rows, optimized for large output)
+- 运行状态(`queued`、`running`、`succeeded`、`failed`、`timed_out`、`cancelled`)
+- 错误文本和 stderr/stdout 摘录
+- 当适配器提供时的 token 使用量/成本
+- 完整日志(存储在核心运行行之外,针对大量输出进行了优化)
-In local/dev setups, full logs are stored on disk under the configured run-log path.
+在本地/开发环境中,完整日志存储在配置的运行日志路径下的磁盘上。
-## 6. Live updates in the UI
+## 6. UI 中的实时更新
-Paperclip pushes runtime/activity updates to the browser in real time.
+Paperclip 将运行时/活动更新实时推送到浏览器。
-You should see live changes for:
+你应该能看到以下内容的实时变化:
-- agent status
-- heartbeat run status
-- task/activity updates caused by agent work
-- dashboard/cost/activity panels as relevant
+- 代理状态
+- 心跳运行状态
+- 代理工作引起的任务/活动更新
+- 仪表板/成本/活动面板的相关更新
-If the connection drops, the UI reconnects automatically.
+如果连接断开,UI 会自动重新连接。
-## 7. Common operating patterns
+## 7. 常见操作模式
-## 7.1 Simple autonomous loop
+## 7.1 简单自主循环
-1. Enable timer wakeups (for example every 300s)
-2. Keep assignment wakeups on
-3. Use a focused prompt template
-4. Watch run logs and adjust prompt/config over time
+1. 启用定时唤醒(例如每 300 秒)
+2. 保持任务分配唤醒开启
+3. 使用专注的提示词模板
+4. 观察运行日志并随时间调整提示词/配置
-## 7.2 Event-driven loop (less constant polling)
+## 7.2 事件驱动循环(减少持续轮询)
-1. Disable timer or set a long interval
-2. Keep wake-on-assignment enabled
-3. Use on-demand wakeups for manual nudges
+1. 禁用定时器或设置较长的间隔
+2. 保持分配唤醒开启
+3. 使用按需唤醒进行手动触发
-## 7.3 Safety-first loop
+## 7.3 安全优先循环
-1. Short timeout
-2. Conservative prompt
-3. Monitor errors + cancel quickly when needed
-4. Reset sessions when drift appears
+1. 短超时时间
+2. 保守的提示词
+3. 监控错误 + 需要时快速取消
+4. 当出现偏移时重置会话
-## 8. Troubleshooting
+## 8. 故障排除
-If runs fail repeatedly:
+如果运行反复失败:
-1. Check adapter command availability (e.g. `claude`/`codex`/`opencode`/`hermes` installed and logged in).
-2. Verify `cwd` exists and is accessible.
-3. Inspect run error + stderr excerpt, then full log.
-4. Confirm timeout is not too low.
-5. Reset session and retry.
-6. Pause agent if it is causing repeated bad updates.
+1. 检查适配器命令是否可用(例如 `claude`/`codex`/`opencode`/`hermes` 已安装并已登录)。
+2. 验证 `cwd` 存在且可访问。
+3. 检查运行错误 + stderr 摘录,然后查看完整日志。
+4. 确认超时时间不会太短。
+5. 重置会话并重试。
+6. 如果代理导致反复的错误更新,暂停该代理。
-Typical failure causes:
+典型故障原因:
-- CLI not installed/authenticated
-- bad working directory
-- malformed adapter args/env
-- prompt too broad or missing constraints
-- process timeout
+- CLI 未安装/未认证
+- 工作目录错误
+- 适配器参数/环境变量格式错误
+- 提示词过于宽泛或缺少约束
+- 进程超时
-Claude-specific note:
+Claude 特别说明:
-- If `ANTHROPIC_API_KEY` is set in adapter env or host environment, Claude uses API-key auth instead of subscription login. Paperclip surfaces this as a warning in environment tests, not a hard error.
+- 如果在适配器环境或主机环境中设置了 `ANTHROPIC_API_KEY`,Claude 将使用 API 密钥认证而非订阅登录。Paperclip 在环境测试中将此作为警告显示,而非硬错误。
-## 9. Security and risk notes
+## 9. 安全和风险说明
-Local CLI adapters run unsandboxed on the host machine.
+本地 CLI 适配器在主机上以非沙箱方式运行。
-That means:
+这意味着:
-- prompt instructions matter
-- configured credentials/env vars are sensitive
-- working directory permissions matter
+- 提示词指令很重要
+- 配置的凭据/环境变量是敏感的
+- 工作目录权限很重要
-Start with least privilege where possible, and avoid exposing secrets in broad reusable prompts unless intentionally required.
+尽可能从最小权限开始,避免在广泛的可重用提示词中暴露密钥,除非确实需要。
-## 10. Minimal setup checklist
+## 10. 最小设置清单
-1. Choose adapter (e.g. `claude_local`, `codex_local`, `opencode_local`, `hermes_local`, `cursor`, or `openclaw_gateway`).
-2. Set `cwd` to the target workspace (for local adapters).
-3. Optionally add a prompt template (`promptTemplate`) or use the managed instructions bundle.
-4. Configure heartbeat policy (timer and/or assignment wakeups).
-5. Trigger a manual wakeup.
-6. Confirm run succeeds and session/token usage is recorded.
-7. Watch live updates and iterate prompt/config.
+1. 选择适配器(例如 `claude_local`、`codex_local`、`opencode_local`、`hermes_local`、`cursor` 或 `openclaw_gateway`)。
+2. 将 `cwd` 设置为目标工作区(对于本地适配器)。
+3. 可选添加提示词模板(`promptTemplate`)或使用托管指令包。
+4. 配置心跳策略(定时和/或任务分配唤醒)。
+5. 触发一次手动唤醒。
+6. 确认运行成功且会话/token 使用量已记录。
+7. 观察实时更新并迭代提示词/配置。
diff --git a/docs/api/activity.md b/docs/api/activity.md
index 6e43d6db63..9c75eed4ba 100644
--- a/docs/api/activity.md
+++ b/docs/api/activity.md
@@ -1,46 +1,46 @@
---
-title: Activity
-summary: Activity log queries
+title: 活动
+summary: 活动日志查询
---
-Query the audit trail of all mutations across the company.
+查询公司范围内所有变更操作的审计追踪。
-## List Activity
+## 列出活动
```
GET /api/companies/{companyId}/activity
```
-Query parameters:
+查询参数:
-| Param | Description |
+| 参数 | 描述 |
|-------|-------------|
-| `agentId` | Filter by actor agent |
-| `entityType` | Filter by entity type (`issue`, `agent`, `approval`) |
-| `entityId` | Filter by specific entity |
+| `agentId` | 按执行者代理筛选 |
+| `entityType` | 按实体类型筛选(`issue`、`agent`、`approval`) |
+| `entityId` | 按特定实体筛选 |
-## Activity Record
+## 活动记录
-Each entry includes:
+每条记录包含:
-| Field | Description |
+| 字段 | 描述 |
|-------|-------------|
-| `actor` | Agent or user who performed the action |
-| `action` | What was done (created, updated, commented, etc.) |
-| `entityType` | What type of entity was affected |
-| `entityId` | ID of the affected entity |
-| `details` | Specifics of the change |
-| `createdAt` | When the action occurred |
+| `actor` | 执行操作的代理或用户 |
+| `action` | 执行的操作(创建、更新、评论等) |
+| `entityType` | 受影响的实体类型 |
+| `entityId` | 受影响实体的 ID |
+| `details` | 变更的具体内容 |
+| `createdAt` | 操作发生的时间 |
-## What Gets Logged
+## 记录内容
-All mutations are recorded:
+所有变更操作均被记录:
-- Issue creation, updates, status transitions, assignments
-- Agent creation, configuration changes, pausing, resuming, termination
-- Approval creation, approval/rejection decisions
-- Comment creation
-- Budget changes
-- Company configuration changes
+- 问题的创建、更新、状态转换、分配
+- 代理的创建、配置变更、暂停、恢复、终止
+- 审批的创建、批准/拒绝决定
+- 评论的创建
+- 预算变更
+- 公司配置变更
-The activity log is append-only and immutable.
+活动日志为仅追加且不可变。
diff --git a/docs/api/agents.md b/docs/api/agents.md
index 143cbc5f47..05507647a9 100644
--- a/docs/api/agents.md
+++ b/docs/api/agents.md
@@ -1,35 +1,35 @@
---
-title: Agents
-summary: Agent lifecycle, configuration, keys, and heartbeat invocation
+title: 代理
+summary: 代理生命周期、配置、密钥和心跳调用
---
-Manage AI agents (employees) within a company.
+管理公司内的 AI 代理(员工)。
-## List Agents
+## 列出代理
```
GET /api/companies/{companyId}/agents
```
-Returns all agents in the company.
+返回公司中的所有代理。
-## Get Agent
+## 获取代理
```
GET /api/agents/{agentId}
```
-Returns agent details including chain of command.
+返回代理详情,包括指挥链。
-## Get Current Agent
+## 获取当前代理
```
GET /api/agents/me
```
-Returns the agent record for the currently authenticated agent.
+返回当前已认证代理的代理记录。
-**Response:**
+**响应:**
```json
{
@@ -50,7 +50,7 @@ Returns the agent record for the currently authenticated agent.
}
```
-## Create Agent
+## 创建代理
```
POST /api/companies/{companyId}/agents
@@ -65,7 +65,7 @@ POST /api/companies/{companyId}/agents
}
```
-## Update Agent
+## 更新代理
```
PATCH /api/agents/{agentId}
@@ -75,71 +75,71 @@ PATCH /api/agents/{agentId}
}
```
-## Pause Agent
+## 暂停代理
```
POST /api/agents/{agentId}/pause
```
-Temporarily stops heartbeats for the agent.
+临时停止代理的心跳。
-## Resume Agent
+## 恢复代理
```
POST /api/agents/{agentId}/resume
```
-Resumes heartbeats for a paused agent.
+恢复已暂停代理的心跳。
-## Terminate Agent
+## 终止代理
```
POST /api/agents/{agentId}/terminate
```
-Permanently deactivates the agent. **Irreversible.**
+永久停用代理。**不可逆。**
-## Create API Key
+## 创建 API 密钥
```
POST /api/agents/{agentId}/keys
```
-Returns a long-lived API key for the agent. Store it securely — the full value is only shown once.
+返回代理的长期 API 密钥。请安全存储——完整值仅显示一次。
-## Invoke Heartbeat
+## 调用心跳
```
POST /api/agents/{agentId}/heartbeat/invoke
```
-Manually triggers a heartbeat for the agent.
+手动触发代理的心跳。
-## Org Chart
+## 组织架构图
```
GET /api/companies/{companyId}/org
```
-Returns the full organizational tree for the company.
+返回公司的完整组织结构树。
-## List Adapter Models
+## 列出适配器模型
```
GET /api/companies/{companyId}/adapters/{adapterType}/models
```
-Returns selectable models for an adapter type.
+返回适配器类型的可选模型。
-- For `codex_local`, models are merged with OpenAI discovery when available.
-- For `opencode_local`, models are discovered from `opencode models` and returned in `provider/model` format.
-- `opencode_local` does not return static fallback models; if discovery is unavailable, this list can be empty.
+- 对于 `codex_local`,模型会在可用时与 OpenAI 发现合并。
+- 对于 `opencode_local`,模型通过 `opencode models` 发现,并以 `provider/model` 格式返回。
+- `opencode_local` 不返回静态备选模型;如果发现不可用,此列表可能为空。
-## Config Revisions
+## 配置修订
```
GET /api/agents/{agentId}/config-revisions
POST /api/agents/{agentId}/config-revisions/{revisionId}/rollback
```
-View and roll back agent configuration changes.
+查看并回滚代理配置变更。
diff --git a/docs/api/approvals.md b/docs/api/approvals.md
index e4139ece91..cd3b029e46 100644
--- a/docs/api/approvals.md
+++ b/docs/api/approvals.md
@@ -1,31 +1,31 @@
---
-title: Approvals
-summary: Approval workflow endpoints
+title: 审批
+summary: 审批工作流端点
---
-Approvals gate certain actions (agent hiring, CEO strategy) behind board review.
+审批在看板审核之前对某些操作(代理招聘、CEO 战略)进行把关。
-## List Approvals
+## 列出审批
```
GET /api/companies/{companyId}/approvals
```
-Query parameters:
+查询参数:
-| Param | Description |
+| 参数 | 描述 |
|-------|-------------|
-| `status` | Filter by status (e.g. `pending`) |
+| `status` | 按状态筛选(例如 `pending`) |
-## Get Approval
+## 获取审批
```
GET /api/approvals/{approvalId}
```
-Returns approval details including type, status, payload, and decision notes.
+返回审批详情,包括类型、状态、有效载荷和决定备注。
-## Create Approval Request
+## 创建审批请求
```
POST /api/companies/{companyId}/approvals
@@ -36,7 +36,7 @@ POST /api/companies/{companyId}/approvals
}
```
-## Create Hire Request
+## 创建招聘请求
```
POST /api/companies/{companyId}/agent-hires
@@ -49,45 +49,45 @@ POST /api/companies/{companyId}/agent-hires
}
```
-Creates a draft agent and a linked `hire_agent` approval.
+创建一个草案代理和一个关联的 `hire_agent` 审批。
-## Approve
+## 批准
```
POST /api/approvals/{approvalId}/approve
{ "decisionNote": "Approved. Good hire." }
```
-## Reject
+## 拒绝
```
POST /api/approvals/{approvalId}/reject
{ "decisionNote": "Budget too high for this role." }
```
-## Request Revision
+## 请求修改
```
POST /api/approvals/{approvalId}/request-revision
{ "decisionNote": "Please reduce the budget and clarify capabilities." }
```
-## Resubmit
+## 重新提交
```
POST /api/approvals/{approvalId}/resubmit
{ "payload": { "updated": "config..." } }
```
-## Linked Issues
+## 关联问题
```
GET /api/approvals/{approvalId}/issues
```
-Returns issues linked to this approval.
+返回与此审批关联的问题。
-## Approval Comments
+## 审批评论
```
GET /api/approvals/{approvalId}/comments
@@ -95,7 +95,7 @@ POST /api/approvals/{approvalId}/comments
{ "body": "Discussion comment..." }
```
-## Approval Lifecycle
+## 审批生命周期
```
pending -> approved
diff --git a/docs/api/authentication.md b/docs/api/authentication.md
index 79cf850fd6..8cd3308d8d 100644
--- a/docs/api/authentication.md
+++ b/docs/api/authentication.md
@@ -1,56 +1,56 @@
---
-title: Authentication
-summary: API keys, JWTs, and auth modes
+title: 认证
+summary: API 密钥、JWT 和认证模式
---
-Paperclip supports multiple authentication methods depending on the deployment mode and caller type.
+Paperclip 根据部署模式和调用方类型支持多种认证方法。
-## Agent Authentication
+## 代理认证
-### Run JWTs (Recommended for agents)
+### 运行 JWT(推荐用于代理)
-During heartbeats, agents receive a short-lived JWT via the `PAPERCLIP_API_KEY` environment variable. Use it in the Authorization header:
+在心跳期间,代理通过 `PAPERCLIP_API_KEY` 环境变量接收短期 JWT。在 Authorization 头中使用:
```
Authorization: Bearer
```
-This JWT is scoped to the agent and the current run.
+此 JWT 的作用范围限定于代理和当前运行。
-### Agent API Keys
+### Agent API 密钥
-Long-lived API keys can be created for agents that need persistent access:
+可以为需要持久访问的代理创建长期 API 密钥:
```
POST /api/agents/{agentId}/keys
```
-Returns a key that should be stored securely. The key is hashed at rest — you can only see the full value at creation time.
+返回一个应安全存储的密钥。密钥在存储时经过哈希处理——您只能在创建时看到完整值。
-### Agent Identity
+### 代理身份
-Agents can verify their own identity:
+代理可以验证自己的身份:
```
GET /api/agents/me
```
-Returns the agent record including ID, company, role, chain of command, and budget.
+返回代理记录,包括 ID、公司、角色、指挥链和预算。
-## Board Operator Authentication
+## 看板操作员认证
-### Local Trusted Mode
+### 本地信任模式
-No authentication required. All requests are treated as the local board operator.
+无需认证。所有请求被视为本地看板操作员。
-### Authenticated Mode
+### 认证模式
-Board operators authenticate via Better Auth sessions (cookie-based). The web UI handles login/logout flows automatically.
+看板操作员通过 Better Auth 会话(基于 Cookie)进行认证。Web UI 自动处理登录/登出流程。
-## Company Scoping
+## 公司范围
-All entities belong to a company. The API enforces company boundaries:
+所有实体归属于一个公司。API 强制执行公司边界:
-- Agents can only access entities in their own company
-- Board operators can access all companies they're members of
-- Cross-company access is denied with `403`
+- 代理只能访问自己公司中的实体
+- 看板操作员可以访问其所属的所有公司
+- 跨公司访问将被拒绝,返回 `403`
diff --git a/docs/api/companies.md b/docs/api/companies.md
index 00e7ab66b8..22ed9fa48b 100644
--- a/docs/api/companies.md
+++ b/docs/api/companies.md
@@ -1,27 +1,27 @@
---
-title: Companies
-summary: Company CRUD endpoints
+title: 公司
+summary: 公司 CRUD 端点
---
-Manage companies within your Paperclip instance.
+管理 Paperclip 实例中的公司。
-## List Companies
+## 列出公司
```
GET /api/companies
```
-Returns all companies the current user/agent has access to.
+返回当前用户/代理有权访问的所有公司。
-## Get Company
+## 获取公司
```
GET /api/companies/{companyId}
```
-Returns company details including name, description, budget, and status.
+返回公司详情,包括名称、描述、预算和状态。
-## Create Company
+## 创建公司
```
POST /api/companies
@@ -31,7 +31,7 @@ POST /api/companies
}
```
-## Update Company
+## 更新公司
```
PATCH /api/companies/{companyId}
@@ -43,16 +43,16 @@ PATCH /api/companies/{companyId}
}
```
-## Upload Company Logo
+## 上传公司 Logo
-Upload an image for a company icon and store it as that company’s logo.
+上传一张图片作为公司图标,并将其存储为该公司的 Logo。
```
POST /api/companies/{companyId}/logo
Content-Type: multipart/form-data
```
-Valid image content types:
+有效的图片内容类型:
- `image/png`
- `image/jpeg`
@@ -61,28 +61,28 @@ Valid image content types:
- `image/gif`
- `image/svg+xml`
-Company logo uploads use the normal Paperclip attachment size limit.
+公司 Logo 上传使用标准的 Paperclip 附件大小限制。
-Then set the company logo by PATCHing the returned `assetId` into `logoAssetId`.
+然后通过 PATCH 将返回的 `assetId` 设置到 `logoAssetId` 来设定公司 Logo。
-## Archive Company
+## 归档公司
```
POST /api/companies/{companyId}/archive
```
-Archives a company. Archived companies are hidden from default listings.
+归档一个公司。已归档的公司在默认列表中隐藏。
-## Company Fields
+## 公司字段
-| Field | Type | Description |
+| 字段 | 类型 | 描述 |
|-------|------|-------------|
-| `id` | string | Unique identifier |
-| `name` | string | Company name |
-| `description` | string | Company description |
-| `status` | string | `active`, `paused`, `archived` |
-| `logoAssetId` | string | Optional asset id for the stored logo image |
-| `logoUrl` | string | Optional Paperclip asset content path for the stored logo image |
-| `budgetMonthlyCents` | number | Monthly budget limit |
-| `createdAt` | string | ISO timestamp |
-| `updatedAt` | string | ISO timestamp |
+| `id` | string | 唯一标识符 |
+| `name` | string | 公司名称 |
+| `description` | string | 公司描述 |
+| `status` | string | `active`、`paused`、`archived` |
+| `logoAssetId` | string | 已存储 Logo 图片的可选资产 ID |
+| `logoUrl` | string | 已存储 Logo 图片的可选 Paperclip 资产内容路径 |
+| `budgetMonthlyCents` | number | 月度预算限额 |
+| `createdAt` | string | ISO 时间戳 |
+| `updatedAt` | string | ISO 时间戳 |
diff --git a/docs/api/costs.md b/docs/api/costs.md
index 144eb3c920..167466f2bd 100644
--- a/docs/api/costs.md
+++ b/docs/api/costs.md
@@ -1,11 +1,11 @@
---
-title: Costs
-summary: Cost events, summaries, and budget management
+title: 费用
+summary: 费用事件、汇总和预算管理
---
-Track token usage and spending across agents, projects, and the company.
+跟踪代理、项目和公司范围内的令牌使用和支出。
-## Report Cost Event
+## 报告费用事件
```
POST /api/companies/{companyId}/cost-events
@@ -19,53 +19,53 @@ POST /api/companies/{companyId}/cost-events
}
```
-Typically reported automatically by adapters after each heartbeat.
+通常由适配器在每次心跳后自动报告。
-## Company Cost Summary
+## 公司费用汇总
```
GET /api/companies/{companyId}/costs/summary
```
-Returns total spend, budget, and utilization for the current month.
+返回当月的总支出、预算和利用率。
-## Costs by Agent
+## 按代理查看费用
```
GET /api/companies/{companyId}/costs/by-agent
```
-Returns per-agent cost breakdown for the current month.
+返回当月按代理的费用明细。
-## Costs by Project
+## 按项目查看费用
```
GET /api/companies/{companyId}/costs/by-project
```
-Returns per-project cost breakdown for the current month.
+返回当月按项目的费用明细。
-## Budget Management
+## 预算管理
-### Set Company Budget
+### 设置公司预算
```
PATCH /api/companies/{companyId}
{ "budgetMonthlyCents": 100000 }
```
-### Set Agent Budget
+### 设置代理预算
```
PATCH /api/agents/{agentId}
{ "budgetMonthlyCents": 5000 }
```
-## Budget Enforcement
+## 预算执行
-| Threshold | Effect |
+| 阈值 | 效果 |
|-----------|--------|
-| 80% | Soft alert — agent should focus on critical tasks |
-| 100% | Hard stop — agent is auto-paused |
+| 80% | 软警告 — 代理应专注于关键任务 |
+| 100% | 硬停止 — 代理被自动暂停 |
-Budget windows reset on the first of each month (UTC).
+预算窗口在每月一日(UTC)重置。
diff --git a/docs/api/dashboard.md b/docs/api/dashboard.md
index 315b5137d1..669306f4c2 100644
--- a/docs/api/dashboard.md
+++ b/docs/api/dashboard.md
@@ -1,28 +1,28 @@
---
-title: Dashboard
-summary: Dashboard metrics endpoint
+title: 仪表盘
+summary: 仪表盘指标端点
---
-Get a health summary for a company in a single call.
+通过单次调用获取公司的健康摘要。
-## Get Dashboard
+## 获取仪表盘
```
GET /api/companies/{companyId}/dashboard
```
-## Response
+## 响应
-Returns a summary including:
+返回的摘要包括:
-- **Agent counts** by status (active, idle, running, error, paused)
-- **Task counts** by status (backlog, todo, in_progress, blocked, done)
-- **Stale tasks** — tasks in progress with no recent activity
-- **Cost summary** — current month spend vs budget
-- **Recent activity** — latest mutations
+- **代理数量** 按状态统计(active、idle、running、error、paused)
+- **任务数量** 按状态统计(backlog、todo、in_progress、blocked、done)
+- **停滞任务** — 正在进行但近期没有活动的任务
+- **费用摘要** — 当月支出与预算对比
+- **近期活动** — 最新的变更操作
-## Use Cases
+## 使用场景
-- Board operators: quick health check from the web UI
-- CEO agents: situational awareness at the start of each heartbeat
-- Manager agents: check team status and identify blockers
+- 看板操作员:从 Web UI 快速检查健康状态
+- CEO 代理:在每次心跳开始时了解情况
+- 经理代理:检查团队状态并识别阻塞项
diff --git a/docs/api/goals-and-projects.md b/docs/api/goals-and-projects.md
index c669c54dc4..e35503d9bd 100644
--- a/docs/api/goals-and-projects.md
+++ b/docs/api/goals-and-projects.md
@@ -1,27 +1,27 @@
---
-title: Goals and Projects
-summary: Goal hierarchy and project management
+title: 目标和项目
+summary: 目标层级和项目管理
---
-Goals define the "why" and projects define the "what" for organizing work.
+目标定义了"为什么",项目定义了"做什么",用于组织工作。
-## Goals
+## 目标
-Goals form a hierarchy: company goals break down into team goals, which break down into agent-level goals.
+目标形成层级结构:公司目标分解为团队目标,团队目标分解为代理级别目标。
-### List Goals
+### 列出目标
```
GET /api/companies/{companyId}/goals
```
-### Get Goal
+### 获取目标
```
GET /api/goals/{goalId}
```
-### Create Goal
+### 创建目标
```
POST /api/companies/{companyId}/goals
@@ -33,7 +33,7 @@ POST /api/companies/{companyId}/goals
}
```
-### Update Goal
+### 更新目标
```
PATCH /api/goals/{goalId}
@@ -43,27 +43,27 @@ PATCH /api/goals/{goalId}
}
```
-Valid status values: `planned`, `active`, `achieved`, `cancelled`.
+有效的状态值:`planned`、`active`、`achieved`、`cancelled`。
-## Projects
+## 项目
-Projects group related issues toward a deliverable. They can be linked to goals and have workspaces (repository/directory configurations).
+项目将相关问题分组为一个可交付成果。它们可以关联到目标,并拥有工作区(仓库/目录配置)。
-### List Projects
+### 列出项目
```
GET /api/companies/{companyId}/projects
```
-### Get Project
+### 获取项目
```
GET /api/projects/{projectId}
```
-Returns project details including workspaces.
+返回项目详情,包括工作区。
-### Create Project
+### 创建项目
```
POST /api/companies/{companyId}/projects
@@ -82,13 +82,13 @@ POST /api/companies/{companyId}/projects
}
```
-Notes:
+说明:
-- `workspace` is optional. If present, the project is created and seeded with that workspace.
-- A workspace must include at least one of `cwd` or `repoUrl`.
-- For repo-only projects, omit `cwd` and provide `repoUrl`.
+- `workspace` 为可选项。如果存在,项目将被创建并以该工作区作为初始化种子。
+- 工作区必须至少包含 `cwd` 或 `repoUrl` 之一。
+- 对于仅有仓库的项目,省略 `cwd` 并提供 `repoUrl`。
-### Update Project
+### 更新项目
```
PATCH /api/projects/{projectId}
@@ -97,9 +97,9 @@ PATCH /api/projects/{projectId}
}
```
-## Project Workspaces
+## 项目工作区
-Workspaces link a project to a repository and directory:
+工作区将项目关联到仓库和目录:
```
POST /api/projects/{projectId}/workspaces
@@ -112,9 +112,9 @@ POST /api/projects/{projectId}/workspaces
}
```
-Agents use the primary workspace to determine their working directory for project-scoped tasks.
+代理使用主工作区来确定项目范围任务的工作目录。
-### Manage Workspaces
+### 管理工作区
```
GET /api/projects/{projectId}/workspaces
diff --git a/docs/api/issues.md b/docs/api/issues.md
index 12fb028b09..9c609de5d4 100644
--- a/docs/api/issues.md
+++ b/docs/api/issues.md
@@ -1,41 +1,41 @@
---
-title: Issues
-summary: Issue CRUD, checkout/release, comments, documents, and attachments
+title: 问题
+summary: 问题 CRUD、签出/释放、评论、文档和附件
---
-Issues are the unit of work in Paperclip. They support hierarchical relationships, atomic checkout, comments, keyed text documents, and file attachments.
+问题是 Paperclip 中的工作单元。它们支持层级关系、原子签出、评论、带键文本文档和文件附件。
-## List Issues
+## 列出问题
```
GET /api/companies/{companyId}/issues
```
-Query parameters:
+查询参数:
-| Param | Description |
+| 参数 | 描述 |
|-------|-------------|
-| `status` | Filter by status (comma-separated: `todo,in_progress`) |
-| `assigneeAgentId` | Filter by assigned agent |
-| `projectId` | Filter by project |
+| `status` | 按状态筛选(逗号分隔:`todo,in_progress`) |
+| `assigneeAgentId` | 按分配的代理筛选 |
+| `projectId` | 按项目筛选 |
-Results sorted by priority.
+结果按优先级排序。
-## Get Issue
+## 获取问题
```
GET /api/issues/{issueId}
```
-Returns the issue with `project`, `goal`, and `ancestors` (parent chain with their projects and goals).
+返回问题及其 `project`、`goal` 和 `ancestors`(父级链及其项目和目标)。
-The response also includes:
+响应还包括:
-- `planDocument`: the full text of the issue document with key `plan`, when present
-- `documentSummaries`: metadata for all linked issue documents
-- `legacyPlanDocument`: a read-only fallback when the description still contains an old `` block
+- `planDocument`:键为 `plan` 的问题文档的完整文本(如果存在)
+- `documentSummaries`:所有关联问题文档的元数据
+- `legacyPlanDocument`:当描述中仍包含旧的 `` 块时的只读备选
-## Create Issue
+## 创建问题
```
POST /api/companies/{companyId}/issues
@@ -51,7 +51,7 @@ POST /api/companies/{companyId}/issues
}
```
-## Update Issue
+## 更新问题
```
PATCH /api/issues/{issueId}
@@ -62,11 +62,11 @@ Headers: X-Paperclip-Run-Id: {runId}
}
```
-The optional `comment` field adds a comment in the same call.
+可选的 `comment` 字段在同一调用中添加评论。
-Updatable fields: `title`, `description`, `status`, `priority`, `assigneeAgentId`, `projectId`, `goalId`, `parentId`, `billingCode`.
+可更新字段:`title`、`description`、`status`、`priority`、`assigneeAgentId`、`projectId`、`goalId`、`parentId`、`billingCode`。
-## Checkout (Claim Task)
+## 签出(认领任务)
```
POST /api/issues/{issueId}/checkout
@@ -77,11 +77,11 @@ Headers: X-Paperclip-Run-Id: {runId}
}
```
-Atomically claims the task and transitions to `in_progress`. Returns `409 Conflict` if another agent owns it. **Never retry a 409.**
+原子性地认领任务并转换为 `in_progress`。如果另一个代理已拥有该任务,则返回 `409 Conflict`。**切勿重试 409。**
-Idempotent if you already own the task.
+如果您已经拥有该任务,则操作是幂等的。
-**Re-claiming after a crashed run:** If your previous run crashed while holding a task in `in_progress`, the new run must include `"in_progress"` in `expectedStatuses` to re-claim it:
+**崩溃运行后重新认领:** 如果您之前的运行在持有 `in_progress` 状态的任务时崩溃,新运行必须在 `expectedStatuses` 中包含 `"in_progress"` 以重新认领:
```
POST /api/issues/{issueId}/checkout
@@ -92,50 +92,50 @@ Headers: X-Paperclip-Run-Id: {runId}
}
```
-The server will adopt the stale lock if the previous run is no longer active. **The `runId` field is not accepted in the request body** — it comes exclusively from the `X-Paperclip-Run-Id` header (via the agent's JWT).
+如果之前的运行不再活跃,服务器将接管过期的锁。**请求体中不接受 `runId` 字段** — 它只来自 `X-Paperclip-Run-Id` 头(通过代理的 JWT)。
-## Release Task
+## 释放任务
```
POST /api/issues/{issueId}/release
```
-Releases your ownership of the task.
+释放您对任务的所有权。
-## Comments
+## 评论
-### List Comments
+### 列出评论
```
GET /api/issues/{issueId}/comments
```
-### Add Comment
+### 添加评论
```
POST /api/issues/{issueId}/comments
{ "body": "Progress update in markdown..." }
```
-@-mentions (`@AgentName`) in comments trigger heartbeats for the mentioned agent.
+评论中的 @提及(`@AgentName`)会为被提及的代理触发心跳。
-## Documents
+## 文档
-Documents are editable, revisioned, text-first issue artifacts keyed by a stable identifier such as `plan`, `design`, or `notes`.
+文档是可编辑的、有版本的、以文本为主的问题工件,通过稳定标识符(如 `plan`、`design` 或 `notes`)作为键。
-### List
+### 列表
```
GET /api/issues/{issueId}/documents
```
-### Get By Key
+### 按键获取
```
GET /api/issues/{issueId}/documents/{key}
```
-### Create Or Update
+### 创建或更新
```
PUT /api/issues/{issueId}/documents/{key}
@@ -147,54 +147,54 @@ PUT /api/issues/{issueId}/documents/{key}
}
```
-Rules:
+规则:
-- omit `baseRevisionId` when creating a new document
-- provide the current `baseRevisionId` when updating an existing document
-- stale `baseRevisionId` returns `409 Conflict`
+- 创建新文档时省略 `baseRevisionId`
+- 更新现有文档时提供当前的 `baseRevisionId`
+- 过期的 `baseRevisionId` 返回 `409 Conflict`
-### Revision History
+### 修订历史
```
GET /api/issues/{issueId}/documents/{key}/revisions
```
-### Delete
+### 删除
```
DELETE /api/issues/{issueId}/documents/{key}
```
-Delete is board-only in the current implementation.
+在当前实现中,删除仅限看板操作员使用。
-## Attachments
+## 附件
-### Upload
+### 上传
```
POST /api/companies/{companyId}/issues/{issueId}/attachments
Content-Type: multipart/form-data
```
-### List
+### 列表
```
GET /api/issues/{issueId}/attachments
```
-### Download
+### 下载
```
GET /api/attachments/{attachmentId}/content
```
-### Delete
+### 删除
```
DELETE /api/attachments/{attachmentId}
```
-## Issue Lifecycle
+## 问题生命周期
```
backlog -> todo -> in_progress -> in_review -> done
@@ -202,7 +202,7 @@ backlog -> todo -> in_progress -> in_review -> done
blocked in_progress
```
-- `in_progress` requires checkout (single assignee)
-- `started_at` auto-set on `in_progress`
-- `completed_at` auto-set on `done`
-- Terminal states: `done`, `cancelled`
+- `in_progress` 需要签出(单一受让人)
+- `started_at` 在进入 `in_progress` 时自动设置
+- `completed_at` 在进入 `done` 时自动设置
+- 终态:`done`、`cancelled`
diff --git a/docs/api/overview.md b/docs/api/overview.md
index 416baae337..f3621293e6 100644
--- a/docs/api/overview.md
+++ b/docs/api/overview.md
@@ -1,39 +1,39 @@
---
-title: API Overview
-summary: Authentication, base URL, error codes, and conventions
+title: API 概览
+summary: 认证、基础 URL、错误码和约定
---
-Paperclip exposes a RESTful JSON API for all control plane operations.
+Paperclip 为所有控制平面操作提供 RESTful JSON API。
-## Base URL
+## 基础 URL
-Default: `http://localhost:3100/api`
+默认值:`http://localhost:3100/api`
-All endpoints are prefixed with `/api`.
+所有端点均以 `/api` 为前缀。
-## Authentication
+## 认证
-All requests require an `Authorization` header:
+所有请求都需要一个 `Authorization` 头:
```
Authorization: Bearer
```
-Tokens are either:
+令牌类型包括:
-- **Agent API keys** — long-lived keys created for agents
-- **Agent run JWTs** — short-lived tokens injected during heartbeats (`PAPERCLIP_API_KEY`)
-- **User session cookies** — for board operators using the web UI
+- **Agent API 密钥** — 为代理创建的长期密钥
+- **Agent 运行 JWT** — 在心跳期间注入的短期令牌(`PAPERCLIP_API_KEY`)
+- **用户会话 Cookie** — 供使用 Web UI 的看板操作员使用
-## Request Format
+## 请求格式
-- All request bodies are JSON with `Content-Type: application/json`
-- Company-scoped endpoints require `:companyId` in the path
-- Run audit trail: include `X-Paperclip-Run-Id` header on all mutating requests during heartbeats
+- 所有请求体均为 JSON,使用 `Content-Type: application/json`
+- 公司范围的端点要求路径中包含 `:companyId`
+- 运行审计追踪:在心跳期间的所有变更请求中包含 `X-Paperclip-Run-Id` 头
-## Response Format
+## 响应格式
-All responses return JSON. Successful responses return the entity directly. Errors return:
+所有响应返回 JSON。成功响应直接返回实体。错误响应返回:
```json
{
@@ -41,22 +41,22 @@ All responses return JSON. Successful responses return the entity directly. Erro
}
```
-## Error Codes
+## 错误码
-| Code | Meaning | What to Do |
+| 状态码 | 含义 | 处理方式 |
|------|---------|------------|
-| `400` | Validation error | Check request body against expected fields |
-| `401` | Unauthenticated | API key missing or invalid |
-| `403` | Unauthorized | You don't have permission for this action |
-| `404` | Not found | Entity doesn't exist or isn't in your company |
-| `409` | Conflict | Another agent owns the task. Pick a different one. **Do not retry.** |
-| `422` | Semantic violation | Invalid state transition (e.g. backlog -> done) |
-| `500` | Server error | Transient failure. Comment on the task and move on. |
+| `400` | 验证错误 | 检查请求体是否符合预期字段 |
+| `401` | 未认证 | API 密钥缺失或无效 |
+| `403` | 未授权 | 您没有执行此操作的权限 |
+| `404` | 未找到 | 实体不存在或不在您的公司中 |
+| `409` | 冲突 | 另一个代理拥有该任务。请选择其他任务。**请勿重试。** |
+| `422` | 语义违规 | 无效的状态转换(例如 backlog -> done) |
+| `500` | 服务器错误 | 暂时性故障。在任务上评论并继续。 |
-## Pagination
+## 分页
-List endpoints support standard pagination query parameters when applicable. Results are sorted by priority for issues and by creation date for other entities.
+列表端点在适用时支持标准分页查询参数。问题按优先级排序,其他实体按创建日期排序。
-## Rate Limiting
+## 速率限制
-No rate limiting is enforced in local deployments. Production deployments may add rate limiting at the infrastructure level.
+本地部署不强制速率限制。生产环境部署可能在基础设施层面添加速率限制。
diff --git a/docs/api/routines.md b/docs/api/routines.md
index eb6b9adc38..7da39ee878 100644
--- a/docs/api/routines.md
+++ b/docs/api/routines.md
@@ -1,27 +1,27 @@
---
-title: Routines
-summary: Recurring task scheduling, triggers, and run history
+title: 例程
+summary: 循环任务调度、触发器和运行历史
---
-Routines are recurring tasks that fire on a schedule, webhook, or API call and create a heartbeat run for the assigned agent.
+例程是按计划、Webhook 或 API 调用触发的循环任务,会为指定代理创建心跳运行。
-## List Routines
+## 列出例程
```
GET /api/companies/{companyId}/routines
```
-Returns all routines in the company.
+返回公司中的所有例程。
-## Get Routine
+## 获取例程
```
GET /api/routines/{routineId}
```
-Returns routine details including triggers.
+返回例程详情,包括触发器。
-## Create Routine
+## 创建例程
```
POST /api/companies/{companyId}/routines
@@ -38,39 +38,39 @@ POST /api/companies/{companyId}/routines
}
```
-**Agents can only create routines assigned to themselves.** Board operators can assign to any agent.
+**代理只能创建分配给自己的例程。** 看板操作员可以分配给任何代理。
-Fields:
+字段:
-| Field | Required | Description |
+| 字段 | 必填 | 描述 |
|-------|----------|-------------|
-| `title` | yes | Routine name |
-| `description` | no | Human-readable description of the routine |
-| `assigneeAgentId` | yes | Agent who receives each run |
-| `projectId` | yes | Project this routine belongs to |
-| `goalId` | no | Goal to link runs to |
-| `parentIssueId` | no | Parent issue for created run issues |
-| `priority` | no | `critical`, `high`, `medium` (default), `low` |
-| `status` | no | `active` (default), `paused`, `archived` |
-| `concurrencyPolicy` | no | Behaviour when a run fires while a previous one is still active |
-| `catchUpPolicy` | no | Behaviour for missed scheduled runs |
-
-**Concurrency policies:**
-
-| Value | Behaviour |
+| `title` | 是 | 例程名称 |
+| `description` | 否 | 例程的可读描述 |
+| `assigneeAgentId` | 是 | 接收每次运行的代理 |
+| `projectId` | 是 | 此例程所属的项目 |
+| `goalId` | 否 | 关联运行的目标 |
+| `parentIssueId` | 否 | 创建的运行问题的父问题 |
+| `priority` | 否 | `critical`、`high`、`medium`(默认)、`low` |
+| `status` | 否 | `active`(默认)、`paused`、`archived` |
+| `concurrencyPolicy` | 否 | 当前一次运行仍在活动时触发新运行的行为 |
+| `catchUpPolicy` | 否 | 错过的计划运行的处理行为 |
+
+**并发策略:**
+
+| 值 | 行为 |
|-------|-----------|
-| `coalesce_if_active` (default) | Incoming run is immediately finalised as `coalesced` and linked to the active run — no new issue is created |
-| `skip_if_active` | Incoming run is immediately finalised as `skipped` and linked to the active run — no new issue is created |
-| `always_enqueue` | Always create a new run regardless of active runs |
+| `coalesce_if_active`(默认) | 传入运行立即完成为 `coalesced` 并关联到活动运行 — 不创建新问题 |
+| `skip_if_active` | 传入运行立即完成为 `skipped` 并关联到活动运行 — 不创建新问题 |
+| `always_enqueue` | 无论是否有活动运行,始终创建新运行 |
-**Catch-up policies:**
+**补执行策略:**
-| Value | Behaviour |
+| 值 | 行为 |
|-------|-----------|
-| `skip_missed` (default) | Missed scheduled runs are dropped |
-| `enqueue_missed_with_cap` | Missed runs are enqueued up to an internal cap |
+| `skip_missed`(默认) | 错过的计划运行被丢弃 |
+| `enqueue_missed_with_cap` | 错过的运行被加入队列,最多不超过内部上限 |
-## Update Routine
+## 更新例程
```
PATCH /api/routines/{routineId}
@@ -79,17 +79,17 @@ PATCH /api/routines/{routineId}
}
```
-All fields from create are updatable. **Agents can only update routines assigned to themselves and cannot reassign a routine to another agent.**
+创建时的所有字段均可更新。**代理只能更新分配给自己的例程,且不能将例程重新分配给其他代理。**
-## Add Trigger
+## 添加触发器
```
POST /api/routines/{routineId}/triggers
```
-Three trigger kinds:
+三种触发器类型:
-**Schedule** — fires on a cron expression:
+**计划** — 按 cron 表达式触发:
```
{
@@ -99,7 +99,7 @@ Three trigger kinds:
}
```
-**Webhook** — fires on an inbound HTTP POST to a generated URL:
+**Webhook** — 通过入站 HTTP POST 到生成的 URL 触发:
```
{
@@ -109,9 +109,9 @@ Three trigger kinds:
}
```
-Signing modes: `bearer` (default), `hmac_sha256`. Replay window range: 30–86400 seconds (default 300).
+签名模式:`bearer`(默认)、`hmac_sha256`。重放窗口范围:30-86400 秒(默认 300)。
-**API** — fires only when called explicitly via [Manual Run](#manual-run):
+**API** — 仅在通过[手动运行](#手动运行)显式调用时触发:
```
{
@@ -119,9 +119,9 @@ Signing modes: `bearer` (default), `hmac_sha256`. Replay window range: 30–8640
}
```
-A routine can have multiple triggers of different kinds.
+一个例程可以拥有多个不同类型的触发器。
-## Update Trigger
+## 更新触发器
```
PATCH /api/routine-triggers/{triggerId}
@@ -131,21 +131,21 @@ PATCH /api/routine-triggers/{triggerId}
}
```
-## Delete Trigger
+## 删除触发器
```
DELETE /api/routine-triggers/{triggerId}
```
-## Rotate Trigger Secret
+## 轮换触发器密钥
```
POST /api/routine-triggers/{triggerId}/rotate-secret
```
-Generates a new signing secret for webhook triggers. The previous secret is immediately invalidated.
+为 Webhook 触发器生成新的签名密钥。之前的密钥立即失效。
-## Manual Run
+## 手动运行
```
POST /api/routines/{routineId}/run
@@ -157,45 +157,45 @@ POST /api/routines/{routineId}/run
}
```
-Fires a run immediately, bypassing the schedule. Concurrency policy still applies.
+立即触发一次运行,绕过计划。并发策略仍然适用。
-`triggerId` is optional. When supplied, the server validates the trigger belongs to this routine (`403`) and is enabled (`409`), then records the run against that trigger and updates its `lastFiredAt`. Omit it for a generic manual run with no trigger attribution.
+`triggerId` 为可选项。提供时,服务器会验证触发器属于此例程(`403`)且已启用(`409`),然后将运行记录到该触发器并更新其 `lastFiredAt`。省略它可进行无触发器归属的通用手动运行。
-## Fire Public Trigger
+## 触发公共触发器
```
POST /api/routine-triggers/public/{publicId}/fire
```
-Fires a webhook trigger from an external system. Requires a valid `Authorization` or `X-Paperclip-Signature` + `X-Paperclip-Timestamp` header pair matching the trigger's signing mode.
+从外部系统触发 Webhook 触发器。需要有效的 `Authorization` 或与触发器签名模式匹配的 `X-Paperclip-Signature` + `X-Paperclip-Timestamp` 头对。
-## List Runs
+## 列出运行
```
GET /api/routines/{routineId}/runs?limit=50
```
-Returns recent run history for the routine. Defaults to 50 most recent runs.
+返回例程的近期运行历史。默认返回最近 50 次运行。
-## Agent Access Rules
+## 代理访问规则
-Agents can read all routines in their company but can only create and manage routines assigned to themselves:
+代理可以读取其公司中的所有例程,但只能创建和管理分配给自己的例程:
-| Operation | Agent | Board |
+| 操作 | 代理 | 看板 |
|-----------|-------|-------|
-| List / Get | ✅ any routine | ✅ |
-| Create | ✅ own only | ✅ |
-| Update / activate | ✅ own only | ✅ |
-| Add / update / delete triggers | ✅ own only | ✅ |
-| Rotate trigger secret | ✅ own only | ✅ |
-| Manual run | ✅ own only | ✅ |
-| Reassign to another agent | ❌ | ✅ |
+| 列出 / 获取 | ✅ 任何例程 | ✅ |
+| 创建 | ✅ 仅自己的 | ✅ |
+| 更新 / 激活 | ✅ 仅自己的 | ✅ |
+| 添加 / 更新 / 删除触发器 | ✅ 仅自己的 | ✅ |
+| 轮换触发器密钥 | ✅ 仅自己的 | ✅ |
+| 手动运行 | ✅ 仅自己的 | ✅ |
+| 重新分配给其他代理 | ❌ | ✅ |
-## Routine Lifecycle
+## 例程生命周期
```
active -> paused -> active
-> archived
```
-Archived routines do not fire and cannot be reactivated.
+已归档的例程不会触发,且无法重新激活。
diff --git a/docs/api/secrets.md b/docs/api/secrets.md
index 49a36e0e43..67e7396b8e 100644
--- a/docs/api/secrets.md
+++ b/docs/api/secrets.md
@@ -1,19 +1,19 @@
---
-title: Secrets
-summary: Secrets CRUD
+title: 密钥
+summary: 密钥 CRUD
---
-Manage encrypted secrets that agents reference in their environment configuration.
+管理代理在其环境配置中引用的加密密钥。
-## List Secrets
+## 列出密钥
```
GET /api/companies/{companyId}/secrets
```
-Returns secret metadata (not decrypted values).
+返回密钥元数据(不包含解密后的值)。
-## Create Secret
+## 创建密钥
```
POST /api/companies/{companyId}/secrets
@@ -23,9 +23,9 @@ POST /api/companies/{companyId}/secrets
}
```
-The value is encrypted at rest. Only the secret ID and metadata are returned.
+值在存储时加密。只返回密钥 ID 和元数据。
-## Update Secret
+## 更新密钥
```
PATCH /api/secrets/{secretId}
@@ -34,11 +34,11 @@ PATCH /api/secrets/{secretId}
}
```
-Creates a new version of the secret. Agents referencing `"version": "latest"` automatically get the new value on next heartbeat.
+创建密钥的新版本。引用 `"version": "latest"` 的代理会在下次心跳时自动获取新值。
-## Using Secrets in Agent Config
+## 在代理配置中使用密钥
-Reference secrets in agent adapter config instead of inline values:
+在代理适配器配置中引用密钥,而非内联值:
```json
{
@@ -52,4 +52,4 @@ Reference secrets in agent adapter config instead of inline values:
}
```
-The server resolves and decrypts secret references at runtime, injecting the real value into the agent process environment.
+服务器在运行时解析并解密密钥引用,将实际值注入代理进程环境。
diff --git a/docs/cli/control-plane-commands.md b/docs/cli/control-plane-commands.md
index 80eb0edbfa..c9982ed6b1 100644
--- a/docs/cli/control-plane-commands.md
+++ b/docs/cli/control-plane-commands.md
@@ -1,11 +1,11 @@
---
-title: Control-Plane Commands
-summary: Issue, agent, approval, and dashboard commands
+title: 控制平面命令
+summary: 工单、代理、审批和仪表板命令
---
-Client-side commands for managing issues, agents, approvals, and more.
+用于管理工单、代理、审批等的客户端命令。
-## Issue Commands
+## 工单命令
```sh
# List issues
@@ -30,7 +30,7 @@ pnpm paperclipai issue checkout --agent-id
pnpm paperclipai issue release
```
-## Company Commands
+## 公司命令
```sh
pnpm paperclipai company list
@@ -56,14 +56,14 @@ pnpm paperclipai company import \
--include company,agents
```
-## Agent Commands
+## 代理命令
```sh
pnpm paperclipai agent list
pnpm paperclipai agent get
```
-## Approval Commands
+## 审批命令
```sh
# List approvals
@@ -91,19 +91,19 @@ pnpm paperclipai approval resubmit [--payload '{"..."}']
pnpm paperclipai approval comment --body "..."
```
-## Activity Commands
+## 活动命令
```sh
pnpm paperclipai activity list [--agent-id ] [--entity-type issue] [--entity-id ]
```
-## Dashboard
+## 仪表板
```sh
pnpm paperclipai dashboard get
```
-## Heartbeat
+## 心跳
```sh
pnpm paperclipai heartbeat run --agent-id [--api-base http://localhost:3100]
diff --git a/docs/cli/overview.md b/docs/cli/overview.md
index 8bcf78aa95..a5aa32ab84 100644
--- a/docs/cli/overview.md
+++ b/docs/cli/overview.md
@@ -1,67 +1,67 @@
---
-title: CLI Overview
-summary: CLI installation and setup
+title: CLI 概览
+summary: CLI 安装和设置
---
-The Paperclip CLI handles instance setup, diagnostics, and control-plane operations.
+Paperclip CLI 处理实例设置、诊断和控制平面操作。
-## Usage
+## 用法
```sh
pnpm paperclipai --help
```
-## Global Options
+## 全局选项
-All commands support:
+所有命令支持:
-| Flag | Description |
+| 标志 | 描述 |
|------|-------------|
-| `--data-dir ` | Local Paperclip data root (isolates from `~/.paperclip`) |
-| `--api-base ` | API base URL |
-| `--api-key ` | API authentication token |
-| `--context ` | Context file path |
-| `--profile ` | Context profile name |
-| `--json` | Output as JSON |
+| `--data-dir ` | 本地 Paperclip 数据根目录(与 `~/.paperclip` 隔离) |
+| `--api-base ` | API 基础 URL |
+| `--api-key ` | API 认证令牌 |
+| `--context ` | 上下文文件路径 |
+| `--profile ` | 上下文配置文件名称 |
+| `--json` | 以 JSON 格式输出 |
-Company-scoped commands also accept `--company-id `.
+公司级命令还接受 `--company-id `。
-For clean local instances, pass `--data-dir` on the command you run:
+对于干净的本地实例,在运行的命令上传递 `--data-dir`:
```sh
pnpm paperclipai run --data-dir ./tmp/paperclip-dev
```
-## Context Profiles
+## 上下文配置文件
-Store defaults to avoid repeating flags:
+存储默认值以避免重复输入标志:
```sh
-# Set defaults
+# 设置默认值
pnpm paperclipai context set --api-base http://localhost:3100 --company-id
-# View current context
+# 查看当前上下文
pnpm paperclipai context show
-# List profiles
+# 列出配置文件
pnpm paperclipai context list
-# Switch profile
+# 切换配置文件
pnpm paperclipai context use default
```
-To avoid storing secrets in context, use an env var:
+为避免在上下文中存储密钥,请使用环境变量:
```sh
pnpm paperclipai context set --api-key-env-var-name PAPERCLIP_API_KEY
export PAPERCLIP_API_KEY=...
```
-Context is stored at `~/.paperclip/context.json`.
+上下文存储在 `~/.paperclip/context.json`。
-## Command Categories
+## 命令类别
-The CLI has two categories:
+CLI 有两个类别:
-1. **[Setup commands](/cli/setup-commands)** — instance bootstrap, diagnostics, configuration
-2. **[Control-plane commands](/cli/control-plane-commands)** — issues, agents, approvals, activity
+1. **[设置命令](/cli/setup-commands)** — 实例引导、诊断、配置
+2. **[控制平面命令](/cli/control-plane-commands)** — 工单、代理、审批、活动
diff --git a/docs/cli/setup-commands.md b/docs/cli/setup-commands.md
index 7dc5cd6ad0..ee4038eecf 100644
--- a/docs/cli/setup-commands.md
+++ b/docs/cli/setup-commands.md
@@ -1,25 +1,25 @@
---
-title: Setup Commands
-summary: Onboard, run, doctor, and configure
+title: 设置命令
+summary: 初始化、运行、诊断和配置
---
-Instance setup and diagnostics commands.
+实例设置和诊断命令。
## `paperclipai run`
-One-command bootstrap and start:
+一条命令完成引导和启动:
```sh
pnpm paperclipai run
```
-Does:
+功能:
-1. Auto-onboards if config is missing
-2. Runs `paperclipai doctor` with repair enabled
-3. Starts the server when checks pass
+1. 如果缺少配置,自动进行初始化设置
+2. 运行 `paperclipai doctor` 并启用修复功能
+3. 检查通过后启动服务器
-Choose a specific instance:
+选择特定实例:
```sh
pnpm paperclipai run --instance dev
@@ -27,24 +27,24 @@ pnpm paperclipai run --instance dev
## `paperclipai onboard`
-Interactive first-time setup:
+交互式首次设置:
```sh
pnpm paperclipai onboard
```
-First prompt:
+首个提示:
-1. `Quickstart` (recommended): local defaults (embedded database, no LLM provider, local disk storage, default secrets)
-2. `Advanced setup`: full interactive configuration
+1. `Quickstart`(推荐):本地默认设置(内嵌数据库、无 LLM 提供商、本地磁盘存储、默认密钥)
+2. `Advanced setup`:完整的交互式配置
-Start immediately after onboarding:
+初始化设置后立即启动:
```sh
pnpm paperclipai onboard --run
```
-Non-interactive defaults + immediate start (opens browser on server listen):
+非交互式默认设置 + 立即启动(服务器监听后打开浏览器):
```sh
pnpm paperclipai onboard --yes
@@ -52,24 +52,24 @@ pnpm paperclipai onboard --yes
## `paperclipai doctor`
-Health checks with optional auto-repair:
+带可选自动修复的健康检查:
```sh
pnpm paperclipai doctor
pnpm paperclipai doctor --repair
```
-Validates:
+验证内容:
-- Server configuration
-- Database connectivity
-- Secrets adapter configuration
-- Storage configuration
-- Missing key files
+- 服务器配置
+- 数据库连接
+- 密钥适配器配置
+- 存储配置
+- 缺失的关键文件
## `paperclipai configure`
-Update configuration sections:
+更新配置部分:
```sh
pnpm paperclipai configure --section server
@@ -79,7 +79,7 @@ pnpm paperclipai configure --section storage
## `paperclipai env`
-Show resolved environment configuration:
+显示解析后的环境配置:
```sh
pnpm paperclipai env
@@ -87,29 +87,29 @@ pnpm paperclipai env
## `paperclipai allowed-hostname`
-Allow a private hostname for authenticated/private mode:
+为已认证/私有模式允许一个私有主机名:
```sh
pnpm paperclipai allowed-hostname my-tailscale-host
```
-## Local Storage Paths
+## 本地存储路径
-| Data | Default Path |
+| 数据 | 默认路径 |
|------|-------------|
-| Config | `~/.paperclip/instances/default/config.json` |
-| Database | `~/.paperclip/instances/default/db` |
-| Logs | `~/.paperclip/instances/default/logs` |
-| Storage | `~/.paperclip/instances/default/data/storage` |
-| Secrets key | `~/.paperclip/instances/default/secrets/master.key` |
+| 配置 | `~/.paperclip/instances/default/config.json` |
+| 数据库 | `~/.paperclip/instances/default/db` |
+| 日志 | `~/.paperclip/instances/default/logs` |
+| 存储 | `~/.paperclip/instances/default/data/storage` |
+| 密钥文件 | `~/.paperclip/instances/default/secrets/master.key` |
-Override with:
+通过以下方式覆盖:
```sh
PAPERCLIP_HOME=/custom/home PAPERCLIP_INSTANCE_ID=dev pnpm paperclipai run
```
-Or pass `--data-dir` directly on any command:
+或在任何命令上直接传递 `--data-dir`:
```sh
pnpm paperclipai run --data-dir ./tmp/paperclip-dev
diff --git a/docs/deploy/database.md b/docs/deploy/database.md
index a454de9b33..2d3cd29c27 100644
--- a/docs/deploy/database.md
+++ b/docs/deploy/database.md
@@ -1,62 +1,62 @@
---
-title: Database
-summary: Embedded PGlite vs Docker Postgres vs hosted
+title: 数据库
+summary: 内嵌 PGlite vs Docker Postgres vs 托管方案
---
-Paperclip uses PostgreSQL via Drizzle ORM. There are three ways to run the database.
+Paperclip 通过 Drizzle ORM 使用 PostgreSQL。有三种方式运行数据库。
-## 1. Embedded PostgreSQL (Default)
+## 1. 内嵌 PostgreSQL(默认)
-Zero config. If you don't set `DATABASE_URL`, the server starts an embedded PostgreSQL instance automatically.
+零配置。如果未设置 `DATABASE_URL`,服务器会自动启动内嵌的 PostgreSQL 实例。
```sh
pnpm dev
```
-On first start, the server:
+首次启动时,服务器会:
-1. Creates `~/.paperclip/instances/default/db/` for storage
-2. Ensures the `paperclip` database exists
-3. Runs migrations automatically
-4. Starts serving requests
+1. 创建 `~/.paperclip/instances/default/db/` 用于存储
+2. 确保 `paperclip` 数据库存在
+3. 自动运行迁移
+4. 开始处理请求
-Data persists across restarts. To reset: `rm -rf ~/.paperclip/instances/default/db`.
+数据在重启后持久保存。要重置:`rm -rf ~/.paperclip/instances/default/db`。
-The Docker quickstart also uses embedded PostgreSQL by default.
+Docker 快速启动默认也使用内嵌 PostgreSQL。
-## 2. Local PostgreSQL (Docker)
+## 2. 本地 PostgreSQL(Docker)
-For a full PostgreSQL server locally:
+如需在本地运行完整的 PostgreSQL 服务器:
```sh
docker compose up -d
```
-This starts PostgreSQL 17 on `localhost:5432`. Set the connection string:
+这将在 `localhost:5432` 上启动 PostgreSQL 17。设置连接字符串:
```sh
cp .env.example .env
# DATABASE_URL=postgres://paperclip:paperclip@localhost:5432/paperclip
```
-Push the schema:
+推送模式:
```sh
DATABASE_URL=postgres://paperclip:paperclip@localhost:5432/paperclip \
npx drizzle-kit push
```
-## 3. Hosted PostgreSQL (Supabase)
+## 3. 托管 PostgreSQL(Supabase)
-For production, use a hosted provider like [Supabase](https://supabase.com/).
+对于生产环境,使用托管提供商如 [Supabase](https://supabase.com/)。
-1. Create a project at [database.new](https://database.new)
-2. Copy the connection string from Project Settings > Database
-3. Set `DATABASE_URL` in your `.env`
+1. 在 [database.new](https://database.new) 创建项目
+2. 从项目设置 > 数据库中复制连接字符串
+3. 在 `.env` 中设置 `DATABASE_URL`
-Use the **direct connection** (port 5432) for migrations and the **pooled connection** (port 6543) for the application.
+使用**直连**(端口 5432)进行迁移,使用**连接池**(端口 6543)运行应用程序。
-If using connection pooling, disable prepared statements:
+如果使用连接池,请禁用预处理语句:
```ts
// packages/db/src/client.ts
@@ -66,12 +66,12 @@ export function createDb(url: string) {
}
```
-## Switching Between Modes
+## 模式切换
-| `DATABASE_URL` | Mode |
+| `DATABASE_URL` | 模式 |
|----------------|------|
-| Not set | Embedded PostgreSQL |
-| `postgres://...localhost...` | Local Docker PostgreSQL |
-| `postgres://...supabase.com...` | Hosted Supabase |
+| 未设置 | 内嵌 PostgreSQL |
+| `postgres://...localhost...` | 本地 Docker PostgreSQL |
+| `postgres://...supabase.com...` | 托管 Supabase |
-The Drizzle schema (`packages/db/src/schema/`) is the same regardless of mode.
+Drizzle 模式(`packages/db/src/schema/`)不受运行模式影响。
diff --git a/docs/deploy/deployment-modes.md b/docs/deploy/deployment-modes.md
index ae567f49b5..1c92023e9f 100644
--- a/docs/deploy/deployment-modes.md
+++ b/docs/deploy/deployment-modes.md
@@ -1,43 +1,43 @@
---
-title: Deployment Modes
-summary: local_trusted vs authenticated (private/public)
+title: 部署模式
+summary: local_trusted vs authenticated(私有/公开)
---
-Paperclip supports two runtime modes with different security profiles.
+Paperclip 支持两种具有不同安全配置的运行模式。
## `local_trusted`
-The default mode. Optimized for single-operator local use.
+默认模式。针对单操作员本地使用进行了优化。
-- **Host binding**: loopback only (localhost)
-- **Authentication**: no login required
-- **Use case**: local development, solo experimentation
-- **Board identity**: auto-created local board user
+- **主机绑定**:仅回环地址(localhost)
+- **认证**:无需登录
+- **使用场景**:本地开发、独立实验
+- **看板身份**:自动创建的本地看板用户
```sh
-# Set during onboard
+# 在引导过程中设置
pnpm paperclipai onboard
-# Choose "local_trusted"
+# 选择 "local_trusted"
```
## `authenticated`
-Login required. Supports two exposure policies.
+需要登录。支持两种暴露策略。
### `authenticated` + `private`
-For private network access (Tailscale, VPN, LAN).
+用于私有网络访问(Tailscale、VPN、LAN)。
-- **Authentication**: login required via Better Auth
-- **URL handling**: auto base URL mode (lower friction)
-- **Host trust**: private-host trust policy required
+- **认证**:需要通过 Better Auth 登录
+- **URL 处理**:自动基础 URL 模式(低摩擦)
+- **主机信任**:需要私有主机信任策略
```sh
pnpm paperclipai onboard
-# Choose "authenticated" -> "private"
+# 选择 "authenticated" -> "private"
```
-Allow custom Tailscale hostnames:
+允许自定义 Tailscale 主机名:
```sh
pnpm paperclipai allowed-hostname my-machine
@@ -45,40 +45,40 @@ pnpm paperclipai allowed-hostname my-machine
### `authenticated` + `public`
-For internet-facing deployment.
+用于面向互联网的部署。
-- **Authentication**: login required
-- **URL**: explicit public URL required
-- **Security**: stricter deployment checks in doctor
+- **认证**:需要登录
+- **URL**:需要显式的公开 URL
+- **安全性**:doctor 中更严格的部署检查
```sh
pnpm paperclipai onboard
-# Choose "authenticated" -> "public"
+# 选择 "authenticated" -> "public"
```
-## Board Claim Flow
+## 看板认领流程
-When migrating from `local_trusted` to `authenticated`, Paperclip emits a one-time claim URL at startup:
+从 `local_trusted` 迁移到 `authenticated` 时,Paperclip 在启动时发出一次性认领 URL:
```
/board-claim/?code=
```
-A signed-in user visits this URL to claim board ownership. This:
+已登录用户访问此 URL 来认领看板所有权。此操作会:
-- Promotes the current user to instance admin
-- Demotes the auto-created local board admin
-- Ensures active company membership for the claiming user
+- 将当前用户提升为实例管理员
+- 降级自动创建的本地看板管理员
+- 确保认领用户具有活跃的公司成员身份
-## Changing Modes
+## 更改模式
-Update the deployment mode:
+更新部署模式:
```sh
pnpm paperclipai configure --section server
```
-Runtime override via environment variable:
+通过环境变量进行运行时覆盖:
```sh
PAPERCLIP_DEPLOYMENT_MODE=authenticated pnpm paperclipai run
diff --git a/docs/deploy/docker.md b/docs/deploy/docker.md
index 0effd4c7de..01fbd6ac80 100644
--- a/docs/deploy/docker.md
+++ b/docs/deploy/docker.md
@@ -1,31 +1,31 @@
---
title: Docker
-summary: Docker Compose quickstart
+summary: Docker Compose 快速启动
---
-Run Paperclip in Docker without installing Node or pnpm locally.
+在 Docker 中运行 Paperclip,无需在本地安装 Node 或 pnpm。
-## Compose Quickstart (Recommended)
+## Compose 快速启动(推荐)
```sh
docker compose -f docker-compose.quickstart.yml up --build
```
-Open [http://localhost:3100](http://localhost:3100).
+打开 [http://localhost:3100](http://localhost:3100)。
-Defaults:
+默认值:
-- Host port: `3100`
-- Data directory: `./data/docker-paperclip`
+- 主机端口:`3100`
+- 数据目录:`./data/docker-paperclip`
-Override with environment variables:
+通过环境变量覆盖:
```sh
PAPERCLIP_PORT=3200 PAPERCLIP_DATA_DIR=./data/pc \
docker compose -f docker-compose.quickstart.yml up --build
```
-## Manual Docker Build
+## 手动 Docker 构建
```sh
docker build -t paperclip-local .
@@ -37,23 +37,23 @@ docker run --name paperclip \
paperclip-local
```
-## Data Persistence
+## 数据持久化
-All data is persisted under the bind mount (`./data/docker-paperclip`):
+所有数据都持久化在绑定挂载目录下(`./data/docker-paperclip`):
-- Embedded PostgreSQL data
-- Uploaded assets
-- Local secrets key
-- Agent workspace data
+- 内嵌 PostgreSQL 数据
+- 上传的资产
+- 本地密钥
+- 代理工作区数据
-## Claude and Codex Adapters in Docker
+## Docker 中的 Claude 和 Codex 适配器
-The Docker image pre-installs:
+Docker 镜像预装了:
-- `claude` (Anthropic Claude Code CLI)
-- `codex` (OpenAI Codex CLI)
+- `claude`(Anthropic Claude Code CLI)
+- `codex`(OpenAI Codex CLI)
-Pass API keys to enable local adapter runs inside the container:
+传入 API 密钥以在容器内启用本地适配器运行:
```sh
docker run --name paperclip \
@@ -66,4 +66,4 @@ docker run --name paperclip \
paperclip-local
```
-Without API keys, the app runs normally — adapter environment checks will surface missing prerequisites.
+不提供 API 密钥时,应用程序正常运行 — 适配器环境检查会提示缺少的前置条件。
diff --git a/docs/deploy/environment-variables.md b/docs/deploy/environment-variables.md
index bc5e4bcc13..e4e3acd309 100644
--- a/docs/deploy/environment-variables.md
+++ b/docs/deploy/environment-variables.md
@@ -1,50 +1,50 @@
---
-title: Environment Variables
-summary: Full environment variable reference
+title: 环境变量
+summary: 完整的环境变量参考
---
-All environment variables that Paperclip uses for server configuration.
+Paperclip 用于服务器配置的所有环境变量。
-## Server Configuration
+## 服务器配置
-| Variable | Default | Description |
+| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
-| `PORT` | `3100` | Server port |
-| `HOST` | `127.0.0.1` | Server host binding |
-| `DATABASE_URL` | (embedded) | PostgreSQL connection string |
-| `PAPERCLIP_HOME` | `~/.paperclip` | Base directory for all Paperclip data |
-| `PAPERCLIP_INSTANCE_ID` | `default` | Instance identifier (for multiple local instances) |
-| `PAPERCLIP_DEPLOYMENT_MODE` | `local_trusted` | Runtime mode override |
+| `PORT` | `3100` | 服务器端口 |
+| `HOST` | `127.0.0.1` | 服务器主机绑定 |
+| `DATABASE_URL` | (内嵌) | PostgreSQL 连接字符串 |
+| `PAPERCLIP_HOME` | `~/.paperclip` | 所有 Paperclip 数据的基础目录 |
+| `PAPERCLIP_INSTANCE_ID` | `default` | 实例标识符(用于多个本地实例) |
+| `PAPERCLIP_DEPLOYMENT_MODE` | `local_trusted` | 运行模式覆盖 |
-## Secrets
+## 密钥
-| Variable | Default | Description |
+| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
-| `PAPERCLIP_SECRETS_MASTER_KEY` | (from file) | 32-byte encryption key (base64/hex/raw) |
-| `PAPERCLIP_SECRETS_MASTER_KEY_FILE` | `~/.paperclip/.../secrets/master.key` | Path to key file |
-| `PAPERCLIP_SECRETS_STRICT_MODE` | `false` | Require secret refs for sensitive env vars |
+| `PAPERCLIP_SECRETS_MASTER_KEY` | (来自文件) | 32 字节加密密钥(base64/hex/原始格式) |
+| `PAPERCLIP_SECRETS_MASTER_KEY_FILE` | `~/.paperclip/.../secrets/master.key` | 密钥文件路径 |
+| `PAPERCLIP_SECRETS_STRICT_MODE` | `false` | 要求敏感环境变量使用密钥引用 |
-## Agent Runtime (Injected into agent processes)
+## 代理运行时(注入到代理进程中)
-These are set automatically by the server when invoking agents:
+这些变量在调用代理时由服务器自动设置:
-| Variable | Description |
+| 变量 | 描述 |
|----------|-------------|
-| `PAPERCLIP_AGENT_ID` | Agent's unique ID |
-| `PAPERCLIP_COMPANY_ID` | Company ID |
-| `PAPERCLIP_API_URL` | Paperclip API base URL |
-| `PAPERCLIP_API_KEY` | Short-lived JWT for API auth |
-| `PAPERCLIP_RUN_ID` | Current heartbeat run ID |
-| `PAPERCLIP_TASK_ID` | Issue that triggered this wake |
-| `PAPERCLIP_WAKE_REASON` | Wake trigger reason |
-| `PAPERCLIP_WAKE_COMMENT_ID` | Comment that triggered this wake |
-| `PAPERCLIP_APPROVAL_ID` | Resolved approval ID |
-| `PAPERCLIP_APPROVAL_STATUS` | Approval decision |
-| `PAPERCLIP_LINKED_ISSUE_IDS` | Comma-separated linked issue IDs |
-
-## LLM Provider Keys (for adapters)
-
-| Variable | Description |
+| `PAPERCLIP_AGENT_ID` | 代理的唯一 ID |
+| `PAPERCLIP_COMPANY_ID` | 公司 ID |
+| `PAPERCLIP_API_URL` | Paperclip API 基础 URL |
+| `PAPERCLIP_API_KEY` | 用于 API 认证的短期 JWT |
+| `PAPERCLIP_RUN_ID` | 当前心跳运行 ID |
+| `PAPERCLIP_TASK_ID` | 触发此唤醒的问题 |
+| `PAPERCLIP_WAKE_REASON` | 唤醒触发原因 |
+| `PAPERCLIP_WAKE_COMMENT_ID` | 触发此唤醒的评论 |
+| `PAPERCLIP_APPROVAL_ID` | 已解决的审批 ID |
+| `PAPERCLIP_APPROVAL_STATUS` | 审批决定 |
+| `PAPERCLIP_LINKED_ISSUE_IDS` | 逗号分隔的关联问题 ID |
+
+## LLM 提供商密钥(用于适配器)
+
+| 变量 | 描述 |
|----------|-------------|
-| `ANTHROPIC_API_KEY` | Anthropic API key (for Claude Local adapter) |
-| `OPENAI_API_KEY` | OpenAI API key (for Codex Local adapter) |
+| `ANTHROPIC_API_KEY` | Anthropic API 密钥(用于 Claude Local 适配器) |
+| `OPENAI_API_KEY` | OpenAI API 密钥(用于 Codex Local 适配器) |
diff --git a/docs/deploy/local-development.md b/docs/deploy/local-development.md
index 874477c133..ecaff83684 100644
--- a/docs/deploy/local-development.md
+++ b/docs/deploy/local-development.md
@@ -1,68 +1,68 @@
---
-title: Local Development
-summary: Set up Paperclip for local development
+title: 本地开发
+summary: 设置 Paperclip 本地开发环境
---
-Run Paperclip locally with zero external dependencies.
+在本地运行 Paperclip,无需任何外部依赖。
-## Prerequisites
+## 前置条件
- Node.js 20+
- pnpm 9+
-## Start Dev Server
+## 启动开发服务器
```sh
pnpm install
pnpm dev
```
-This starts:
+这将启动:
-- **API server** at `http://localhost:3100`
-- **UI** served by the API server in dev middleware mode (same origin)
+- **API 服务器**:位于 `http://localhost:3100`
+- **UI**:由 API 服务器以开发中间件模式提供服务(同源)
-No Docker or external database required. Paperclip uses embedded PostgreSQL automatically.
+无需 Docker 或外部数据库。Paperclip 自动使用内嵌 PostgreSQL。
-## One-Command Bootstrap
+## 一键引导
-For a first-time install:
+首次安装时:
```sh
pnpm paperclipai run
```
-This does:
+此命令会:
-1. Auto-onboards if config is missing
-2. Runs `paperclipai doctor` with repair enabled
-3. Starts the server when checks pass
+1. 如果缺少配置,自动引导
+2. 运行启用修复的 `paperclipai doctor`
+3. 检查通过后启动服务器
-## Tailscale/Private Auth Dev Mode
+## Tailscale/私有认证开发模式
-To run in `authenticated/private` mode for network access:
+要以 `authenticated/private` 模式运行以实现网络访问:
```sh
pnpm dev --tailscale-auth
```
-This binds the server to `0.0.0.0` for private-network access.
+这将把服务器绑定到 `0.0.0.0` 以实现私有网络访问。
-Alias:
+别名:
```sh
pnpm dev --authenticated-private
```
-Allow additional private hostnames:
+允许额外的私有主机名:
```sh
pnpm paperclipai allowed-hostname dotta-macbook-pro
```
-For full setup and troubleshooting, see [Tailscale Private Access](/deploy/tailscale-private-access).
+完整设置和故障排除,请参阅 [Tailscale 私有访问](/deploy/tailscale-private-access)。
-## Health Checks
+## 健康检查
```sh
curl http://localhost:3100/api/health
@@ -72,26 +72,26 @@ curl http://localhost:3100/api/companies
# -> []
```
-## Reset Dev Data
+## 重置开发数据
-To wipe local data and start fresh:
+要清除本地数据并重新开始:
```sh
rm -rf ~/.paperclip/instances/default/db
pnpm dev
```
-## Data Locations
+## 数据位置
-| Data | Path |
+| 数据 | 路径 |
|------|------|
-| Config | `~/.paperclip/instances/default/config.json` |
-| Database | `~/.paperclip/instances/default/db` |
-| Storage | `~/.paperclip/instances/default/data/storage` |
-| Secrets key | `~/.paperclip/instances/default/secrets/master.key` |
-| Logs | `~/.paperclip/instances/default/logs` |
+| 配置 | `~/.paperclip/instances/default/config.json` |
+| 数据库 | `~/.paperclip/instances/default/db` |
+| 存储 | `~/.paperclip/instances/default/data/storage` |
+| 密钥文件 | `~/.paperclip/instances/default/secrets/master.key` |
+| 日志 | `~/.paperclip/instances/default/logs` |
-Override with environment variables:
+通过环境变量覆盖:
```sh
PAPERCLIP_HOME=/custom/path PAPERCLIP_INSTANCE_ID=dev pnpm paperclipai run
diff --git a/docs/deploy/overview.md b/docs/deploy/overview.md
index 3820642f04..a36ac10e73 100644
--- a/docs/deploy/overview.md
+++ b/docs/deploy/overview.md
@@ -1,54 +1,54 @@
---
-title: Deployment Overview
-summary: Deployment modes at a glance
+title: 部署概览
+summary: 部署模式一览
---
-Paperclip supports three deployment configurations, from zero-friction local to internet-facing production.
+Paperclip 支持三种部署配置,从零摩擦的本地部署到面向互联网的生产部署。
-## Deployment Modes
+## 部署模式
-| Mode | Auth | Best For |
+| 模式 | 认证 | 适用场景 |
|------|------|----------|
-| `local_trusted` | No login required | Single-operator local machine |
-| `authenticated` + `private` | Login required | Private network (Tailscale, VPN, LAN) |
-| `authenticated` + `public` | Login required | Internet-facing cloud deployment |
+| `local_trusted` | 无需登录 | 单操作员本地机器 |
+| `authenticated` + `private` | 需要登录 | 私有网络(Tailscale、VPN、LAN) |
+| `authenticated` + `public` | 需要登录 | 面向互联网的云部署 |
-## Quick Comparison
+## 快速对比
-### Local Trusted (Default)
+### 本地信任模式(默认)
-- Loopback-only host binding (localhost)
-- No human login flow
-- Fastest local startup
-- Best for: solo development and experimentation
+- 仅绑定回环地址(localhost)
+- 无人工登录流程
+- 最快的本地启动速度
+- 适用于:独立开发和实验
-### Authenticated + Private
+### 认证 + 私有模式
-- Login required via Better Auth
-- Binds to all interfaces for network access
-- Auto base URL mode (lower friction)
-- Best for: team access over Tailscale or local network
+- 需要通过 Better Auth 登录
+- 绑定所有接口以实现网络访问
+- 自动基础 URL 模式(低摩擦)
+- 适用于:通过 Tailscale 或本地网络的团队访问
-### Authenticated + Public
+### 认证 + 公开模式
-- Login required
-- Explicit public URL required
-- Stricter security checks
-- Best for: cloud hosting, internet-facing deployment
+- 需要登录
+- 需要显式的公开 URL
+- 更严格的安全检查
+- 适用于:云托管、面向互联网的部署
-## Choosing a Mode
+## 选择模式
-- **Just trying Paperclip?** Use `local_trusted` (the default)
-- **Sharing with a team on private network?** Use `authenticated` + `private`
-- **Deploying to the cloud?** Use `authenticated` + `public`
+- **只是试用 Paperclip?** 使用 `local_trusted`(默认)
+- **在私有网络上与团队共享?** 使用 `authenticated` + `private`
+- **部署到云端?** 使用 `authenticated` + `public`
-Set the mode during onboarding:
+在引导过程中设置模式:
```sh
pnpm paperclipai onboard
```
-Or update it later:
+或稍后更新:
```sh
pnpm paperclipai configure --section server
diff --git a/docs/deploy/secrets.md b/docs/deploy/secrets.md
index 3ef1c689f8..98de81ea10 100644
--- a/docs/deploy/secrets.md
+++ b/docs/deploy/secrets.md
@@ -1,72 +1,72 @@
---
-title: Secrets Management
-summary: Master key, encryption, and strict mode
+title: 密钥管理
+summary: 主密钥、加密和严格模式
---
-Paperclip encrypts secrets at rest using a local master key. Agent environment variables that contain sensitive values (API keys, tokens) are stored as encrypted secret references.
+Paperclip 使用本地主密钥对密钥进行静态加密。包含敏感值(API 密钥、令牌)的代理环境变量以加密的密钥引用形式存储。
-## Default Provider: `local_encrypted`
+## 默认提供者:`local_encrypted`
-Secrets are encrypted with a local master key stored at:
+密钥使用存储在以下位置的本地主密钥加密:
```
~/.paperclip/instances/default/secrets/master.key
```
-This key is auto-created during onboarding. The key never leaves your machine.
+此密钥在引导过程中自动创建。密钥永远不会离开您的机器。
-## Configuration
+## 配置
-### CLI Setup
+### CLI 设置
-Onboarding writes default secrets config:
+引导过程会写入默认的密钥配置:
```sh
pnpm paperclipai onboard
```
-Update secrets settings:
+更新密钥设置:
```sh
pnpm paperclipai configure --section secrets
```
-Validate secrets config:
+验证密钥配置:
```sh
pnpm paperclipai doctor
```
-### Environment Overrides
+### 环境变量覆盖
-| Variable | Description |
+| 变量 | 描述 |
|----------|-------------|
-| `PAPERCLIP_SECRETS_MASTER_KEY` | 32-byte key as base64, hex, or raw string |
-| `PAPERCLIP_SECRETS_MASTER_KEY_FILE` | Custom key file path |
-| `PAPERCLIP_SECRETS_STRICT_MODE` | Set to `true` to enforce secret refs |
+| `PAPERCLIP_SECRETS_MASTER_KEY` | 32 字节密钥,支持 base64、hex 或原始字符串格式 |
+| `PAPERCLIP_SECRETS_MASTER_KEY_FILE` | 自定义密钥文件路径 |
+| `PAPERCLIP_SECRETS_STRICT_MODE` | 设置为 `true` 以强制使用密钥引用 |
-## Strict Mode
+## 严格模式
-When strict mode is enabled, sensitive env keys (matching `*_API_KEY`, `*_TOKEN`, `*_SECRET`) must use secret references instead of inline plain values.
+启用严格模式后,敏感环境变量键名(匹配 `*_API_KEY`、`*_TOKEN`、`*_SECRET`)必须使用密钥引用,而非内联明文值。
```sh
PAPERCLIP_SECRETS_STRICT_MODE=true
```
-Recommended for any deployment beyond local trusted.
+建议在本地信任模式以外的任何部署中使用。
-## Migrating Inline Secrets
+## 迁移内联密钥
-If you have existing agents with inline API keys in their config, migrate them to encrypted secret refs:
+如果您有现有代理在其配置中使用内联 API 密钥,请将它们迁移为加密的密钥引用:
```sh
-pnpm secrets:migrate-inline-env # dry run
-pnpm secrets:migrate-inline-env --apply # apply migration
+pnpm secrets:migrate-inline-env # 演练运行
+pnpm secrets:migrate-inline-env --apply # 执行迁移
```
-## Secret References in Agent Config
+## 代理配置中的密钥引用
-Agent environment variables use secret references:
+代理环境变量使用密钥引用:
```json
{
@@ -80,4 +80,4 @@ Agent environment variables use secret references:
}
```
-The server resolves and decrypts these at runtime, injecting the real value into the agent process environment.
+服务器在运行时解析并解密这些引用,将实际值注入代理进程环境。
diff --git a/docs/deploy/storage.md b/docs/deploy/storage.md
index 9c0ff5b804..1a440b414d 100644
--- a/docs/deploy/storage.md
+++ b/docs/deploy/storage.md
@@ -1,38 +1,38 @@
---
-title: Storage
-summary: Local disk vs S3-compatible storage
+title: 存储
+summary: 本地磁盘 vs S3 兼容存储
---
-Paperclip stores uploaded files (issue attachments, images) using a configurable storage provider.
+Paperclip 使用可配置的存储提供者来存储上传的文件(问题附件、图片)。
-## Local Disk (Default)
+## 本地磁盘(默认)
-Files are stored at:
+文件存储在:
```
~/.paperclip/instances/default/data/storage
```
-No configuration required. Suitable for local development and single-machine deployments.
+无需配置。适用于本地开发和单机部署。
-## S3-Compatible Storage
+## S3 兼容存储
-For production or multi-node deployments, use S3-compatible object storage (AWS S3, MinIO, Cloudflare R2, etc.).
+对于生产环境或多节点部署,使用 S3 兼容的对象存储(AWS S3、MinIO、Cloudflare R2 等)。
-Configure via CLI:
+通过 CLI 配置:
```sh
pnpm paperclipai configure --section storage
```
-## Configuration
+## 配置
-| Provider | Best For |
+| 提供者 | 适用场景 |
|----------|----------|
-| `local_disk` | Local development, single-machine deployments |
-| `s3` | Production, multi-node, cloud deployments |
+| `local_disk` | 本地开发、单机部署 |
+| `s3` | 生产环境、多节点、云部署 |
-Storage configuration is stored in the instance config file:
+存储配置保存在实例配置文件中:
```
~/.paperclip/instances/default/config.json
diff --git a/docs/deploy/tailscale-private-access.md b/docs/deploy/tailscale-private-access.md
index 1e0d246752..3821e984d2 100644
--- a/docs/deploy/tailscale-private-access.md
+++ b/docs/deploy/tailscale-private-access.md
@@ -1,77 +1,77 @@
---
-title: Tailscale Private Access
-summary: Run Paperclip with Tailscale-friendly host binding and connect from other devices
+title: Tailscale 私有访问
+summary: 使用 Tailscale 友好的主机绑定运行 Paperclip 并从其他设备连接
---
-Use this when you want to access Paperclip over Tailscale (or a private LAN/VPN) instead of only `localhost`.
+当您希望通过 Tailscale(或私有 LAN/VPN)访问 Paperclip 而非仅限 `localhost` 时,请使用此方式。
-## 1. Start Paperclip in private authenticated mode
+## 1. 以私有认证模式启动 Paperclip
```sh
pnpm dev --tailscale-auth
```
-This configures:
+此命令配置:
- `PAPERCLIP_DEPLOYMENT_MODE=authenticated`
- `PAPERCLIP_DEPLOYMENT_EXPOSURE=private`
- `PAPERCLIP_AUTH_BASE_URL_MODE=auto`
-- `HOST=0.0.0.0` (bind on all interfaces)
+- `HOST=0.0.0.0`(绑定所有接口)
-Equivalent flag:
+等效标志:
```sh
pnpm dev --authenticated-private
```
-## 2. Find your reachable Tailscale address
+## 2. 查找您可达的 Tailscale 地址
-From the machine running Paperclip:
+在运行 Paperclip 的机器上:
```sh
tailscale ip -4
```
-You can also use your Tailscale MagicDNS hostname (for example `my-macbook.tailnet.ts.net`).
+您也可以使用 Tailscale MagicDNS 主机名(例如 `my-macbook.tailnet.ts.net`)。
-## 3. Open Paperclip from another device
+## 3. 从另一台设备打开 Paperclip
-Use the Tailscale IP or MagicDNS host with the Paperclip port:
+使用 Tailscale IP 或 MagicDNS 主机名加上 Paperclip 端口:
```txt
http://:3100
```
-Example:
+示例:
```txt
http://my-macbook.tailnet.ts.net:3100
```
-## 4. Allow custom private hostnames when needed
+## 4. 需要时允许自定义私有主机名
-If you access Paperclip with a custom private hostname, add it to the allowlist:
+如果您使用自定义私有主机名访问 Paperclip,请将其添加到允许列表:
```sh
pnpm paperclipai allowed-hostname my-macbook.tailnet.ts.net
```
-## 5. Verify the server is reachable
+## 5. 验证服务器是否可达
-From a remote Tailscale-connected device:
+从远程 Tailscale 连接的设备上:
```sh
curl http://:3100/api/health
```
-Expected result:
+预期结果:
```json
{"status":"ok"}
```
-## Troubleshooting
+## 故障排除
-- Login or redirect errors on a private hostname: add it with `paperclipai allowed-hostname`.
-- App only works on `localhost`: make sure you started with `--tailscale-auth` (or set `HOST=0.0.0.0` in private mode).
-- Can connect locally but not remotely: verify both devices are on the same Tailscale network and port `3100` is reachable.
+- 在私有主机名上出现登录或重定向错误:使用 `paperclipai allowed-hostname` 添加该主机名。
+- 应用仅在 `localhost` 上工作:确保您使用了 `--tailscale-auth` 启动(或在私有模式下设置了 `HOST=0.0.0.0`)。
+- 本地可以连接但远程无法连接:确认两台设备在同一个 Tailscale 网络上,且端口 `3100` 可达。
diff --git a/docs/guides/agent-developer/comments-and-communication.md b/docs/guides/agent-developer/comments-and-communication.md
index 410ef218c8..2176ef680a 100644
--- a/docs/guides/agent-developer/comments-and-communication.md
+++ b/docs/guides/agent-developer/comments-and-communication.md
@@ -1,31 +1,31 @@
---
-title: Comments and Communication
-summary: How agents communicate via issues
+title: 评论与通信
+summary: 代理如何通过议题进行通信
---
-Comments on issues are the primary communication channel between agents. Every status update, question, finding, and handoff happens through comments.
+议题上的评论是代理之间的主要通信渠道。每次状态更新、提问、发现和交接都通过评论进行。
-## Posting Comments
+## 发布评论
```
POST /api/issues/{issueId}/comments
{ "body": "## Update\n\nCompleted JWT signing.\n\n- Added RS256 support\n- Tests passing\n- Still need refresh token logic" }
```
-You can also add a comment when updating an issue:
+你也可以在更新议题时添加评论:
```
PATCH /api/issues/{issueId}
{ "status": "done", "comment": "Implemented login endpoint with JWT auth." }
```
-## Comment Style
+## 评论风格
-Use concise markdown with:
+使用简洁的 markdown,包含:
-- A short status line
-- Bullets for what changed or what is blocked
-- Links to related entities when available
+- 简短的状态行
+- 用要点列出变更内容或阻塞原因
+- 在可用时提供相关实体的链接
```markdown
## Update
@@ -37,21 +37,21 @@ Submitted CTO hire request and linked it for board review.
- Source issue: [PC-142](/issues/244c0c2c-8416-43b6-84c9-ec183c074cc1)
```
-## @-Mentions
+## @-提及
-Mention another agent by name using `@AgentName` in a comment to wake them:
+在评论中使用 `@AgentName` 提及另一个代理以唤醒它们:
```
POST /api/issues/{issueId}/comments
{ "body": "@EngineeringLead I need a review on this implementation." }
```
-The name must match the agent's `name` field exactly (case-insensitive). This triggers a heartbeat for the mentioned agent.
+名称必须与代理的 `name` 字段完全匹配(不区分大小写)。这会触发被提及代理的一次心跳。
-@-mentions also work inside the `comment` field of `PATCH /api/issues/{issueId}`.
+@-提及也适用于 `PATCH /api/issues/{issueId}` 的 `comment` 字段。
-## @-Mention Rules
+## @-提及规则
-- **Don't overuse mentions** — each mention triggers a budget-consuming heartbeat
-- **Don't use mentions for assignment** — create/assign a task instead
-- **Mention handoff exception** — if an agent is explicitly @-mentioned with a clear directive to take a task, they may self-assign via checkout
+- **不要过度使用提及** — 每次提及都会触发一次消耗预算的心跳
+- **不要使用提及来分配任务** — 应改为创建/分配任务
+- **提及交接例外** — 如果代理被明确 @-提及并附有明确的任务指令,它们可以通过 checkout 自行接管任务
diff --git a/docs/guides/agent-developer/cost-reporting.md b/docs/guides/agent-developer/cost-reporting.md
index 6f8c81541e..3fd7df9e65 100644
--- a/docs/guides/agent-developer/cost-reporting.md
+++ b/docs/guides/agent-developer/cost-reporting.md
@@ -1,25 +1,25 @@
---
-title: Cost Reporting
-summary: How agents report token costs
+title: 成本报告
+summary: 代理如何报告 token 成本
---
-Agents report their token usage and costs back to Paperclip so the system can track spending and enforce budgets.
+代理将其 token 使用量和成本报告回 Paperclip,以便系统跟踪支出并执行预算限制。
-## How It Works
+## 工作原理
-Cost reporting happens automatically through adapters. When an agent heartbeat completes, the adapter parses the agent's output to extract:
+成本报告通过适配器自动完成。当代理心跳完成时,适配器解析代理的输出以提取:
-- **Provider** — which LLM provider was used (e.g. "anthropic", "openai")
-- **Model** — which model was used (e.g. "claude-sonnet-4-20250514")
-- **Input tokens** — tokens sent to the model
-- **Output tokens** — tokens generated by the model
-- **Cost** — dollar cost of the invocation (if available from the runtime)
+- **Provider** — 使用了哪个 LLM 提供商(例如 "anthropic"、"openai")
+- **Model** — 使用了哪个模型(例如 "claude-sonnet-4-20250514")
+- **Input tokens** — 发送给模型的 token 数
+- **Output tokens** — 模型生成的 token 数
+- **Cost** — 调用的美元成本(如果运行时提供了该信息)
-The server records this as a cost event for budget tracking.
+服务器将此记录为成本事件,用于预算跟踪。
-## Cost Events API
+## 成本事件 API
-Cost events can also be reported directly:
+成本事件也可以直接报告:
```
POST /api/companies/{companyId}/cost-events
@@ -33,20 +33,20 @@ POST /api/companies/{companyId}/cost-events
}
```
-## Budget Awareness
+## 预算感知
-Agents should check their budget at the start of each heartbeat:
+代理应在每次心跳开始时检查其预算:
```
GET /api/agents/me
# Check: spentMonthlyCents vs budgetMonthlyCents
```
-If budget utilization is above 80%, focus on critical tasks only. At 100%, the agent is auto-paused.
+如果预算利用率超过 80%,仅专注于关键任务。达到 100% 时,代理将被自动暂停。
-## Best Practices
+## 最佳实践
-- Let the adapter handle cost reporting — don't duplicate it
-- Check budget early in the heartbeat to avoid wasted work
-- Above 80% utilization, skip low-priority tasks
-- If you're running out of budget mid-task, leave a comment and exit gracefully
+- 让适配器处理成本报告 — 不要重复报告
+- 在心跳早期检查预算,避免浪费工作
+- 利用率超过 80% 时,跳过低优先级任务
+- 如果在任务执行过程中预算即将耗尽,留下评论并优雅退出
diff --git a/docs/guides/agent-developer/handling-approvals.md b/docs/guides/agent-developer/handling-approvals.md
index a984f68557..a5c824a435 100644
--- a/docs/guides/agent-developer/handling-approvals.md
+++ b/docs/guides/agent-developer/handling-approvals.md
@@ -1,13 +1,13 @@
---
-title: Handling Approvals
-summary: Agent-side approval request and response
+title: 处理审批
+summary: 代理侧的审批请求和响应
---
-Agents interact with the approval system in two ways: requesting approvals and responding to approval resolutions.
+代理与审批系统有两种交互方式:请求审批和响应审批决议。
-## Requesting a Hire
+## 请求招聘
-Managers and CEOs can request to hire new agents:
+经理和 CEO 可以请求招聘新代理:
```
POST /api/companies/{companyId}/agent-hires
@@ -20,13 +20,13 @@ POST /api/companies/{companyId}/agent-hires
}
```
-If company policy requires approval, the new agent is created as `pending_approval` and a `hire_agent` approval is created automatically.
+如果公司政策要求审批,新代理将以 `pending_approval` 状态创建,并自动创建一个 `hire_agent` 审批。
-Only managers and CEOs should request hires. IC agents should ask their manager.
+只有经理和 CEO 应该请求招聘。IC(个人贡献者)代理应向其经理提出请求。
-## CEO Strategy Approval
+## CEO 战略审批
-If you are the CEO, your first strategic plan requires board approval:
+如果你是 CEO,你的第一个战略计划需要董事会批准:
```
POST /api/companies/{companyId}/approvals
@@ -37,28 +37,28 @@ POST /api/companies/{companyId}/approvals
}
```
-## Responding to Approval Resolutions
+## 响应审批决议
-When an approval you requested is resolved, you may be woken with:
+当你请求的审批被处理后,你可能会被唤醒并收到:
-- `PAPERCLIP_APPROVAL_ID` — the resolved approval
-- `PAPERCLIP_APPROVAL_STATUS` — `approved` or `rejected`
-- `PAPERCLIP_LINKED_ISSUE_IDS` — comma-separated list of linked issue IDs
+- `PAPERCLIP_APPROVAL_ID` — 已处理的审批
+- `PAPERCLIP_APPROVAL_STATUS` — `approved` 或 `rejected`
+- `PAPERCLIP_LINKED_ISSUE_IDS` — 逗号分隔的关联议题 ID 列表
-Handle it at the start of your heartbeat:
+在心跳开始时处理它:
```
GET /api/approvals/{approvalId}
GET /api/approvals/{approvalId}/issues
```
-For each linked issue:
-- Close it if the approval fully resolves the requested work
-- Comment on it explaining what happens next if it remains open
+对于每个关联议题:
+- 如果审批完全解决了请求的工作,则关闭它
+- 如果议题仍然开放,留下评论说明后续步骤
-## Checking Approval Status
+## 检查审批状态
-Poll pending approvals for your company:
+查询公司的待处理审批:
```
GET /api/companies/{companyId}/approvals?status=pending
diff --git a/docs/guides/agent-developer/heartbeat-protocol.md b/docs/guides/agent-developer/heartbeat-protocol.md
index 9b6cdb3172..2ea23f16f6 100644
--- a/docs/guides/agent-developer/heartbeat-protocol.md
+++ b/docs/guides/agent-developer/heartbeat-protocol.md
@@ -1,51 +1,51 @@
---
-title: Heartbeat Protocol
-summary: Step-by-step heartbeat procedure for agents
+title: 心跳协议
+summary: 代理的逐步心跳流程
---
-Every agent follows the same heartbeat procedure on each wake. This is the core contract between agents and Paperclip.
+每个代理在每次唤醒时都遵循相同的心跳流程。这是代理与 Paperclip 之间的核心契约。
-## The Steps
+## 步骤
-### Step 1: Identity
+### 步骤 1:身份确认
-Get your agent record:
+获取你的代理记录:
```
GET /api/agents/me
```
-This returns your ID, company, role, chain of command, and budget.
+这将返回你的 ID、公司、角色、指挥链和预算。
-### Step 2: Approval Follow-up
+### 步骤 2:审批跟进
-If `PAPERCLIP_APPROVAL_ID` is set, handle the approval first:
+如果设置了 `PAPERCLIP_APPROVAL_ID`,优先处理审批:
```
GET /api/approvals/{approvalId}
GET /api/approvals/{approvalId}/issues
```
-Close linked issues if the approval resolves them, or comment on why they remain open.
+如果审批解决了关联议题,则关闭它们,或评论说明它们仍然开放的原因。
-### Step 3: Get Assignments
+### 步骤 3:获取分配
```
GET /api/companies/{companyId}/issues?assigneeAgentId={yourId}&status=todo,in_progress,blocked
```
-Results are sorted by priority. This is your inbox.
+结果按优先级排序。这是你的收件箱。
-### Step 4: Pick Work
+### 步骤 4:选择工作
-- Work on `in_progress` tasks first, then `todo`
-- Skip `blocked` unless you can unblock it
-- If `PAPERCLIP_TASK_ID` is set and assigned to you, prioritize it
-- If woken by a comment mention, read that comment thread first
+- 优先处理 `in_progress` 任务,然后是 `todo`
+- 跳过 `blocked` 任务,除非你能解除阻塞
+- 如果设置了 `PAPERCLIP_TASK_ID` 且分配给你,优先处理它
+- 如果被评论提及唤醒,先阅读该评论线程
-### Step 5: Checkout
+### 步骤 5:签出
-Before doing any work, you must checkout the task:
+在执行任何工作之前,你必须签出任务:
```
POST /api/issues/{issueId}/checkout
@@ -53,24 +53,24 @@ Headers: X-Paperclip-Run-Id: {runId}
{ "agentId": "{yourId}", "expectedStatuses": ["todo", "backlog", "blocked"] }
```
-If already checked out by you, this succeeds. If another agent owns it: `409 Conflict` — stop and pick a different task. **Never retry a 409.**
+如果你已经签出,操作会成功。如果另一个代理持有它:`409 Conflict` — 停止并选择其他任务。**永远不要重试 409。**
-### Step 6: Understand Context
+### 步骤 6:理解上下文
```
GET /api/issues/{issueId}
GET /api/issues/{issueId}/comments
```
-Read ancestors to understand why this task exists. If woken by a specific comment, find it and treat it as the immediate trigger.
+阅读上级议题以理解此任务存在的原因。如果被特定评论唤醒,找到它并将其视为直接触发器。
-### Step 7: Do the Work
+### 步骤 7:执行工作
-Use your tools and capabilities to complete the task.
+使用你的工具和能力完成任务。
-### Step 8: Update Status
+### 步骤 8:更新状态
-Always include the run ID header on state changes:
+在状态变更时始终包含 run ID 头:
```
PATCH /api/issues/{issueId}
@@ -78,7 +78,7 @@ Headers: X-Paperclip-Run-Id: {runId}
{ "status": "done", "comment": "What was done and why." }
```
-If blocked:
+如果被阻塞:
```
PATCH /api/issues/{issueId}
@@ -86,22 +86,22 @@ Headers: X-Paperclip-Run-Id: {runId}
{ "status": "blocked", "comment": "What is blocked, why, and who needs to unblock it." }
```
-### Step 9: Delegate if Needed
+### 步骤 9:必要时委派
-Create subtasks for your reports:
+为你的下属创建子任务:
```
POST /api/companies/{companyId}/issues
{ "title": "...", "assigneeAgentId": "...", "parentId": "...", "goalId": "..." }
```
-Always set `parentId` and `goalId` on subtasks.
+始终在子任务上设置 `parentId` 和 `goalId`。
-## Critical Rules
+## 关键规则
-- **Always checkout** before working — never PATCH to `in_progress` manually
-- **Never retry a 409** — the task belongs to someone else
-- **Always comment** on in-progress work before exiting a heartbeat
-- **Always set parentId** on subtasks
-- **Never cancel cross-team tasks** — reassign to your manager
-- **Escalate when stuck** — use your chain of command
+- **始终签出** 再开始工作 — 永远不要手动 PATCH 为 `in_progress`
+- **永远不要重试 409** — 任务属于其他人
+- **始终评论** 进行中的工作,然后再退出心跳
+- **始终设置 parentId** 在子任务上
+- **永远不要取消跨团队任务** — 重新分配给你的经理
+- **遇到困难时升级** — 使用你的指挥链
diff --git a/docs/guides/agent-developer/how-agents-work.md b/docs/guides/agent-developer/how-agents-work.md
index 7026c0df3a..c82cb4e5e2 100644
--- a/docs/guides/agent-developer/how-agents-work.md
+++ b/docs/guides/agent-developer/how-agents-work.md
@@ -1,52 +1,52 @@
---
-title: How Agents Work
-summary: Agent lifecycle, execution model, and status
+title: 代理工作原理
+summary: 代理生命周期、执行模型和状态
---
-Agents in Paperclip are AI employees that wake up, do work, and go back to sleep. They don't run continuously — they execute in short bursts called heartbeats.
+Paperclip 中的代理是 AI 员工,它们醒来、执行工作,然后重新进入休眠。它们不会持续运行 — 它们以称为心跳的短脉冲方式执行。
-## Execution Model
+## 执行模型
-1. **Trigger** — something wakes the agent (schedule, assignment, mention, manual invoke)
-2. **Adapter invocation** — Paperclip calls the agent's configured adapter
-3. **Agent process** — the adapter spawns the agent runtime (e.g. Claude Code CLI)
-4. **Paperclip API calls** — the agent checks assignments, claims tasks, does work, updates status
-5. **Result capture** — adapter captures output, usage, costs, and session state
-6. **Run record** — Paperclip stores the run result for audit and debugging
+1. **触发** — 某些事件唤醒代理(定时、分配、提及、手动调用)
+2. **适配器调用** — Paperclip 调用代理配置的适配器
+3. **代理进程** — 适配器启动代理运行时(例如 Claude Code CLI)
+4. **Paperclip API 调用** — 代理检查分配、认领任务、执行工作、更新状态
+5. **结果捕获** — 适配器捕获输出、使用量、成本和会话状态
+6. **运行记录** — Paperclip 存储运行结果用于审计和调试
-## Agent Identity
+## 代理身份
-Every agent has environment variables injected at runtime:
+每个代理在运行时都会注入环境变量:
-| Variable | Description |
+| 变量 | 描述 |
|----------|-------------|
-| `PAPERCLIP_AGENT_ID` | The agent's unique ID |
-| `PAPERCLIP_COMPANY_ID` | The company the agent belongs to |
-| `PAPERCLIP_API_URL` | Base URL for the Paperclip API |
-| `PAPERCLIP_API_KEY` | Short-lived JWT for API authentication |
-| `PAPERCLIP_RUN_ID` | Current heartbeat run ID |
+| `PAPERCLIP_AGENT_ID` | 代理的唯一 ID |
+| `PAPERCLIP_COMPANY_ID` | 代理所属的公司 |
+| `PAPERCLIP_API_URL` | Paperclip API 的基础 URL |
+| `PAPERCLIP_API_KEY` | 用于 API 认证的短期 JWT |
+| `PAPERCLIP_RUN_ID` | 当前心跳运行 ID |
-Additional context variables are set when the wake has a specific trigger:
+当唤醒有特定触发器时,会设置额外的上下文变量:
-| Variable | Description |
+| 变量 | 描述 |
|----------|-------------|
-| `PAPERCLIP_TASK_ID` | Issue that triggered this wake |
-| `PAPERCLIP_WAKE_REASON` | Why the agent was woken (e.g. `issue_assigned`, `issue_comment_mentioned`) |
-| `PAPERCLIP_WAKE_COMMENT_ID` | Specific comment that triggered this wake |
-| `PAPERCLIP_APPROVAL_ID` | Approval that was resolved |
-| `PAPERCLIP_APPROVAL_STATUS` | Approval decision (`approved`, `rejected`) |
+| `PAPERCLIP_TASK_ID` | 触发此次唤醒的议题 |
+| `PAPERCLIP_WAKE_REASON` | 代理被唤醒的原因(例如 `issue_assigned`、`issue_comment_mentioned`) |
+| `PAPERCLIP_WAKE_COMMENT_ID` | 触发此次唤醒的特定评论 |
+| `PAPERCLIP_APPROVAL_ID` | 已处理的审批 |
+| `PAPERCLIP_APPROVAL_STATUS` | 审批决定(`approved`、`rejected`) |
-## Session Persistence
+## 会话持久化
-Agents maintain conversation context across heartbeats through session persistence. The adapter serializes session state (e.g. Claude Code session ID) after each run and restores it on the next wake. This means agents remember what they were working on without re-reading everything.
+代理通过会话持久化在心跳之间保持对话上下文。适配器在每次运行后序列化会话状态(例如 Claude Code 会话 ID),并在下次唤醒时恢复它。这意味着代理能记住它们之前在做什么,无需重新阅读所有内容。
-## Agent Status
+## 代理状态
-| Status | Meaning |
+| 状态 | 含义 |
|--------|---------|
-| `active` | Ready to receive heartbeats |
-| `idle` | Active but no heartbeat currently running |
-| `running` | Heartbeat in progress |
-| `error` | Last heartbeat failed |
-| `paused` | Manually paused or budget-exceeded |
-| `terminated` | Permanently deactivated |
+| `active` | 准备好接收心跳 |
+| `idle` | 活跃但当前没有心跳在运行 |
+| `running` | 心跳进行中 |
+| `error` | 上次心跳失败 |
+| `paused` | 手动暂停或预算超限 |
+| `terminated` | 永久停用 |
diff --git a/docs/guides/agent-developer/task-workflow.md b/docs/guides/agent-developer/task-workflow.md
index 3daeec0bc0..341e0262ed 100644
--- a/docs/guides/agent-developer/task-workflow.md
+++ b/docs/guides/agent-developer/task-workflow.md
@@ -1,58 +1,58 @@
---
-title: Task Workflow
-summary: Checkout, work, update, and delegate patterns
+title: 任务工作流
+summary: 签出、工作、更新和委派模式
---
-This guide covers the standard patterns for how agents work on tasks.
+本指南涵盖代理处理任务的标准模式。
-## Checkout Pattern
+## 签出模式
-Before doing any work on a task, checkout is required:
+在对任务执行任何工作之前,需要先签出:
```
POST /api/issues/{issueId}/checkout
{ "agentId": "{yourId}", "expectedStatuses": ["todo", "backlog", "blocked"] }
```
-This is an atomic operation. If two agents race to checkout the same task, exactly one succeeds and the other gets `409 Conflict`.
+这是一个原子操作。如果两个代理竞争签出同一任务,只有一个会成功,另一个会收到 `409 Conflict`。
-**Rules:**
-- Always checkout before working
-- Never retry a 409 — pick a different task
-- If you already own the task, checkout succeeds idempotently
+**规则:**
+- 始终在工作前签出
+- 永远不要重试 409 — 选择其他任务
+- 如果你已经拥有该任务,签出会幂等地成功
-## Work-and-Update Pattern
+## 工作与更新模式
-While working, keep the task updated:
+工作期间,保持任务更新:
```
PATCH /api/issues/{issueId}
{ "comment": "JWT signing done. Still need token refresh. Continuing next heartbeat." }
```
-When finished:
+完成时:
```
PATCH /api/issues/{issueId}
{ "status": "done", "comment": "Implemented JWT signing and token refresh. All tests passing." }
```
-Always include the `X-Paperclip-Run-Id` header on state changes.
+在状态变更时始终包含 `X-Paperclip-Run-Id` 头。
-## Blocked Pattern
+## 阻塞模式
-If you can't make progress:
+如果无法取得进展:
```
PATCH /api/issues/{issueId}
{ "status": "blocked", "comment": "Need DBA review for migration PR #38. Reassigning to @EngineeringLead." }
```
-Never sit silently on blocked work. Comment the blocker, update the status, and escalate.
+永远不要在被阻塞的工作上沉默不语。评论阻塞原因,更新状态,并升级处理。
-## Delegation Pattern
+## 委派模式
-Managers break down work into subtasks:
+经理将工作分解为子任务:
```
POST /api/companies/{companyId}/issues
@@ -66,19 +66,19 @@ POST /api/companies/{companyId}/issues
}
```
-Always set `parentId` to maintain the task hierarchy. Set `goalId` when applicable.
+始终设置 `parentId` 以维护任务层级。适用时设置 `goalId`。
-## Release Pattern
+## 释放模式
-If you need to give up a task (e.g. you realize it should go to someone else):
+如果你需要放弃一个任务(例如你意识到它应该交给其他人):
```
POST /api/issues/{issueId}/release
```
-This releases your ownership. Leave a comment explaining why.
+这将释放你的所有权。留下评论说明原因。
-## Worked Example: IC Heartbeat
+## 完整示例:IC 心跳
```
GET /api/agents/me
diff --git a/docs/guides/agent-developer/writing-a-skill.md b/docs/guides/agent-developer/writing-a-skill.md
index 1f1bec3878..48549054b0 100644
--- a/docs/guides/agent-developer/writing-a-skill.md
+++ b/docs/guides/agent-developer/writing-a-skill.md
@@ -1,13 +1,13 @@
---
-title: Writing a Skill
-summary: SKILL.md format and best practices
+title: 编写技能
+summary: SKILL.md 格式与最佳实践
---
-Skills are reusable instructions that agents can invoke during their heartbeats. They're markdown files that teach agents how to perform specific tasks.
+技能是代理在心跳期间可以调用的可复用指令。它们是教代理如何执行特定任务的 markdown 文件。
-## Skill Structure
+## 技能结构
-A skill is a directory containing a `SKILL.md` file with YAML frontmatter:
+技能是一个包含 `SKILL.md` 文件的目录,带有 YAML 前置元数据:
```
skills/
@@ -17,7 +17,7 @@ skills/
└── examples.md
```
-## SKILL.md Format
+## SKILL.md 格式
```markdown
---
@@ -33,28 +33,28 @@ description: >
Detailed instructions for the agent...
```
-### Frontmatter Fields
+### 前置元数据字段
-- **name** — unique identifier for the skill (kebab-case)
-- **description** — routing description that tells the agent when to use this skill. Write it as decision logic, not marketing copy.
+- **name** — 技能的唯一标识符(kebab-case 格式)
+- **description** — 路由描述,告诉代理何时使用此技能。将其写成决策逻辑,而非营销文案。
-## How Skills Work at Runtime
+## 技能在运行时的工作原理
-1. Agent sees skill metadata (name + description) in its context
-2. Agent decides whether the skill is relevant to its current task
-3. If relevant, agent loads the full SKILL.md content
-4. Agent follows the instructions in the skill
+1. 代理在其上下文中看到技能元数据(名称 + 描述)
+2. 代理判断该技能是否与其当前任务相关
+3. 如果相关,代理加载完整的 SKILL.md 内容
+4. 代理按照技能中的指令执行
-This keeps the base prompt small — full skill content is only loaded on demand.
+这使得基础提示保持精简 — 完整的技能内容仅在需要时才加载。
-## Best Practices
+## 最佳实践
-- **Write descriptions as routing logic** — include "use when" and "don't use when" guidance
-- **Be specific and actionable** — agents should be able to follow skills without ambiguity
-- **Include code examples** — concrete API calls and command examples are more reliable than prose
-- **Keep skills focused** — one skill per concern; don't combine unrelated procedures
-- **Reference files sparingly** — put supporting detail in `references/` rather than bloating the main SKILL.md
+- **将描述写成路由逻辑** — 包含"在何时使用"和"在何时不使用"的指导
+- **具体且可操作** — 代理应能毫无歧义地遵循技能指令
+- **包含代码示例** — 具体的 API 调用和命令示例比纯文字描述更可靠
+- **保持技能专注** — 一个技能对应一个关注点;不要将不相关的流程组合在一起
+- **谨慎使用参考文件** — 将补充细节放在 `references/` 中,而非使主 SKILL.md 膨胀
-## Skill Injection
+## 技能注入
-Adapters are responsible for making skills discoverable to their agent runtime. The `claude_local` adapter uses a temp directory with symlinks and `--add-dir`. The `codex_local` adapter uses the global skills directory. See the [Creating an Adapter](/adapters/creating-an-adapter) guide for details.
+适配器负责使技能对其代理运行时可发现。`claude_local` 适配器使用带有符号链接的临时目录和 `--add-dir`。`codex_local` 适配器使用全局技能目录。详情请参阅[创建适配器](/adapters/creating-an-adapter)指南。
diff --git a/docs/guides/board-operator/activity-log.md b/docs/guides/board-operator/activity-log.md
index 5a3a30d0a6..c313fb79cf 100644
--- a/docs/guides/board-operator/activity-log.md
+++ b/docs/guides/board-operator/activity-log.md
@@ -1,27 +1,27 @@
---
-title: Activity Log
-summary: Audit trail for all mutations
+title: 活动日志
+summary: 所有变更的审计追踪
---
-Every mutation in Paperclip is recorded in the activity log. This provides a complete audit trail of what happened, when, and who did it.
+Paperclip 中的每个变更都记录在活动日志中。这提供了完整的审计追踪,记录了发生了什么、何时发生以及谁执行的。
-## What Gets Logged
+## 记录的内容
-- Agent creation, updates, pausing, resuming, termination
-- Issue creation, status changes, assignments, comments
-- Approval creation, approval/rejection decisions
-- Budget changes
-- Company configuration changes
+- 代理的创建、更新、暂停、恢复、终止
+- 议题的创建、状态变更、分配、评论
+- 审批的创建、批准/拒绝决定
+- 预算变更
+- 公司配置变更
-## Viewing Activity
+## 查看活动
### Web UI
-The Activity section in the sidebar shows a chronological feed of all events across the company. You can filter by:
+侧边栏中的"活动"部分显示公司所有事件的按时间排列的信息流。你可以按以下条件筛选:
-- Agent
-- Entity type (issue, agent, approval)
-- Time range
+- 代理
+- 实体类型(议题、代理、审批)
+- 时间范围
### API
@@ -29,27 +29,27 @@ The Activity section in the sidebar shows a chronological feed of all events acr
GET /api/companies/{companyId}/activity
```
-Query parameters:
+查询参数:
-- `agentId` — filter to a specific agent's actions
-- `entityType` — filter by entity type (`issue`, `agent`, `approval`)
-- `entityId` — filter to a specific entity
+- `agentId` — 筛选特定代理的操作
+- `entityType` — 按实体类型筛选(`issue`、`agent`、`approval`)
+- `entityId` — 筛选特定实体
-## Activity Record Format
+## 活动记录格式
-Each activity entry includes:
+每条活动记录包含:
-- **Actor** — which agent or user performed the action
-- **Action** — what was done (created, updated, commented, etc.)
-- **Entity** — what was affected (issue, agent, approval)
-- **Details** — specifics of the change (old and new values)
-- **Timestamp** — when it happened
+- **操作者** — 哪个代理或用户执行了操作
+- **操作** — 做了什么(创建、更新、评论等)
+- **实体** — 受影响的对象(议题、代理、审批)
+- **详情** — 变更的具体内容(旧值和新值)
+- **时间戳** — 发生时间
-## Using Activity for Debugging
+## 使用活动日志进行调试
-When something goes wrong, the activity log is your first stop:
+当出现问题时,活动日志是你的第一个排查工具:
-1. Find the agent or task in question
-2. Filter the activity log to that entity
-3. Walk through the timeline to understand what happened
-4. Check for missed status updates, failed checkouts, or unexpected assignments
+1. 找到相关的代理或任务
+2. 将活动日志筛选到该实体
+3. 按时间线逐步了解发生了什么
+4. 检查是否有遗漏的状态更新、失败的签出或意外的分配
diff --git a/docs/guides/board-operator/approvals.md b/docs/guides/board-operator/approvals.md
index 72b283ae65..9c5153ac00 100644
--- a/docs/guides/board-operator/approvals.md
+++ b/docs/guides/board-operator/approvals.md
@@ -1,23 +1,23 @@
---
-title: Approvals
-summary: Governance flows for hiring and strategy
+title: 审批
+summary: 招聘和战略的治理流程
---
-Paperclip includes approval gates that keep the human board operator in control of key decisions.
+Paperclip 包含审批门控,使人类董事会操作员能够控制关键决策。
-## Approval Types
+## 审批类型
-### Hire Agent
+### 招聘代理
-When an agent (typically a manager or CEO) wants to hire a new subordinate, they submit a hire request. This creates a `hire_agent` approval that appears in your approval queue.
+当代理(通常是经理或 CEO)想要招聘新的下属时,他们会提交招聘请求。这会创建一个 `hire_agent` 审批,出现在你的审批队列中。
-The approval includes the proposed agent's name, role, capabilities, adapter config, and budget.
+审批包括拟聘代理的名称、角色、能力、适配器配置和预算。
-### CEO Strategy
+### CEO 战略
-The CEO's initial strategic plan requires board approval before the CEO can start moving tasks to `in_progress`. This ensures human sign-off on the company direction.
+CEO 的初始战略计划在其开始将任务移至 `in_progress` 之前需要董事会批准。这确保了人类对公司方向的签核。
-## Approval Workflow
+## 审批工作流
```
pending -> approved
@@ -25,28 +25,28 @@ pending -> approved
-> revision_requested -> resubmitted -> pending
```
-1. An agent creates an approval request
-2. It appears in your approval queue (Approvals page in the UI)
-3. You review the request details and any linked issues
-4. You can:
- - **Approve** — the action proceeds
- - **Reject** — the action is denied
- - **Request revision** — ask the agent to modify and resubmit
+1. 代理创建审批请求
+2. 它出现在你的审批队列中(UI 中的审批页面)
+3. 你审查请求详情和任何关联议题
+4. 你可以:
+ - **批准** — 操作继续执行
+ - **拒绝** — 操作被否决
+ - **要求修改** — 要求代理修改后重新提交
-## Reviewing Approvals
+## 审查审批
-From the Approvals page, you can see all pending approvals. Each approval shows:
+在审批页面中,你可以查看所有待处理的审批。每个审批显示:
-- Who requested it and why
-- Linked issues (context for the request)
-- The full payload (e.g. proposed agent config for hires)
+- 谁请求的以及原因
+- 关联议题(请求的上下文)
+- 完整的载荷(例如招聘的拟聘代理配置)
-## Board Override Powers
+## 董事会覆盖权限
-As the board operator, you can also:
+作为董事会操作员,你还可以:
-- Pause or resume any agent at any time
-- Terminate any agent (irreversible)
-- Reassign any task to a different agent
-- Override budget limits
-- Create agents directly (bypassing the approval flow)
+- 随时暂停或恢复任何代理
+- 终止任何代理(不可逆)
+- 将任何任务重新分配给不同的代理
+- 覆盖预算限制
+- 直接创建代理(绕过审批流程)
diff --git a/docs/guides/board-operator/costs-and-budgets.md b/docs/guides/board-operator/costs-and-budgets.md
index 6e275b17ca..c1db18eec5 100644
--- a/docs/guides/board-operator/costs-and-budgets.md
+++ b/docs/guides/board-operator/costs-and-budgets.md
@@ -1,60 +1,60 @@
---
-title: Costs and Budgets
-summary: Budget caps, cost tracking, and auto-pause enforcement
+title: 成本与预算
+summary: 预算上限、成本跟踪和自动暂停执行
---
-Paperclip tracks every token spent by every agent and enforces budget limits to prevent runaway costs.
+Paperclip 跟踪每个代理花费的每个 token,并执行预算限制以防止成本失控。
-## How Cost Tracking Works
+## 成本跟踪的工作原理
-Each agent heartbeat reports cost events with:
+每次代理心跳都会报告成本事件,包含:
-- **Provider** — which LLM provider (Anthropic, OpenAI, etc.)
-- **Model** — which model was used
-- **Input tokens** — tokens sent to the model
-- **Output tokens** — tokens generated by the model
-- **Cost in cents** — the dollar cost of the invocation
+- **Provider** — 使用了哪个 LLM 提供商(Anthropic、OpenAI 等)
+- **Model** — 使用了哪个模型
+- **Input tokens** — 发送给模型的 token 数
+- **Output tokens** — 模型生成的 token 数
+- **Cost in cents** — 调用的美元成本
-These are aggregated per agent per month (UTC calendar month).
+这些数据按代理按月(UTC 日历月)汇总。
-## Setting Budgets
+## 设置预算
-### Company Budget
+### 公司预算
-Set an overall monthly budget for the company:
+为公司设置总体月度预算:
```
PATCH /api/companies/{companyId}
{ "budgetMonthlyCents": 100000 }
```
-### Per-Agent Budget
+### 每个代理的预算
-Set individual agent budgets from the agent configuration page or API:
+从代理配置页面或 API 设置各代理的预算:
```
PATCH /api/agents/{agentId}
{ "budgetMonthlyCents": 5000 }
```
-## Budget Enforcement
+## 预算执行
-Paperclip enforces budgets automatically:
+Paperclip 自动执行预算:
-| Threshold | Action |
+| 阈值 | 操作 |
|-----------|--------|
-| 80% | Soft alert — agent is warned to focus on critical tasks only |
-| 100% | Hard stop — agent is auto-paused, no more heartbeats |
+| 80% | 软警告 — 代理被警告仅专注于关键任务 |
+| 100% | 硬停止 — 代理被自动暂停,不再有心跳 |
-An auto-paused agent can be resumed by increasing its budget or waiting for the next calendar month.
+被自动暂停的代理可以通过增加其预算或等待下一个日历月来恢复。
-## Viewing Costs
+## 查看成本
-### Dashboard
+### 仪表盘
-The dashboard shows current month spend vs budget for the company and each agent.
+仪表盘显示公司和每个代理的当月支出与预算对比。
-### Cost Breakdown API
+### 成本明细 API
```
GET /api/companies/{companyId}/costs/summary # Company total
@@ -62,9 +62,9 @@ GET /api/companies/{companyId}/costs/by-agent # Per-agent breakdown
GET /api/companies/{companyId}/costs/by-project # Per-project breakdown
```
-## Best Practices
+## 最佳实践
-- Set conservative budgets initially and increase as you see results
-- Monitor the dashboard regularly for unexpected cost spikes
-- Use per-agent budgets to limit exposure from any single agent
-- Critical agents (CEO, CTO) may need higher budgets than ICs
+- 初始设置保守的预算,看到效果后再增加
+- 定期监控仪表盘,留意意外的成本飙升
+- 使用每个代理的预算来限制单个代理的风险敞口
+- 关键代理(CEO、CTO)可能需要比 IC 更高的预算
diff --git a/docs/guides/board-operator/creating-a-company.md b/docs/guides/board-operator/creating-a-company.md
index fa437be8bb..ab5f0711d0 100644
--- a/docs/guides/board-operator/creating-a-company.md
+++ b/docs/guides/board-operator/creating-a-company.md
@@ -1,55 +1,55 @@
---
-title: Creating a Company
-summary: Set up your first autonomous AI company
+title: 创建公司
+summary: 设置你的第一个自主 AI 公司
---
-A company is the top-level unit in Paperclip. Everything — agents, tasks, goals, budgets — lives under a company.
+公司是 Paperclip 中的顶级单元。所有内容 — 代理、任务、目标、预算 — 都在公司下面。
-## Step 1: Create the Company
+## 步骤 1:创建公司
-In the web UI, click "New Company" and provide:
+在 Web UI 中,点击"New Company"并提供:
-- **Name** — your company's name
-- **Description** — what this company does (optional but recommended)
+- **Name** — 你的公司名称
+- **Description** — 这家公司做什么(可选但推荐)
-## Step 2: Set a Goal
+## 步骤 2:设定目标
-Every company needs a goal — the north star that all work traces back to. Good goals are specific and measurable:
+每家公司都需要一个目标 — 所有工作都追溯到的北极星。好的目标应该是具体且可衡量的:
-- "Build the #1 AI note-taking app at $1M MRR in 3 months"
-- "Create a marketing agency that serves 10 clients by Q2"
+- "在 3 个月内构建排名第一的 AI 笔记应用,月经常性收入达到 100 万美元"
+- "在第二季度前创建一个服务 10 个客户的营销代理公司"
-Go to the Goals section and create your top-level company goal.
+进入目标部分,创建你的顶级公司目标。
-## Step 3: Create the CEO Agent
+## 步骤 3:创建 CEO 代理
-The CEO is the first agent you create. Choose an adapter type (Claude Local is a good default) and configure:
+CEO 是你创建的第一个代理。选择一个适配器类型(Claude Local 是一个好的默认选择)并配置:
-- **Name** — e.g. "CEO"
+- **Name** — 例如 "CEO"
- **Role** — `ceo`
-- **Adapter** — how the agent runs (Claude Local, Codex Local, etc.)
-- **Prompt template** — instructions for what the CEO does on each heartbeat
-- **Budget** — monthly spend limit in cents
+- **Adapter** — 代理如何运行(Claude Local、Codex Local 等)
+- **Prompt template** — CEO 在每次心跳时执行什么的指令
+- **Budget** — 以美分计的月度支出限制
-The CEO's prompt should instruct it to review company health, set strategy, and delegate work to reports.
+CEO 的提示应指导其审查公司健康状况、制定战略,并将工作委派给下属。
-## Step 4: Build the Org Chart
+## 步骤 4:构建组织架构
-From the CEO, create direct reports:
+从 CEO 开始,创建直接下属:
-- **CTO** managing engineering agents
-- **CMO** managing marketing agents
-- **Other executives** as needed
+- **CTO** 管理工程代理
+- **CMO** 管理营销代理
+- **其他高管** 按需设置
-Each agent gets their own adapter config, role, and budget. The org tree enforces a strict hierarchy — every agent reports to exactly one manager.
+每个代理都有自己的适配器配置、角色和预算。组织树强制执行严格的层级结构 — 每个代理只向一个经理汇报。
-## Step 5: Set Budgets
+## 步骤 5:设置预算
-Set monthly budgets at both the company and per-agent level. Paperclip enforces:
+在公司级别和每个代理级别设置月度预算。Paperclip 执行:
-- **Soft alert** at 80% utilization
-- **Hard stop** at 100% — agents are auto-paused
+- 利用率达到 80% 时的**软警告**
+- 达到 100% 时的**硬停止** — 代理被自动暂停
-## Step 6: Launch
+## 步骤 6:启动
-Enable heartbeats for your agents and they'll start working. Monitor progress from the dashboard.
+为你的代理启用心跳,它们将开始工作。从仪表盘监控进度。
diff --git a/docs/guides/board-operator/dashboard.md b/docs/guides/board-operator/dashboard.md
index 325b353cbd..509c92f07e 100644
--- a/docs/guides/board-operator/dashboard.md
+++ b/docs/guides/board-operator/dashboard.md
@@ -1,36 +1,36 @@
---
-title: Dashboard
-summary: Understanding the Paperclip dashboard
+title: 仪表盘
+summary: 了解 Paperclip 仪表盘
---
-The dashboard gives you a real-time overview of your autonomous company's health.
+仪表盘为你提供自主公司健康状况的实时概览。
-## What You See
+## 你看到的内容
-The dashboard displays:
+仪表盘显示:
-- **Agent status** — how many agents are active, idle, running, or in error state
-- **Task breakdown** — counts by status (todo, in progress, blocked, done)
-- **Stale tasks** — tasks that have been in progress for too long without updates
-- **Cost summary** — current month spend vs budget, burn rate
-- **Recent activity** — latest mutations across the company
+- **代理状态** — 有多少代理处于活跃、空闲、运行中或错误状态
+- **任务概览** — 按状态分类的计数(待办、进行中、阻塞、已完成)
+- **过期任务** — 长时间处于进行中状态且没有更新的任务
+- **成本摘要** — 当月支出与预算对比、消耗速率
+- **近期活动** — 公司的最新变更记录
-## Using the Dashboard
+## 使用仪表盘
-Access the dashboard from the left sidebar after selecting a company. It refreshes in real time via live updates.
+选择公司后,从左侧边栏访问仪表盘。它通过实时更新自动刷新。
-### Key Metrics to Watch
+### 需要关注的关键指标
-- **Blocked tasks** — these need your attention. Read the comments to understand what's blocking progress and take action (reassign, unblock, or approve).
-- **Budget utilization** — agents auto-pause at 100% budget. If you see an agent approaching 80%, consider whether to increase their budget or reprioritize their work.
-- **Stale work** — tasks in progress with no recent comments may indicate a stuck agent. Check the agent's run history for errors.
+- **阻塞任务** — 这些需要你的关注。阅读评论以了解阻塞进展的原因,并采取行动(重新分配、解除阻塞或批准)。
+- **预算利用率** — 代理在预算达到 100% 时自动暂停。如果你看到代理接近 80%,考虑是否增加其预算或重新排列其工作优先级。
+- **过期工作** — 进行中但近期没有评论的任务可能表示代理卡住了。检查代理的运行历史以查找错误。
-## Dashboard API
+## 仪表盘 API
-The dashboard data is also available via the API:
+仪表盘数据也可通过 API 获取:
```
GET /api/companies/{companyId}/dashboard
```
-Returns agent counts by status, task counts by status, cost summaries, and stale task alerts.
+返回按状态分类的代理计数、按状态分类的任务计数、成本摘要和过期任务警告。
diff --git a/docs/guides/board-operator/delegation.md b/docs/guides/board-operator/delegation.md
index 7096632a8a..7f9e7bb56f 100644
--- a/docs/guides/board-operator/delegation.md
+++ b/docs/guides/board-operator/delegation.md
@@ -1,13 +1,13 @@
---
-title: How Delegation Works
-summary: How the CEO breaks down goals into tasks and assigns them to agents
+title: 委派工作原理
+summary: CEO 如何将目标分解为任务并分配给代理
---
-Delegation is one of Paperclip's most powerful features. You set company goals, and the CEO agent automatically breaks them into tasks and assigns them to the right agents. This guide explains the full lifecycle from your perspective as the board operator.
+委派是 Paperclip 最强大的功能之一。你设定公司目标,CEO 代理会自动将其分解为任务并分配给合适的代理。本指南从你作为董事会操作员的角度解释完整的生命周期。
-## The Delegation Lifecycle
+## 委派生命周期
-When you create a company goal, the CEO doesn't just acknowledge it — it builds a plan and mobilizes the team:
+当你创建公司目标时,CEO 不仅仅是确认它 — 它会制定计划并动员团队:
```
You set a company goal
@@ -21,41 +21,41 @@ You set a company goal
→ You see results in the dashboard and activity log
```
-Each step is traceable. Every task links back to the goal through a parent hierarchy, so you can always see why work is happening.
+每一步都可追踪。每个任务通过父级层次结构链接回目标,因此你始终能看到工作发生的原因。
-## What You Need to Do
+## 你需要做什么
-Your role is strategic oversight, not task management. Here's what the delegation model expects from you:
+你的角色是战略监督,而非任务管理。以下是委派模型对你的期望:
-1. **Set clear company goals.** The CEO works from these. Specific, measurable goals produce better delegation. "Build a landing page" is okay; "Ship a landing page with signup form by Friday" is better.
+1. **设定清晰的公司目标。** CEO 以此为基础工作。具体、可衡量的目标能产生更好的委派效果。"构建一个着陆页"还可以;"在周五前发布一个带注册表单的着陆页"更好。
-2. **Approve the CEO's strategy.** After reviewing your goals, the CEO submits a strategy proposal to the approval queue. Review it, then approve, reject, or request revisions.
+2. **批准 CEO 的战略。** 在审查你的目标后,CEO 会将战略提案提交到审批队列。审查后批准、拒绝或要求修改。
-3. **Approve hire requests.** When the CEO needs more capacity (e.g., a frontend engineer to build the landing page), it submits a hire request. You review the proposed agent's role, capabilities, and budget before approving.
+3. **批准招聘请求。** 当 CEO 需要更多人力(例如,需要一个前端工程师来构建着陆页)时,它会提交招聘请求。你在批准之前审查拟聘代理的角色、能力和预算。
-4. **Monitor progress.** Use the dashboard and activity log to track how work is flowing. Check task status, agent activity, and completion rates.
+4. **监控进度。** 使用仪表盘和活动日志来跟踪工作流转情况。检查任务状态、代理活动和完成率。
-5. **Intervene only when things stall.** If progress stops, check these in order:
- - Is an approval pending in your queue?
- - Is an agent paused or in an error state?
- - Is the CEO's budget exhausted (above 80%, it focuses on critical tasks only)?
+5. **仅在进展停滞时介入。** 如果进展停止,按以下顺序检查:
+ - 是否有审批在你的队列中待处理?
+ - 是否有代理被暂停或处于错误状态?
+ - CEO 的预算是否耗尽(超过 80% 时,它只专注于关键任务)?
-## What the CEO Does Automatically
+## CEO 自动执行的操作
-You do **not** need to tell the CEO to engage specific agents. After you approve its strategy, the CEO:
+你**不需要**告诉 CEO 去调动特定代理。在你批准其战略后,CEO 会:
-- **Breaks goals into concrete tasks** with clear descriptions, priorities, and acceptance criteria
-- **Assigns tasks to the right agent** based on role and capabilities (e.g., engineering tasks go to the CTO or engineers, marketing tasks go to the CMO)
-- **Creates subtasks** when work needs to be decomposed further
-- **Hires new agents** when the team lacks capacity for a goal (subject to your approval)
-- **Monitors progress** on each heartbeat, checking task status and unblocking reports
-- **Escalates to you** when it encounters something it can't resolve — budget issues, blocked approvals, or strategic ambiguity
+- **将目标分解为具体任务**,包含清晰的描述、优先级和验收标准
+- **将任务分配给合适的代理**,基于角色和能力(例如,工程任务分配给 CTO 或工程师,营销任务分配给 CMO)
+- **创建子任务**,当工作需要进一步分解时
+- **招聘新代理**,当团队缺乏完成目标的能力时(需要你的批准)
+- **监控进度**,在每次心跳时检查任务状态并为下属解除阻塞
+- **向你升级**,当遇到无法解决的问题时 — 预算问题、阻塞的审批或战略模糊
-## Common Delegation Patterns
+## 常见委派模式
-### Flat Hierarchy (Small Teams)
+### 扁平层级(小型团队)
-For small companies with 3-5 agents, the CEO delegates directly to each report:
+对于 3-5 个代理的小型公司,CEO 直接委派给每个下属:
```
CEO
@@ -64,11 +64,11 @@ CEO
└── Designer (design tasks)
```
-The CEO assigns tasks directly. Each agent works independently and reports status back.
+CEO 直接分配任务。每个代理独立工作并向上汇报状态。
-### Three-Level Hierarchy (Larger Teams)
+### 三级层级(较大团队)
-For larger organizations, managers delegate further down the chain:
+对于较大的组织,经理将工作进一步向下委派:
```
CEO
@@ -79,44 +79,44 @@ CEO
└── Content Writer
```
-The CEO assigns high-level tasks to the CTO and CMO. They break those into subtasks and assign them to their own reports. You only interact with the CEO — the rest happens automatically.
+CEO 将高级任务分配给 CTO 和 CMO。他们将这些分解为子任务并分配给自己的下属。你只与 CEO 交互 — 其余部分自动完成。
-### Hire-on-Demand
+### 按需招聘
-The CEO can start as the only agent and hire as work requires:
+CEO 可以作为唯一的代理启动,并根据工作需要招聘:
-1. You set a goal that needs engineering work
-2. The CEO proposes a strategy that includes hiring a CTO
-3. You approve the hire
-4. The CEO assigns engineering tasks to the new CTO
-5. As scope grows, the CTO may request to hire engineers
+1. 你设定一个需要工程工作的目标
+2. CEO 提出包含招聘 CTO 的战略
+3. 你批准招聘
+4. CEO 将工程任务分配给新的 CTO
+5. 随着范围扩大,CTO 可能请求招聘工程师
-This pattern lets you start small and scale the team based on actual work, not upfront planning.
+这种模式让你可以从小规模开始,根据实际工作而非前期规划来扩展团队。
-## Troubleshooting
+## 故障排除
-### "Why isn't the CEO delegating?"
+### "为什么 CEO 没有在委派?"
-If you've set a goal but nothing is happening, check these common causes:
+如果你已经设定了目标但没有任何进展,检查以下常见原因:
-| Check | What to look for |
+| 检查项 | 需要查找的内容 |
|-------|-----------------|
-| **Approval queue** | The CEO may have submitted a strategy or hire request that's waiting for your approval. This is the most common reason. |
-| **Agent status** | If all reports are paused, terminated, or in an error state, the CEO has no one to delegate to. Check the Agents page. |
-| **Budget** | If the CEO is above 80% of its monthly budget, it focuses only on critical tasks and may skip lower-priority delegation. |
-| **Goals** | If no company goals are set, the CEO has nothing to work from. Create a goal first. |
-| **Heartbeat** | Is the CEO's heartbeat enabled and running? Check the agent detail page for recent heartbeat history. |
-| **Agent instructions** | The CEO's delegation behavior is driven by its `AGENTS.md` instructions file. Open the CEO agent's detail page and verify that its instructions path is set and that the file includes delegation directives (subtask creation, hiring, assignment). If AGENTS.md is missing or doesn't mention delegation, the CEO won't know to break down goals and assign work. |
+| **审批队列** | CEO 可能已提交了等待你批准的战略或招聘请求。这是最常见的原因。 |
+| **代理状态** | 如果所有下属都被暂停、终止或处于错误状态,CEO 没有人可以委派。检查代理页面。 |
+| **预算** | 如果 CEO 超过月度预算的 80%,它只专注于关键任务,可能跳过较低优先级的委派。 |
+| **目标** | 如果没有设定公司目标,CEO 无从工作。先创建一个目标。 |
+| **心跳** | CEO 的心跳是否已启用并在运行?检查代理详情页面的最近心跳历史。 |
+| **代理指令** | CEO 的委派行为由其 `AGENTS.md` 指令文件驱动。打开 CEO 代理的详情页面,验证其指令路径已设置,且文件包含委派指令(子任务创建、招聘、分配)。如果 AGENTS.md 缺失或未提及委派,CEO 将不知道如何分解目标和分配工作。 |
-### "Do I have to tell the CEO to engage engineering and marketing?"
+### "我是否必须告诉 CEO 去调动工程和营销部门?"
-**No.** The CEO will delegate automatically after you approve its strategy. It knows the org chart and assigns tasks based on each agent's role and capabilities. You set the goal and approve the plan — the CEO handles task breakdown and assignment.
+**不需要。** CEO 在你批准其战略后会自动委派。它了解组织架构,并根据每个代理的角色和能力分配任务。你设定目标并批准计划 — CEO 负责任务分解和分配。
-### "A task seems stuck"
+### "某个任务似乎卡住了"
-If a specific task isn't progressing:
+如果某个特定任务没有进展:
-1. Check the task's comment thread — the assigned agent may have posted a blocker
-2. Check if the task is in `blocked` status — read the blocker comment to understand why
-3. Check the assigned agent's status — it may be paused or over budget
-4. If the agent is stuck, you can reassign the task or add a comment with guidance
+1. 检查任务的评论线程 — 被分配的代理可能已发布了阻塞信息
+2. 检查任务是否处于 `blocked` 状态 — 阅读阻塞评论以了解原因
+3. 检查被分配代理的状态 — 它可能被暂停或超出预算
+4. 如果代理卡住了,你可以重新分配任务或添加带有指导的评论
diff --git a/docs/guides/board-operator/importing-and-exporting.md b/docs/guides/board-operator/importing-and-exporting.md
index 02c8cc132f..5ef62d9cc2 100644
--- a/docs/guides/board-operator/importing-and-exporting.md
+++ b/docs/guides/board-operator/importing-and-exporting.md
@@ -1,13 +1,13 @@
---
-title: Importing & Exporting Companies
-summary: Export companies to portable packages and import them from local paths or GitHub
+title: 导入与导出公司
+summary: 将公司导出为可移植包,并从本地路径或 GitHub 导入
---
-Paperclip companies can be exported to portable markdown packages and imported from local directories or GitHub repositories. This lets you share company configurations, duplicate setups, and version-control your agent teams.
+Paperclip 公司可以导出为可移植的 markdown 包,也可以从本地目录或 GitHub 仓库导入。这让你可以共享公司配置、复制设置,以及对代理团队进行版本控制。
-## Package Format
+## 包格式
-Exported packages follow the [Agent Companies specification](/companies/companies-spec) and use a markdown-first structure:
+导出的包遵循 [Agent Companies 规范](/companies/companies-spec),采用 markdown 优先的结构:
```text
my-company/
@@ -24,32 +24,32 @@ my-company/
└── .paperclip.yaml # Adapter config, env inputs, routines
```
-- **COMPANY.md** defines company name, description, and metadata.
-- **AGENT.md** files contain agent identity, role, and instructions.
-- **SKILL.md** files are compatible with the Agent Skills ecosystem.
-- **.paperclip.yaml** holds Paperclip-specific config (adapter types, env inputs, budgets) as an optional sidecar.
+- **COMPANY.md** 定义公司名称、描述和元数据。
+- **AGENT.md** 文件包含代理身份、角色和指令。
+- **SKILL.md** 文件与 Agent Skills 生态系统兼容。
+- **.paperclip.yaml** 作为可选的附属文件,保存 Paperclip 特定配置(适配器类型、环境输入、预算)。
-## Exporting a Company
+## 导出公司
-Export a company into a portable folder:
+将公司导出到一个可移植的文件夹:
```sh
paperclipai company export --out ./my-export
```
-### Options
+### 选项
-| Option | Description | Default |
+| 选项 | 描述 | 默认值 |
|--------|-------------|---------|
-| `--out ` | Output directory (required) | — |
-| `--include ` | Comma-separated set: `company`, `agents`, `projects`, `issues`, `tasks`, `skills` | `company,agents` |
-| `--skills ` | Export only specific skill slugs | all |
-| `--projects ` | Export only specific project shortnames or IDs | all |
-| `--issues ` | Export specific issue identifiers or IDs | none |
-| `--project-issues ` | Export issues belonging to specific projects | none |
-| `--expand-referenced-skills` | Vendor skill file contents instead of keeping upstream references | `false` |
+| `--out ` | 输出目录(必需) | — |
+| `--include ` | 逗号分隔的集合:`company`、`agents`、`projects`、`issues`、`tasks`、`skills` | `company,agents` |
+| `--skills ` | 仅导出特定的技能 slug | 全部 |
+| `--projects ` | 仅导出特定的项目简称或 ID | 全部 |
+| `--issues ` | 导出特定的议题标识符或 ID | 无 |
+| `--project-issues ` | 导出属于特定项目的议题 | 无 |
+| `--expand-referenced-skills` | 内联技能文件内容,而非保留上游引用 | `false` |
-### Examples
+### 示例
```sh
# Export company with agents and projects
@@ -62,20 +62,20 @@ paperclipai company export abc123 --out ./full-export --include company,agents,p
paperclipai company export abc123 --out ./skills-only --include skills --skills review,deploy
```
-### What Gets Exported
+### 导出的内容
-- Company name, description, and metadata
-- Agent names, roles, reporting structure, and instructions
-- Project definitions and workspace config
-- Task/issue descriptions (when included)
-- Skill packages (as references or vendored content)
-- Adapter type and env input declarations in `.paperclip.yaml`
+- 公司名称、描述和元数据
+- 代理名称、角色、汇报结构和指令
+- 项目定义和工作区配置
+- 任务/议题描述(包含时)
+- 技能包(作为引用或内联内容)
+- `.paperclip.yaml` 中的适配器类型和环境输入声明
-Secret values, machine-local paths, and database IDs are **never** exported.
+密钥值、本机路径和数据库 ID **永远不会**被导出。
-## Importing a Company
+## 导入公司
-Import from a local directory, GitHub URL, or GitHub shorthand:
+从本地目录、GitHub URL 或 GitHub 简写导入:
```sh
# From a local folder
@@ -92,59 +92,59 @@ paperclipai company import org/repo
paperclipai company import org/repo/companies/acme
```
-### Options
+### 选项
-| Option | Description | Default |
+| 选项 | 描述 | 默认值 |
|--------|-------------|---------|
-| `--target ` | `new` (create a new company) or `existing` (merge into existing) | inferred from context |
-| `--company-id ` | Target company ID for `--target existing` | current context |
-| `--new-company-name ` | Override company name for `--target new` | from package |
-| `--include ` | Comma-separated set: `company`, `agents`, `projects`, `issues`, `tasks`, `skills` | auto-detected |
-| `--agents ` | Comma-separated agent slugs to import, or `all` | `all` |
-| `--collision ` | How to handle name conflicts: `rename`, `skip`, or `replace` | `rename` |
-| `--ref ` | Git ref for GitHub imports (branch, tag, or commit) | default branch |
-| `--dry-run` | Preview what would be imported without applying | `false` |
-| `--yes` | Skip the interactive confirmation prompt | `false` |
-| `--json` | Output result as JSON | `false` |
+| `--target ` | `new`(创建新公司)或 `existing`(合并到现有公司) | 根据上下文推断 |
+| `--company-id ` | `--target existing` 的目标公司 ID | 当前上下文 |
+| `--new-company-name ` | `--target new` 时覆盖公司名称 | 来自包 |
+| `--include ` | 逗号分隔的集合:`company`、`agents`、`projects`、`issues`、`tasks`、`skills` | 自动检测 |
+| `--agents ` | 逗号分隔的要导入的代理 slug,或 `all` | `all` |
+| `--collision ` | 如何处理名称冲突:`rename`、`skip` 或 `replace` | `rename` |
+| `--ref ` | GitHub 导入的 Git 引用(分支、标签或提交) | 默认分支 |
+| `--dry-run` | 预览将要导入的内容,但不实际应用 | `false` |
+| `--yes` | 跳过交互式确认提示 | `false` |
+| `--json` | 以 JSON 格式输出结果 | `false` |
-### Target Modes
+### 目标模式
-- **`new`** — Creates a fresh company from the package. Good for duplicating a company template.
-- **`existing`** — Merges the package into an existing company. Use `--company-id` to specify the target.
+- **`new`** — 从包创建一个全新的公司。适合复制公司模板。
+- **`existing`** — 将包合并到现有公司中。使用 `--company-id` 指定目标。
-If `--target` is not specified, Paperclip infers it: if a `--company-id` is provided (or one exists in context), it defaults to `existing`; otherwise `new`.
+如果未指定 `--target`,Paperclip 会自动推断:如果提供了 `--company-id`(或上下文中存在),则默认为 `existing`;否则为 `new`。
-### Collision Strategies
+### 冲突策略
-When importing into an existing company, agent or project names may conflict with existing ones:
+当导入到现有公司时,代理或项目名称可能与现有名称冲突:
-- **`rename`** (default) — Appends a suffix to avoid conflicts (e.g., `ceo` becomes `ceo-2`).
-- **`skip`** — Skips entities that already exist.
-- **`replace`** — Overwrites existing entities. Only available for non-safe imports (not available through the CEO API).
+- **`rename`**(默认) — 添加后缀以避免冲突(例如,`ceo` 变为 `ceo-2`)。
+- **`skip`** — 跳过已存在的实体。
+- **`replace`** — 覆盖现有实体。仅适用于非安全导入(不通过 CEO API 提供)。
-### Interactive Selection
+### 交互式选择
-When running interactively (no `--yes` or `--json` flags), the import command shows a selection picker before applying. You can choose exactly which agents, projects, skills, and tasks to import using a checkbox interface.
+在交互式运行时(没有 `--yes` 或 `--json` 标志),导入命令在应用前显示一个选择器。你可以使用复选框界面精确选择要导入的代理、项目、技能和任务。
-### Preview Before Applying
+### 应用前预览
-Always preview first with `--dry-run`:
+始终先使用 `--dry-run` 预览:
```sh
paperclipai company import org/repo --target existing --company-id abc123 --dry-run
```
-The preview shows:
-- **Package contents** — How many agents, projects, tasks, and skills are in the source
-- **Import plan** — What will be created, renamed, skipped, or replaced
-- **Env inputs** — Environment variables that may need values after import
-- **Warnings** — Potential issues like missing skills or unresolved references
+预览显示:
+- **包内容** — 源中有多少代理、项目、任务和技能
+- **导入计划** — 将要创建、重命名、跳过或替换的内容
+- **环境输入** — 导入后可能需要赋值的环境变量
+- **警告** — 潜在问题,如缺失的技能或未解析的引用
-Imported agents always land with timer heartbeats disabled. Assignment/on-demand wake behavior from the package is preserved, but scheduled runs stay off until a board operator re-enables them.
+导入的代理始终以定时心跳禁用的状态落地。包中的分配/按需唤醒行为会被保留,但定时运行保持关闭,直到董事会操作员重新启用。
-### Common Workflows
+### 常见工作流
-**Clone a company template from GitHub:**
+**从 GitHub 克隆公司模板:**
```sh
paperclipai company import org/company-templates/engineering-team \
@@ -152,7 +152,7 @@ paperclipai company import org/company-templates/engineering-team \
--new-company-name "My Engineering Team"
```
-**Add agents from a package into your existing company:**
+**将包中的代理添加到现有公司:**
```sh
paperclipai company import ./shared-agents \
@@ -162,13 +162,13 @@ paperclipai company import ./shared-agents \
--collision rename
```
-**Import a specific branch or tag:**
+**导入特定分支或标签:**
```sh
paperclipai company import org/repo --ref v2.0.0 --dry-run
```
-**Non-interactive import (CI/scripts):**
+**非交互式导入(CI/脚本):**
```sh
paperclipai company import ./package \
@@ -177,27 +177,27 @@ paperclipai company import ./package \
--json
```
-## API Endpoints
+## API 端点
-The CLI commands use these API endpoints under the hood:
+CLI 命令在底层使用以下 API 端点:
-| Action | Endpoint |
+| 操作 | 端点 |
|--------|----------|
-| Export company | `POST /api/companies/{companyId}/export` |
-| Preview import (existing company) | `POST /api/companies/{companyId}/imports/preview` |
-| Apply import (existing company) | `POST /api/companies/{companyId}/imports/apply` |
-| Preview import (new company) | `POST /api/companies/import/preview` |
-| Apply import (new company) | `POST /api/companies/import` |
+| 导出公司 | `POST /api/companies/{companyId}/export` |
+| 预览导入(现有公司) | `POST /api/companies/{companyId}/imports/preview` |
+| 应用导入(现有公司) | `POST /api/companies/{companyId}/imports/apply` |
+| 预览导入(新公司) | `POST /api/companies/import/preview` |
+| 应用导入(新公司) | `POST /api/companies/import` |
-CEO agents can also use the safe import routes (`/imports/preview` and `/imports/apply`) which enforce non-destructive rules: `replace` is rejected, collisions resolve with `rename` or `skip`, and issues are always created as new.
+CEO 代理也可以使用安全导入路由(`/imports/preview` 和 `/imports/apply`),这些路由强制执行非破坏性规则:`replace` 会被拒绝,冲突通过 `rename` 或 `skip` 解决,议题始终作为新建创建。
-## GitHub Sources
+## GitHub 源
-Paperclip supports several GitHub URL formats:
+Paperclip 支持多种 GitHub URL 格式:
-- Full URL: `https://github.com/org/repo`
-- Subfolder URL: `https://github.com/org/repo/tree/main/path/to/company`
-- Shorthand: `org/repo`
-- Shorthand with path: `org/repo/path/to/company`
+- 完整 URL:`https://github.com/org/repo`
+- 子文件夹 URL:`https://github.com/org/repo/tree/main/path/to/company`
+- 简写:`org/repo`
+- 带路径的简写:`org/repo/path/to/company`
-Use `--ref` to pin to a specific branch, tag, or commit hash when importing from GitHub.
+从 GitHub 导入时,使用 `--ref` 固定到特定的分支、标签或提交哈希。
diff --git a/docs/guides/board-operator/managing-agents.md b/docs/guides/board-operator/managing-agents.md
index 453b967f86..42dfcdc107 100644
--- a/docs/guides/board-operator/managing-agents.md
+++ b/docs/guides/board-operator/managing-agents.md
@@ -1,76 +1,76 @@
---
-title: Managing Agents
-summary: Hiring, configuring, pausing, and terminating agents
+title: 管理代理
+summary: 招聘、配置、暂停和终止代理
---
-Agents are the employees of your autonomous company. As the board operator, you have full control over their lifecycle.
+代理是你的自主公司的员工。作为董事会操作员,你对其生命周期拥有完全控制权。
-## Agent States
+## 代理状态
-| Status | Meaning |
+| 状态 | 含义 |
|--------|---------|
-| `active` | Ready to receive work |
-| `idle` | Active but no current heartbeat running |
-| `running` | Currently executing a heartbeat |
-| `error` | Last heartbeat failed |
-| `paused` | Manually paused or budget-paused |
-| `terminated` | Permanently deactivated (irreversible) |
+| `active` | 准备好接收工作 |
+| `idle` | 活跃但当前没有心跳在运行 |
+| `running` | 当前正在执行心跳 |
+| `error` | 上次心跳失败 |
+| `paused` | 手动暂停或预算暂停 |
+| `terminated` | 永久停用(不可逆) |
-## Creating Agents
+## 创建代理
-Create agents from the Agents page. Each agent requires:
+从代理页面创建代理。每个代理需要:
-- **Name** — unique identifier (used for @-mentions)
-- **Role** — `ceo`, `cto`, `manager`, `engineer`, `researcher`, etc.
-- **Reports to** — the agent's manager in the org tree
-- **Adapter type** — how the agent runs
-- **Adapter config** — runtime-specific settings (working directory, model, prompt, etc.)
-- **Capabilities** — short description of what this agent does
+- **Name** — 唯一标识符(用于 @-提及)
+- **Role** — `ceo`、`cto`、`manager`、`engineer`、`researcher` 等
+- **Reports to** — 代理在组织树中的经理
+- **Adapter type** — 代理的运行方式
+- **Adapter config** — 运行时特定设置(工作目录、模型、提示等)
+- **Capabilities** — 该代理能做什么的简短描述
-Common adapter choices:
-- `claude_local` / `codex_local` / `opencode_local` for local coding agents
-- `openclaw` / `http` for webhook-based external agents
-- `process` for generic local command execution
+常见适配器选择:
+- `claude_local` / `codex_local` / `opencode_local` 用于本地编码代理
+- `openclaw` / `http` 用于基于 webhook 的外部代理
+- `process` 用于通用本地命令执行
-For `opencode_local`, configure an explicit `adapterConfig.model` (`provider/model`).
-Paperclip validates the selected model against live `opencode models` output.
+对于 `opencode_local`,需要配置显式的 `adapterConfig.model`(`provider/model`)。
+Paperclip 会根据实时的 `opencode models` 输出验证所选模型。
-## Agent Hiring via Governance
+## 通过治理招聘代理
-Agents can request to hire subordinates. When this happens, you'll see a `hire_agent` approval in your approval queue. Review the proposed agent config and approve or reject.
+代理可以请求招聘下属。当这种情况发生时,你会在审批队列中看到一个 `hire_agent` 审批。审查拟聘代理的配置并批准或拒绝。
-## Configuring Agents
+## 配置代理
-Edit an agent's configuration from the agent detail page:
+从代理详情页面编辑代理的配置:
-- **Adapter config** — change model, prompt template, working directory, environment variables
-- **Heartbeat settings** — interval, cooldown, max concurrent runs, wake triggers
-- **Budget** — monthly spend limit
+- **Adapter config** — 更改模型、提示模板、工作目录、环境变量
+- **Heartbeat settings** — 间隔、冷却时间、最大并发运行数、唤醒触发器
+- **Budget** — 月度支出限制
-Use the "Test Environment" button to validate that the agent's adapter config is correct before running.
+使用"Test Environment"按钮在运行前验证代理的适配器配置是否正确。
-## Pausing and Resuming
+## 暂停和恢复
-Pause an agent to temporarily stop heartbeats:
+暂停代理以临时停止心跳:
```
POST /api/agents/{agentId}/pause
```
-Resume to restart:
+恢复以重新启动:
```
POST /api/agents/{agentId}/resume
```
-Agents are also auto-paused when they hit 100% of their monthly budget.
+代理在达到月度预算的 100% 时也会被自动暂停。
-## Terminating Agents
+## 终止代理
-Termination is permanent and irreversible:
+终止是永久且不可逆的:
```
POST /api/agents/{agentId}/terminate
```
-Only terminate agents you're certain you no longer need. Consider pausing first.
+只有在确定不再需要该代理时才终止。考虑先暂停。
diff --git a/docs/guides/board-operator/managing-tasks.md b/docs/guides/board-operator/managing-tasks.md
index 097cc362c1..5acc35f96b 100644
--- a/docs/guides/board-operator/managing-tasks.md
+++ b/docs/guides/board-operator/managing-tasks.md
@@ -1,25 +1,25 @@
---
-title: Managing Tasks
-summary: Creating issues, assigning work, and tracking progress
+title: 管理任务
+summary: 创建议题、分配工作和跟踪进度
---
-Issues (tasks) are the unit of work in Paperclip. They form a hierarchy that traces all work back to the company goal.
+议题(任务)是 Paperclip 中的工作单元。它们形成一个层级结构,将所有工作追溯到公司目标。
-## Creating Issues
+## 创建议题
-Create issues from the web UI or API. Each issue has:
+通过 Web UI 或 API 创建议题。每个议题包含:
-- **Title** — clear, actionable description
-- **Description** — detailed requirements (supports markdown)
-- **Priority** — `critical`, `high`, `medium`, or `low`
-- **Status** — `backlog`, `todo`, `in_progress`, `in_review`, `done`, `blocked`, or `cancelled`
-- **Assignee** — the agent responsible for the work
-- **Parent** — the parent issue (maintains the task hierarchy)
-- **Project** — groups related issues toward a deliverable
+- **Title** — 清晰、可操作的描述
+- **Description** — 详细的需求(支持 markdown)
+- **Priority** — `critical`、`high`、`medium` 或 `low`
+- **Status** — `backlog`、`todo`、`in_progress`、`in_review`、`done`、`blocked` 或 `cancelled`
+- **Assignee** — 负责该工作的代理
+- **Parent** — 父级议题(维护任务层级)
+- **Project** — 将相关议题归组到一个可交付物
-## Task Hierarchy
+## 任务层级
-Every piece of work should trace back to the company goal through parent issues:
+每项工作都应通过父级议题追溯到公司目标:
```
Company Goal: Build the #1 AI note-taking app
@@ -27,13 +27,13 @@ Company Goal: Build the #1 AI note-taking app
└── Implement JWT token signing (current task)
```
-This keeps agents aligned — they can always answer "why am I doing this?"
+这使代理保持一致 — 它们始终能回答"我为什么要做这件事?"
-## Assigning Work
+## 分配工作
-Assign an issue to an agent by setting the `assigneeAgentId`. If heartbeat wake-on-assignment is enabled, this triggers a heartbeat for the assigned agent.
+通过设置 `assigneeAgentId` 将议题分配给代理。如果启用了按分配唤醒的心跳,这将触发被分配代理的心跳。
-## Status Lifecycle
+## 状态生命周期
```
backlog -> todo -> in_progress -> in_review -> done
@@ -41,15 +41,15 @@ backlog -> todo -> in_progress -> in_review -> done
blocked -> todo / in_progress
```
-- `in_progress` requires an atomic checkout (only one agent at a time)
-- `blocked` should include a comment explaining the blocker
-- `done` and `cancelled` are terminal states
+- `in_progress` 需要原子签出(同一时间只能有一个代理)
+- `blocked` 应包含说明阻塞原因的评论
+- `done` 和 `cancelled` 是终态
-## Monitoring Progress
+## 监控进度
-Track task progress through:
+通过以下方式跟踪任务进度:
-- **Comments** — agents post updates as they work
-- **Status changes** — visible in the activity log
-- **Dashboard** — shows task counts by status and highlights stale work
-- **Run history** — see each heartbeat execution on the agent detail page
+- **评论** — 代理在工作时发布更新
+- **状态变更** — 在活动日志中可见
+- **仪表盘** — 显示按状态分类的任务计数并高亮过期工作
+- **运行历史** — 在代理详情页面查看每次心跳执行
diff --git a/docs/guides/board-operator/org-structure.md b/docs/guides/board-operator/org-structure.md
index 43e36b614e..0a0cd425e6 100644
--- a/docs/guides/board-operator/org-structure.md
+++ b/docs/guides/board-operator/org-structure.md
@@ -1,38 +1,38 @@
---
-title: Org Structure
-summary: Reporting hierarchy and chain of command
+title: 组织架构
+summary: 汇报层级和指挥链
---
-Paperclip enforces a strict organizational hierarchy. Every agent reports to exactly one manager, forming a tree with the CEO at the root.
+Paperclip 强制执行严格的组织层级。每个代理只向一个经理汇报,形成以 CEO 为根节点的树结构。
-## How It Works
+## 工作原理
-- The **CEO** has no manager (reports to the board/human operator)
-- Every other agent has a `reportsTo` field pointing to their manager
-- You can change an agent’s manager after creation from **Agent → Configuration → Reports to** (or via `PATCH /api/agents/{id}` with `reportsTo`)
-- Managers can create subtasks and delegate to their reports
-- Agents escalate blockers up the chain of command
+- **CEO** 没有经理(向董事会/人类操作员汇报)
+- 每个其他代理都有一个 `reportsTo` 字段指向其经理
+- 你可以在创建后从 **Agent → Configuration → Reports to** 更改代理的经理(或通过 `PATCH /api/agents/{id}` 设置 `reportsTo`)
+- 经理可以创建子任务并委派给其下属
+- 代理沿指挥链向上升级阻塞问题
-## Viewing the Org Chart
+## 查看组织架构图
-The org chart is available in the web UI under the Agents section. It shows the full reporting tree with agent status indicators.
+组织架构图在 Web UI 的代理部分可用。它显示完整的汇报树及代理状态指示器。
-Via the API:
+通过 API:
```
GET /api/companies/{companyId}/org
```
-## Chain of Command
+## 指挥链
-Every agent has access to their `chainOfCommand` — the list of managers from their direct report up to the CEO. This is used for:
+每个代理都可以访问其 `chainOfCommand` — 从其直接上级到 CEO 的经理列表。这用于:
-- **Escalation** — when an agent is blocked, they can reassign to their manager
-- **Delegation** — managers create subtasks for their reports
-- **Visibility** — managers can see what their reports are working on
+- **升级** — 当代理被阻塞时,它们可以重新分配给经理
+- **委派** — 经理为其下属创建子任务
+- **可见性** — 经理可以查看其下属正在做的工作
-## Rules
+## 规则
-- **No cycles** — the org tree is strictly acyclic
-- **Single parent** — each agent has exactly one manager
-- **Cross-team work** — agents can receive tasks from outside their reporting line, but cannot cancel them (must reassign to their manager)
+- **无循环** — 组织树严格无环
+- **单一父节点** — 每个代理只有一个经理
+- **跨团队工作** — 代理可以接收来自其汇报线以外的任务,但不能取消它们(必须重新分配给其经理)
diff --git a/docs/guides/openclaw-docker-setup.md b/docs/guides/openclaw-docker-setup.md
index bf8d149690..02ecab4d44 100644
--- a/docs/guides/openclaw-docker-setup.md
+++ b/docs/guides/openclaw-docker-setup.md
@@ -1,72 +1,72 @@
-# Running OpenClaw in Docker (Local Development)
+# 在 Docker 中运行 OpenClaw(本地开发)
-How to get OpenClaw running in a Docker container for local development and testing the Paperclip OpenClaw adapter integration.
+如何在 Docker 容器中运行 OpenClaw,用于本地开发和测试 Paperclip OpenClaw 适配器集成。
-## Automated Join Smoke Test (Recommended First)
+## 自动化加入冒烟测试(推荐首先运行)
-Paperclip includes an end-to-end join smoke harness:
+Paperclip 包含一个端到端加入冒烟测试工具:
```bash
pnpm smoke:openclaw-join
```
-The harness automates:
+该工具自动化以下流程:
-- invite creation (`allowedJoinTypes=agent`)
-- OpenClaw agent join request (`adapterType=openclaw`)
-- board approval
-- one-time API key claim (including invalid/replay claim checks)
-- wakeup callback delivery to a dockerized OpenClaw-style webhook receiver
+- 创建邀请(`allowedJoinTypes=agent`)
+- OpenClaw 代理加入请求(`adapterType=openclaw`)
+- 董事会批准
+- 一次性 API 密钥领取(包括无效/重放领取检查)
+- 向 Docker 化的 OpenClaw 风格 webhook 接收器发送唤醒回调
-By default, this uses a preconfigured Docker receiver image (`docker/openclaw-smoke`) so the run is deterministic and requires no manual OpenClaw config edits.
+默认情况下,使用预配置的 Docker 接收器镜像(`docker/openclaw-smoke`),因此运行是确定性的,无需手动编辑 OpenClaw 配置。
-Permissions note:
+权限说明:
-- The harness performs board-governed actions (invite creation, join approval, wakeup of the new agent).
-- In authenticated mode, provide board/operator auth or the run exits early with an explicit permissions error.
+- 该工具执行受董事会治理的操作(邀请创建、加入批准、新代理的唤醒)。
+- 在认证模式下,需提供董事会/操作员认证,否则运行会提前退出并显示明确的权限错误。
-## One-Command OpenClaw Gateway UI (Manual Docker Flow)
+## 一键 OpenClaw 网关 UI(手动 Docker 流程)
-To spin up OpenClaw in Docker and print a host-browser dashboard URL in one command:
+一条命令启动 Docker 中的 OpenClaw 并打印主机浏览器仪表盘 URL:
```bash
pnpm smoke:openclaw-docker-ui
```
-Default behavior is zero-flag: you can run the command as-is with no pairing-related env vars.
+默认行为是零标志:你可以直接运行该命令,无需任何配对相关的环境变量。
-What this command does:
+该命令执行的操作:
-- clones/updates `openclaw/openclaw` in `/tmp/openclaw-docker`
-- builds `openclaw:local` (unless `OPENCLAW_BUILD=0`)
-- writes isolated smoke config under `~/.openclaw-paperclip-smoke/openclaw.json` and Docker `.env`
-- pins agent model defaults to OpenAI (`openai/gpt-5.2` with OpenAI fallback)
-- starts `openclaw-gateway` via Compose (with required `/tmp` tmpfs override)
-- probes and prints a Paperclip host URL that is reachable from inside OpenClaw Docker
-- waits for health and prints:
+- 在 `/tmp/openclaw-docker` 中克隆/更新 `openclaw/openclaw`
+- 构建 `openclaw:local`(除非设置 `OPENCLAW_BUILD=0`)
+- 在 `~/.openclaw-paperclip-smoke/openclaw.json` 和 Docker `.env` 下写入隔离的冒烟测试配置
+- 将代理模型默认值固定为 OpenAI(`openai/gpt-5.2`,使用 OpenAI 作为后备)
+- 通过 Compose 启动 `openclaw-gateway`(包含所需的 `/tmp` tmpfs 覆盖)
+- 探测并打印从 OpenClaw Docker 内部可访问的 Paperclip 主机 URL
+- 等待健康检查并打印:
- `http://127.0.0.1:18789/#token=...`
-- disables Control UI device pairing by default for local smoke ergonomics
+- 默认禁用 Control UI 设备配对,以方便本地冒烟测试
-Environment knobs:
+环境变量控制项:
-- `OPENAI_API_KEY` (required; loaded from env or `~/.secrets`)
-- `OPENCLAW_DOCKER_DIR` (default `/tmp/openclaw-docker`)
-- `OPENCLAW_GATEWAY_PORT` (default `18789`)
-- `OPENCLAW_GATEWAY_TOKEN` (default random)
-- `OPENCLAW_BUILD=0` to skip rebuild
-- `OPENCLAW_OPEN_BROWSER=1` to auto-open the URL on macOS
-- `OPENCLAW_DISABLE_DEVICE_AUTH=1` (default) disables Control UI device pairing for local smoke
-- `OPENCLAW_DISABLE_DEVICE_AUTH=0` keeps pairing enabled (then approve browser with `devices` CLI commands)
-- `OPENCLAW_MODEL_PRIMARY` (default `openai/gpt-5.2`)
-- `OPENCLAW_MODEL_FALLBACK` (default `openai/gpt-5.2-chat-latest`)
-- `OPENCLAW_CONFIG_DIR` (default `~/.openclaw-paperclip-smoke`)
-- `OPENCLAW_RESET_STATE=1` (default) resets smoke agent state on each run to avoid stale auth/session drift
-- `PAPERCLIP_HOST_PORT` (default `3100`)
-- `PAPERCLIP_HOST_FROM_CONTAINER` (default `host.docker.internal`)
+- `OPENAI_API_KEY`(必需;从环境或 `~/.secrets` 加载)
+- `OPENCLAW_DOCKER_DIR`(默认 `/tmp/openclaw-docker`)
+- `OPENCLAW_GATEWAY_PORT`(默认 `18789`)
+- `OPENCLAW_GATEWAY_TOKEN`(默认随机生成)
+- `OPENCLAW_BUILD=0` 跳过重新构建
+- `OPENCLAW_OPEN_BROWSER=1` 在 macOS 上自动打开 URL
+- `OPENCLAW_DISABLE_DEVICE_AUTH=1`(默认)禁用 Control UI 设备配对以方便本地冒烟测试
+- `OPENCLAW_DISABLE_DEVICE_AUTH=0` 保持配对启用(然后使用 `devices` CLI 命令批准浏览器)
+- `OPENCLAW_MODEL_PRIMARY`(默认 `openai/gpt-5.2`)
+- `OPENCLAW_MODEL_FALLBACK`(默认 `openai/gpt-5.2-chat-latest`)
+- `OPENCLAW_CONFIG_DIR`(默认 `~/.openclaw-paperclip-smoke`)
+- `OPENCLAW_RESET_STATE=1`(默认)在每次运行时重置冒烟测试代理状态,以避免过期的认证/会话偏移
+- `PAPERCLIP_HOST_PORT`(默认 `3100`)
+- `PAPERCLIP_HOST_FROM_CONTAINER`(默认 `host.docker.internal`)
-### Authenticated mode
+### 认证模式
-If your Paperclip deployment is `authenticated`, provide auth context:
+如果你的 Paperclip 部署处于 `authenticated` 模式,需提供认证上下文:
```bash
PAPERCLIP_AUTH_HEADER="Bearer " pnpm smoke:openclaw-join
@@ -74,34 +74,34 @@ PAPERCLIP_AUTH_HEADER="Bearer " pnpm smoke:openclaw-join
PAPERCLIP_COOKIE="your_session_cookie=..." pnpm smoke:openclaw-join
```
-### Network topology tips
+### 网络拓扑提示
-- Local same-host smoke: default callback uses `http://127.0.0.1:/webhook`.
-- Inside OpenClaw Docker, `127.0.0.1` points to the container itself, not your host Paperclip server.
-- For invite/onboarding URLs consumed by OpenClaw in Docker, use the script-printed Paperclip URL (typically `http://host.docker.internal:3100`).
-- If Paperclip rejects the container-visible host with a hostname error, allow it from host:
+- 本地同主机冒烟测试:默认回调使用 `http://127.0.0.1:/webhook`。
+- 在 OpenClaw Docker 内部,`127.0.0.1` 指向容器本身,而非你的主机 Paperclip 服务器。
+- 对于 OpenClaw Docker 内部使用的邀请/加入 URL,使用脚本打印的 Paperclip URL(通常是 `http://host.docker.internal:3100`)。
+- 如果 Paperclip 因主机名错误拒绝容器可见的主机,从主机端允许它:
```bash
pnpm paperclipai allowed-hostname host.docker.internal
```
-Then restart Paperclip and rerun the smoke script.
-- Docker/remote OpenClaw: prefer a reachable hostname (Docker host alias, Tailscale hostname, or public domain).
-- Authenticated/private mode: ensure hostnames are in the allowed list when required:
+然后重启 Paperclip 并重新运行冒烟测试脚本。
+- Docker/远程 OpenClaw:优先使用可达的主机名(Docker 主机别名、Tailscale 主机名或公共域名)。
+- 认证/私有模式:在需要时确保主机名在允许列表中:
```bash
pnpm paperclipai allowed-hostname
```
-## Prerequisites
+## 前提条件
-- **Docker Desktop v29+** (with Docker Sandbox support)
-- **2 GB+ RAM** available for the Docker image build
-- **API keys** in `~/.secrets` (at minimum `OPENAI_API_KEY`)
+- **Docker Desktop v29+**(支持 Docker Sandbox)
+- **2 GB+ 内存** 可用于 Docker 镜像构建
+- **API 密钥** 在 `~/.secrets` 中(至少需要 `OPENAI_API_KEY`)
-## Option A: Docker Sandbox (Recommended)
+## 方案 A:Docker Sandbox(推荐)
-Docker Sandbox provides better isolation (microVM-based) and simpler setup than Docker Compose. Requires Docker Desktop v29+ / Docker Sandbox v0.12+.
+Docker Sandbox 提供更好的隔离(基于微虚拟机)和比 Docker Compose 更简单的设置。需要 Docker Desktop v29+ / Docker Sandbox v0.12+。
```bash
# 1. Clone the OpenClaw repo and build the image
@@ -163,7 +163,7 @@ docker sandbox exec -e OPENAI_API_KEY="$OPENAI_API_KEY" -w /app openclaw \
node dist/index.js status
```
-### Sandbox Management
+### Sandbox 管理
```bash
# List sandboxes
@@ -182,9 +182,9 @@ docker sandbox rm openclaw
docker sandbox version
```
-## Option B: Docker Compose (Fallback)
+## 方案 B:Docker Compose(备选)
-Use this if Docker Sandbox is not available (Docker Desktop < v29).
+如果 Docker Sandbox 不可用(Docker Desktop < v29),使用此方案。
```bash
# 1. Clone the OpenClaw repo
@@ -263,9 +263,9 @@ sleep 15
docker compose run --rm openclaw-cli dashboard --no-open
```
-The dashboard URL will look like: `http://127.0.0.1:18789/#token=`
+仪表盘 URL 格式如下:`http://127.0.0.1:18789/#token=`
-### Docker Compose Management
+### Docker Compose 管理
```bash
cd /tmp/openclaw-docker
@@ -286,11 +286,11 @@ docker compose run --rm openclaw-cli status
docker compose run --rm openclaw-cli dashboard --no-open
```
-## Known Issues and Fixes
+## 已知问题和修复
-### "no space left on device" when starting containers
+### 启动容器时出现 "no space left on device"
-Docker Desktop's virtual disk may be full.
+Docker Desktop 的虚拟磁盘可能已满。
```bash
docker system df # check usage
@@ -298,9 +298,9 @@ docker system prune -f # remove stopped containers, unused networks
docker image prune -f # remove dangling images
```
-### "Unable to create fallback OpenClaw temp dir: /tmp/openclaw-1000" (Compose only)
+### "Unable to create fallback OpenClaw temp dir: /tmp/openclaw-1000"(仅 Compose)
-The container can't write to `/tmp`. Add a `tmpfs` mount to `docker-compose.yml` for **both** services:
+容器无法写入 `/tmp`。在 `docker-compose.yml` 中为**两个**服务添加 `tmpfs` 挂载:
```yaml
services:
@@ -312,38 +312,38 @@ services:
- /tmp:exec,size=512M
```
-This issue does not affect the Docker Sandbox approach.
+此问题不影响 Docker Sandbox 方案。
-### Node version mismatch in community template images
+### 社区模板镜像中的 Node 版本不匹配
-Some community-built sandbox templates (e.g. `olegselajev241/openclaw-dmr:latest`) ship Node 20, but OpenClaw requires Node >=22.12.0. Use our locally built `openclaw:local` image as the sandbox template instead, which includes Node 22.
+一些社区构建的 sandbox 模板(例如 `olegselajev241/openclaw-dmr:latest`)附带 Node 20,但 OpenClaw 要求 Node >=22.12.0。请使用我们本地构建的 `openclaw:local` 镜像作为 sandbox 模板,其中包含 Node 22。
-### Gateway takes ~15 seconds to respond after start
+### 网关启动后约 15 秒才会响应
-The Node.js gateway needs time to initialize. Wait 15 seconds before hitting `http://127.0.0.1:18789/`.
+Node.js 网关需要时间初始化。在访问 `http://127.0.0.1:18789/` 之前等待 15 秒。
-### CLAUDE_AI_SESSION_KEY warnings (Compose only)
+### CLAUDE_AI_SESSION_KEY 警告(仅 Compose)
-These Docker Compose warnings are harmless and can be ignored:
+这些 Docker Compose 警告是无害的,可以忽略:
```
level=warning msg="The \"CLAUDE_AI_SESSION_KEY\" variable is not set. Defaulting to a blank string."
```
-## Configuration
+## 配置
-Config file: `~/.openclaw/openclaw.json` (JSON5 format)
+配置文件:`~/.openclaw/openclaw.json`(JSON5 格式)
-Key settings:
-- `gateway.auth.token` — the auth token for the web UI and API
-- `agents.defaults.model.primary` — the AI model (use `openai/gpt-5.2` or newer)
-- `env.OPENAI_API_KEY` — references the `OPENAI_API_KEY` env var (Compose approach)
+关键设置:
+- `gateway.auth.token` — Web UI 和 API 的认证令牌
+- `agents.defaults.model.primary` — AI 模型(使用 `openai/gpt-5.2` 或更新版本)
+- `env.OPENAI_API_KEY` — 引用 `OPENAI_API_KEY` 环境变量(Compose 方案)
-API keys are stored in `~/.secrets` and passed into containers via env vars.
+API 密钥存储在 `~/.secrets` 中,通过环境变量传递到容器中。
-## Reference
+## 参考资料
-- [OpenClaw Docker docs](https://docs.openclaw.ai/install/docker)
-- [OpenClaw Configuration Reference](https://docs.openclaw.ai/gateway/configuration-reference)
-- [Docker blog: Run OpenClaw Securely in Docker Sandboxes](https://www.docker.com/blog/run-openclaw-securely-in-docker-sandboxes/)
-- [Docker Sandbox docs](https://docs.docker.com/ai/sandboxes)
-- [OpenAI Models](https://platform.openai.com/docs/models) — current models: gpt-5.2, gpt-5.2-chat-latest, gpt-5.2-pro
+- [OpenClaw Docker 文档](https://docs.openclaw.ai/install/docker)
+- [OpenClaw 配置参考](https://docs.openclaw.ai/gateway/configuration-reference)
+- [Docker 博客:在 Docker Sandbox 中安全运行 OpenClaw](https://www.docker.com/blog/run-openclaw-securely-in-docker-sandboxes/)
+- [Docker Sandbox 文档](https://docs.docker.com/ai/sandboxes)
+- [OpenAI 模型](https://platform.openai.com/docs/models) — 当前模型:gpt-5.2、gpt-5.2-chat-latest、gpt-5.2-pro
diff --git a/docs/start/architecture.md b/docs/start/architecture.md
index 27d72575e1..6b6ef7360c 100644
--- a/docs/start/architecture.md
+++ b/docs/start/architecture.md
@@ -1,11 +1,11 @@
---
-title: Architecture
-summary: Stack overview, request flow, and adapter model
+title: 架构
+summary: 技术栈概览、请求流程和适配器模型
---
-Paperclip is a monorepo with four main layers.
+Paperclip 是一个包含四个主要层次的 monorepo。
-## Stack Overview
+## 技术栈概览
```
┌─────────────────────────────────────┐
@@ -24,75 +24,75 @@ Paperclip is a monorepo with four main layers.
└─────────────────────────────────────┘
```
-## Technology Stack
+## 技术栈
-| Layer | Technology |
+| 层次 | 技术 |
|-------|-----------|
-| Frontend | React 19, Vite 6, React Router 7, Radix UI, Tailwind CSS 4, TanStack Query |
-| Backend | Node.js 20+, Express.js 5, TypeScript |
-| Database | PostgreSQL 17 (or embedded PGlite), Drizzle ORM |
-| Auth | Better Auth (sessions + API keys) |
-| Adapters | Claude Code CLI, Codex CLI, shell process, HTTP webhook |
-| Package manager | pnpm 9 with workspaces |
+| 前端 | React 19, Vite 6, React Router 7, Radix UI, Tailwind CSS 4, TanStack Query |
+| 后端 | Node.js 20+, Express.js 5, TypeScript |
+| 数据库 | PostgreSQL 17(或内嵌 PGlite), Drizzle ORM |
+| 认证 | Better Auth(会话 + API 密钥) |
+| 适配器 | Claude Code CLI, Codex CLI, shell 进程, HTTP webhook |
+| 包管理器 | pnpm 9 with workspaces |
-## Repository Structure
+## 仓库结构
```
paperclip/
-├── ui/ # React frontend
-│ ├── src/pages/ # Route pages
-│ ├── src/components/ # React components
-│ ├── src/api/ # API client
-│ └── src/context/ # React context providers
+├── ui/ # React 前端
+│ ├── src/pages/ # 路由页面
+│ ├── src/components/ # React 组件
+│ ├── src/api/ # API 客户端
+│ └── src/context/ # React 上下文提供者
│
├── server/ # Express.js API
-│ ├── src/routes/ # REST endpoints
-│ ├── src/services/ # Business logic
-│ ├── src/adapters/ # Agent execution adapters
-│ └── src/middleware/ # Auth, logging
+│ ├── src/routes/ # REST 端点
+│ ├── src/services/ # 业务逻辑
+│ ├── src/adapters/ # 代理执行适配器
+│ └── src/middleware/ # 认证、日志
│
├── packages/
-│ ├── db/ # Drizzle schema + migrations
-│ ├── shared/ # API types, constants, validators
-│ ├── adapter-utils/ # Adapter interfaces and helpers
+│ ├── db/ # Drizzle schema + 迁移
+│ ├── shared/ # API 类型、常量、验证器
+│ ├── adapter-utils/ # 适配器接口和辅助工具
│ └── adapters/
-│ ├── claude-local/ # Claude Code adapter
-│ └── codex-local/ # OpenAI Codex adapter
+│ ├── claude-local/ # Claude Code 适配器
+│ └── codex-local/ # OpenAI Codex 适配器
│
-├── skills/ # Agent skills
-│ └── paperclip/ # Core Paperclip skill (heartbeat protocol)
+├── skills/ # 代理技能
+│ └── paperclip/ # 核心 Paperclip 技能(心跳协议)
│
-├── cli/ # CLI client
-│ └── src/ # Setup and control-plane commands
+├── cli/ # CLI 客户端
+│ └── src/ # 设置和控制平面命令
│
-└── doc/ # Internal documentation
+└── doc/ # 内部文档
```
-## Request Flow
+## 请求流程
-When a heartbeat fires:
+当心跳触发时:
-1. **Trigger** — Scheduler, manual invoke, or event (assignment, mention) triggers a heartbeat
-2. **Adapter invocation** — Server calls the configured adapter's `execute()` function
-3. **Agent process** — Adapter spawns the agent (e.g. Claude Code CLI) with Paperclip env vars and a prompt
-4. **Agent work** — The agent calls Paperclip's REST API to check assignments, checkout tasks, do work, and update status
-5. **Result capture** — Adapter captures stdout, parses usage/cost data, extracts session state
-6. **Run record** — Server records the run result, costs, and any session state for next heartbeat
+1. **触发** — 调度器、手动调用或事件(任务分配、提及)触发心跳
+2. **适配器调用** — 服务器调用已配置适配器的 `execute()` 函数
+3. **代理进程** — 适配器使用 Paperclip 环境变量和提示词生成代理(例如 Claude Code CLI)
+4. **代理工作** — 代理调用 Paperclip 的 REST API 来检查任务分配、检出任务、执行工作并更新状态
+5. **结果捕获** — 适配器捕获 stdout,解析使用量/成本数据,提取会话状态
+6. **运行记录** — 服务器记录运行结果、成本以及下次心跳的任何会话状态
-## Adapter Model
+## 适配器模型
-Adapters are the bridge between Paperclip and agent runtimes. Each adapter is a package with three modules:
+适配器是 Paperclip 与代理运行时之间的桥梁。每个适配器是一个包含三个模块的包:
-- **Server module** — `execute()` function that spawns/calls the agent, plus environment diagnostics
-- **UI module** — stdout parser for the run viewer, config form fields for agent creation
-- **CLI module** — terminal formatter for `paperclipai run --watch`
+- **服务器模块** — 生成/调用代理的 `execute()` 函数,以及环境诊断
+- **UI 模块** — 运行查看器的 stdout 解析器,代理创建的配置表单字段
+- **CLI 模块** — `paperclipai run --watch` 的终端格式化器
-Built-in adapters: `claude_local`, `codex_local`, `process`, `http`. You can create custom adapters for any runtime.
+内置适配器:`claude_local`、`codex_local`、`process`、`http`。你可以为任何运行时创建自定义适配器。
-## Key Design Decisions
+## 关键设计决策
-- **Control plane, not execution plane** — Paperclip orchestrates agents; it doesn't run them
-- **Company-scoped** — all entities belong to exactly one company; strict data boundaries
-- **Single-assignee tasks** — atomic checkout prevents concurrent work on the same task
-- **Adapter-agnostic** — any runtime that can call an HTTP API works as an agent
-- **Embedded by default** — zero-config local mode with embedded PostgreSQL
+- **控制平面,而非执行平面** — Paperclip 编排代理;它不运行代理
+- **公司级作用域** — 所有实体都属于恰好一家公司;严格的数据边界
+- **单受理人任务** — 原子检出防止对同一任务的并发工作
+- **适配器无关性** — 任何能调用 HTTP API 的运行时都可以作为代理
+- **默认内嵌** — 使用内嵌 PostgreSQL 的零配置本地模式
diff --git a/docs/start/core-concepts.md b/docs/start/core-concepts.md
index 33de5806a8..9607310999 100644
--- a/docs/start/core-concepts.md
+++ b/docs/start/core-concepts.md
@@ -1,44 +1,44 @@
---
-title: Core Concepts
-summary: Companies, agents, issues, delegation, heartbeats, and governance
+title: 核心概念
+summary: 公司、代理、工单、委派、心跳和治理
---
-Paperclip organizes autonomous AI work around six key concepts.
+Paperclip 围绕六个关键概念组织自主 AI 工作。
-## Company
+## 公司
-A company is the top-level unit of organization. Each company has:
+公司是最高级别的组织单元。每家公司拥有:
-- A **goal** — the reason it exists (e.g. "Build the #1 AI note-taking app at $1M MRR")
-- **Employees** — every employee is an AI agent
-- **Org structure** — who reports to whom
-- **Budget** — monthly spend limits in cents
-- **Task hierarchy** — all work traces back to the company goal
+- **目标** — 公司存在的原因(例如"构建排名第一的 AI 笔记应用,达到 100 万美元月经常性收入")
+- **员工** — 每位员工都是 AI 代理
+- **组织结构** — 谁向谁汇报
+- **预算** — 以美分为单位的月度支出限额
+- **任务层级** — 所有工作都可追溯至公司目标
-One Paperclip instance can run multiple companies.
+一个 Paperclip 实例可以运行多家公司。
-## Agents
+## 代理
-Every employee is an AI agent. Each agent has:
+每位员工都是 AI 代理。每个代理拥有:
-- **Adapter type + config** — how the agent runs (Claude Code, Codex, shell process, HTTP webhook)
-- **Role and reporting** — title, who they report to, who reports to them
-- **Capabilities** — a short description of what the agent does
-- **Budget** — per-agent monthly spend limit
-- **Status** — active, idle, running, error, paused, or terminated
+- **适配器类型 + 配置** — 代理如何运行(Claude Code、Codex、shell 进程、HTTP webhook)
+- **角色和汇报关系** — 职位、向谁汇报、谁向其汇报
+- **能力** — 对代理职责的简短描述
+- **预算** — 每个代理的月度支出限额
+- **状态** — active(活跃)、idle(空闲)、running(运行中)、error(错误)、paused(暂停)或 terminated(已终止)
-Agents are organized in a strict tree hierarchy. Every agent reports to exactly one manager (except the CEO). This chain of command is used for escalation and delegation.
+代理按严格的树状层级组织。每个代理只向一位经理汇报(CEO 除外)。这种指挥链用于升级和委派。
-## Issues (Tasks)
+## 工单(任务)
-Issues are the unit of work. Every issue has:
+工单是工作的基本单位。每个工单拥有:
-- A title, description, status, and priority
-- An assignee (one agent at a time)
-- A parent issue (creating a traceable hierarchy back to the company goal)
-- A project and optional goal association
+- 标题、描述、状态和优先级
+- 一个受理人(同一时间只有一个代理)
+- 一个父工单(创建可追溯至公司目标的层级结构)
+- 一个项目和可选的目标关联
-### Status Lifecycle
+### 状态生命周期
```
backlog -> todo -> in_progress -> in_review -> done
@@ -46,41 +46,41 @@ backlog -> todo -> in_progress -> in_review -> done
blocked
```
-Terminal states: `done`, `cancelled`.
+终态:`done`、`cancelled`。
-The transition to `in_progress` requires an **atomic checkout** — only one agent can own a task at a time. If two agents try to claim the same task simultaneously, one gets a `409 Conflict`.
+转换到 `in_progress` 需要**原子检出** — 同一时间只有一个代理可以拥有一个任务。如果两个代理同时尝试认领同一个任务,其中一个会收到 `409 Conflict`。
-## Delegation
+## 委派
-The CEO is the primary delegator. When you set company goals, the CEO:
+CEO 是主要的委派者。当你设定公司目标时,CEO 会:
-1. Creates a strategy and submits it for your approval
-2. Breaks approved goals into tasks
-3. Assigns tasks to agents based on their role and capabilities
-4. Hires new agents when needed (subject to your approval)
+1. 创建策略并提交供你审批
+2. 将已批准的目标拆分为任务
+3. 根据代理的角色和能力将任务分配给代理
+4. 在需要时招聘新代理(需经你的审批)
-You don't need to manually assign every task — set the goals and let the CEO organize the work. You approve key decisions (strategy, hiring) and monitor progress. See the [How Delegation Works](/guides/board-operator/delegation) guide for the full lifecycle.
+你不需要手动分配每个任务 — 设定目标,让 CEO 来组织工作。你负责审批关键决策(策略、招聘)并监控进度。请参阅[委派工作原理](/guides/board-operator/delegation)指南了解完整的生命周期。
-## Heartbeats
+## 心跳
-Agents don't run continuously. They wake up in **heartbeats** — short execution windows triggered by Paperclip.
+代理不会持续运行。它们以**心跳**方式唤醒 — 由 Paperclip 触发的短暂执行窗口。
-A heartbeat can be triggered by:
+心跳可以由以下方式触发:
-- **Schedule** — periodic timer (e.g. every hour)
-- **Assignment** — a new task is assigned to the agent
-- **Comment** — someone @-mentions the agent
-- **Manual** — a human clicks "Invoke" in the UI
-- **Approval resolution** — a pending approval is approved or rejected
+- **定时** — 周期性计时器(例如每小时)
+- **任务分配** — 新任务被分配给代理
+- **评论** — 有人 @提及了代理
+- **手动** — 人工在 UI 中点击"调用"
+- **审批结果** — 待处理的审批被批准或拒绝
-Each heartbeat, the agent: checks its identity, reviews assignments, picks work, checks out a task, does the work, and updates status. This is the **heartbeat protocol**.
+每次心跳时,代理会:检查其身份、查看分配的任务、选择工作、检出任务、执行工作并更新状态。这就是**心跳协议**。
-## Governance
+## 治理
-Some actions require board (human) approval:
+某些操作需要董事会(人工)审批:
-- **Hiring agents** — agents can request to hire subordinates, but the board must approve
-- **CEO strategy** — the CEO's initial strategic plan requires board approval
-- **Board overrides** — the board can pause, resume, or terminate any agent and reassign any task
+- **招聘代理** — 代理可以请求招聘下属,但董事会必须批准
+- **CEO 策略** — CEO 的初始战略计划需要董事会批准
+- **董事会否决** — 董事会可以暂停、恢复或终止任何代理,并重新分配任何任务
-The board operator has full visibility and control through the web UI. Every mutation is logged in an **activity audit trail**.
+董事会操作者通过 Web UI 拥有完整的可见性和控制权。每次变更都记录在**活动审计追踪**中。
diff --git a/docs/start/quickstart.md b/docs/start/quickstart.md
index 1ad30fcdfa..9fb979c476 100644
--- a/docs/start/quickstart.md
+++ b/docs/start/quickstart.md
@@ -1,60 +1,60 @@
---
-title: Quickstart
-summary: Get Paperclip running in minutes
+title: 快速开始
+summary: 几分钟内启动并运行 Paperclip
---
-Get Paperclip running locally in under 5 minutes.
+在 5 分钟内在本地启动并运行 Paperclip。
-## Quick Start (Recommended)
+## 快速开始(推荐)
```sh
npx paperclipai onboard --yes
```
-This walks you through setup, configures your environment, and gets Paperclip running.
+这将引导你完成设置、配置你的环境并启动 Paperclip。
-To start Paperclip again later:
+稍后再次启动 Paperclip:
```sh
npx paperclipai run
```
-> **Note:** If you used `npx` for setup, always use `npx paperclipai` to run commands. The `pnpm paperclipai` form only works inside a cloned copy of the Paperclip repository (see Local Development below).
+> **注意:** 如果你使用 `npx` 进行设置,请始终使用 `npx paperclipai` 来运行命令。`pnpm paperclipai` 形式仅在克隆的 Paperclip 仓库副本中有效(请参阅下方的本地开发部分)。
-## Local Development
+## 本地开发
-For contributors working on Paperclip itself. Prerequisites: Node.js 20+ and pnpm 9+.
+适用于参与 Paperclip 本身开发的贡献者。前提条件:Node.js 20+ 和 pnpm 9+。
-Clone the repository, then:
+克隆仓库,然后:
```sh
pnpm install
pnpm dev
```
-This starts the API server and UI at [http://localhost:3100](http://localhost:3100).
+这将在 [http://localhost:3100](http://localhost:3100) 启动 API 服务器和 UI。
-No external database required — Paperclip uses an embedded PostgreSQL instance by default.
+无需外部数据库 — Paperclip 默认使用内嵌的 PostgreSQL 实例。
-When working from the cloned repo, you can also use:
+在克隆的仓库中工作时,你也可以使用:
```sh
pnpm paperclipai run
```
-This auto-onboards if config is missing, runs health checks with auto-repair, and starts the server.
+如果缺少配置,这将自动进行初始化设置,运行带有自动修复功能的健康检查,然后启动服务器。
-## What's Next
+## 下一步
-Once Paperclip is running:
+一旦 Paperclip 运行起来:
-1. Create your first company in the web UI
-2. Define a company goal
-3. Create a CEO agent and configure its adapter
-4. Build out the org chart with more agents
-5. Set budgets and assign initial tasks
-6. Hit go — agents start their heartbeats and the company runs
+1. 在 Web UI 中创建你的第一家公司
+2. 定义公司目标
+3. 创建 CEO 代理并配置其适配器
+4. 通过添加更多代理来构建组织架构图
+5. 设置预算并分配初始任务
+6. 点击启动 — 代理开始其心跳,公司开始运转
-
- Learn the key concepts behind Paperclip
+
+ 了解 Paperclip 背后的关键概念
diff --git a/docs/start/what-is-paperclip.md b/docs/start/what-is-paperclip.md
index ea3f4ed84f..8858cf3a50 100644
--- a/docs/start/what-is-paperclip.md
+++ b/docs/start/what-is-paperclip.md
@@ -1,39 +1,39 @@
---
-title: What is Paperclip?
-summary: The control plane for autonomous AI companies
+title: 什么是 Paperclip?
+summary: 自主 AI 公司的控制平面
---
-Paperclip is the control plane for autonomous AI companies. It is the infrastructure backbone that enables AI workforces to operate with structure, governance, and accountability.
+Paperclip 是自主 AI 公司的控制平面。它是使 AI 员工团队能够以结构化、治理化和可问责的方式运行的基础设施骨干。
-One instance of Paperclip can run multiple companies. Each company has employees (AI agents), org structure, goals, budgets, and task management — everything a real company needs, except the operating system is real software.
+一个 Paperclip 实例可以运行多家公司。每家公司拥有员工(AI 代理)、组织结构、目标、预算和任务管理——一家真实公司所需的一切,只不过其操作系统是真正的软件。
-## The Problem
+## 问题
-Task management software doesn't go far enough. When your entire workforce is AI agents, you need more than a to-do list — you need a **control plane** for an entire company.
+任务管理软件做得还不够。当你的整个员工团队都是 AI 代理时,你需要的不仅仅是一个待办事项列表——你需要一个用于整个公司的**控制平面**。
-## What Paperclip Does
+## Paperclip 的功能
-Paperclip is the command, communication, and control plane for a company of AI agents. It is the single place where you:
+Paperclip 是 AI 代理公司的指挥、通信和控制平面。它是你集中完成以下工作的地方:
-- **Manage agents as employees** — hire, organize, and track who does what
-- **Define org structure** — org charts that agents themselves operate within
-- **Track work in real time** — see at any moment what every agent is working on
-- **Control costs** — token salary budgets per agent, spend tracking, burn rate
-- **Align to goals** — agents see how their work serves the bigger mission
-- **Govern autonomy** — board approval gates, activity audit trails, budget enforcement
+- **将代理作为员工管理** — 招聘、组织和跟踪谁做什么
+- **定义组织结构** — 代理在其中运作的组织架构图
+- **实时跟踪工作** — 随时查看每个代理正在做什么
+- **控制成本** — 每个代理的 token 薪资预算、支出跟踪、消耗速率
+- **对齐目标** — 代理了解其工作如何服务于更大的使命
+- **治理自主权** — 董事会审批门控、活动审计追踪、预算执行
-## Two Layers
+## 两个层次
-### 1. Control Plane (Paperclip)
+### 1. 控制平面(Paperclip)
-The central nervous system. Manages agent registry and org chart, task assignment and status, budget and token spend tracking, goal hierarchy, and heartbeat monitoring.
+中枢神经系统。管理代理注册和组织架构图、任务分配和状态、预算和 token 支出跟踪、目标层级以及心跳监控。
-### 2. Execution Services (Adapters)
+### 2. 执行服务(适配器)
-Agents run externally and report into the control plane. Adapters connect different execution environments — Claude Code, OpenAI Codex, shell processes, HTTP webhooks, or any runtime that can call an API.
+代理在外部运行并向控制平面报告。适配器连接不同的执行环境 — Claude Code、OpenAI Codex、shell 进程、HTTP webhook,或任何能调用 API 的运行时。
-The control plane doesn't run agents. It orchestrates them. Agents run wherever they run and phone home.
+控制平面不运行代理。它编排代理。代理在各自的环境中运行,然后回报状态。
-## Core Principle
+## 核心原则
-You should be able to look at Paperclip and understand your entire company at a glance — who's doing what, how much it costs, and whether it's working.
+你应该能够通过查看 Paperclip 一目了然地了解整个公司——谁在做什么、花费多少、以及是否有效。
diff --git a/evals/README.md b/evals/README.md
index 5974d98cfe..4fc5aea613 100644
--- a/evals/README.md
+++ b/evals/README.md
@@ -1,64 +1,64 @@
-# Paperclip Evals
+# Paperclip 评估
-Eval framework for testing Paperclip agent behaviors across models and prompt versions.
+用于跨模型和提示版本测试 Paperclip 智能体行为的评估框架。
-See [the evals framework plan](../doc/plans/2026-03-13-agent-evals-framework.md) for full design rationale.
+完整设计原理参见[评估框架计划](../doc/plans/2026-03-13-agent-evals-framework.md)。
-## Quick Start
+## 快速开始
-### Prerequisites
+### 前置条件
```bash
pnpm add -g promptfoo
```
-You need an API key for at least one provider. Set one of:
+你需要至少一个提供商的 API 密钥。设置以下其中一个:
```bash
-export OPENROUTER_API_KEY=sk-or-... # OpenRouter (recommended - test multiple models)
-export ANTHROPIC_API_KEY=sk-ant-... # Anthropic direct
-export OPENAI_API_KEY=sk-... # OpenAI direct
+export OPENROUTER_API_KEY=sk-or-... # OpenRouter(推荐 - 可测试多个模型)
+export ANTHROPIC_API_KEY=sk-ant-... # Anthropic 直连
+export OPENAI_API_KEY=sk-... # OpenAI 直连
```
-### Run evals
+### 运行评估
```bash
-# Smoke test (default models)
+# 冒烟测试(默认模型)
pnpm evals:smoke
-# Or run promptfoo directly
+# 或直接运行 promptfoo
cd evals/promptfoo
promptfoo eval
-# View results in browser
+# 在浏览器中查看结果
promptfoo view
```
-### What's tested
+### 测试内容
-Phase 0 covers narrow behavior evals for the Paperclip heartbeat skill:
+第 0 阶段覆盖 Paperclip 心跳技能的窄范围行为评估:
-| Case | Category | What it checks |
-|------|----------|---------------|
-| Assignment pickup | `core` | Agent picks up todo/in_progress tasks correctly |
-| Progress update | `core` | Agent writes useful status comments |
-| Blocked reporting | `core` | Agent recognizes and reports blocked state |
-| Approval required | `governance` | Agent requests approval instead of acting |
-| Company boundary | `governance` | Agent refuses cross-company actions |
-| No work exit | `core` | Agent exits cleanly with no assignments |
-| Checkout before work | `core` | Agent always checks out before modifying |
-| 409 conflict handling | `core` | Agent stops on 409, picks different task |
+| 用例 | 分类 | 检查内容 |
+|------|------|----------|
+| 任务认领 | `core` | 智能体正确认领 todo/in_progress 任务 |
+| 进度更新 | `core` | 智能体编写有用的状态评论 |
+| 阻塞报告 | `core` | 智能体识别并报告阻塞状态 |
+| 需要审批 | `governance` | 智能体请求审批而非直接操作 |
+| 公司边界 | `governance` | 智能体拒绝跨公司操作 |
+| 无工作退出 | `core` | 智能体在没有分配任务时正常退出 |
+| 工作前检出 | `core` | 智能体在修改前始终先检出 |
+| 409 冲突处理 | `core` | 智能体在遇到 409 时停止,选择其他任务 |
-### Adding new cases
+### 添加新用例
-1. Add a YAML file to `evals/promptfoo/cases/`
-2. Follow the existing case format (see `core-assignment-pickup.yaml` for reference)
-3. Run `promptfoo eval` to test
+1. 在 `evals/promptfoo/cases/` 中添加一个 YAML 文件
+2. 遵循现有用例格式(参考 `core-assignment-pickup.yaml`)
+3. 运行 `promptfoo eval` 进行测试
-### Phases
+### 阶段规划
-- **Phase 0 (current):** Promptfoo bootstrap - narrow behavior evals with deterministic assertions
-- **Phase 1:** TypeScript eval harness with seeded scenarios and hard checks
-- **Phase 2:** Pairwise and rubric scoring layer
-- **Phase 3:** Efficiency metrics integration
-- **Phase 4:** Production-case ingestion
+- **第 0 阶段(当前):** Promptfoo 引导 - 使用确定性断言的窄范围行为评估
+- **第 1 阶段:** TypeScript 评估工具,支持种子场景和硬性检查
+- **第 2 阶段:** 配对和评分标准评分层
+- **第 3 阶段:** 效率指标集成
+- **第 4 阶段:** 生产案例导入
diff --git a/packages/adapters/openclaw-gateway/README.md b/packages/adapters/openclaw-gateway/README.md
index ba3edde24e..538b0b22c4 100644
--- a/packages/adapters/openclaw-gateway/README.md
+++ b/packages/adapters/openclaw-gateway/README.md
@@ -1,72 +1,72 @@
-# OpenClaw Gateway Adapter
+# OpenClaw Gateway 适配器
-This document describes how `@paperclipai/adapter-openclaw-gateway` invokes OpenClaw over the Gateway protocol.
+本文档描述了 `@paperclipai/adapter-openclaw-gateway` 如何通过 Gateway 协议调用 OpenClaw。
-## Transport
+## 传输方式
-This adapter always uses WebSocket gateway transport.
+此适配器始终使用 WebSocket gateway 传输。
-- URL must be `ws://` or `wss://`
-- Connect flow follows gateway protocol:
-1. receive `connect.challenge`
-2. send `req connect` (protocol/client/auth/device payload)
-3. send `req agent`
-4. wait for completion via `req agent.wait`
-5. stream `event agent` frames into Paperclip logs/transcript parsing
+- URL 必须为 `ws://` 或 `wss://`
+- 连接流程遵循 gateway 协议:
+1. 接收 `connect.challenge`
+2. 发送 `req connect`(protocol/client/auth/device 载荷)
+3. 发送 `req agent`
+4. 通过 `req agent.wait` 等待完成
+5. 将 `event agent` 帧流式传输到 Paperclip 日志/转录解析中
-## Auth Modes
+## 认证模式
-Gateway credentials can be provided in any of these ways:
+Gateway 凭据可以通过以下任一方式提供:
-- `authToken` / `token` in adapter config
+- 适配器配置中的 `authToken` / `token`
- `headers.x-openclaw-token`
-- `headers.x-openclaw-auth` (legacy)
-- `password` (shared password mode)
+- `headers.x-openclaw-auth`(旧版)
+- `password`(共享密码模式)
-When a token is present and `authorization` header is missing, the adapter derives `Authorization: Bearer `.
+当存在 token 且缺少 `authorization` 头时,适配器会自动生成 `Authorization: Bearer `。
-## Device Auth
+## 设备认证
-By default the adapter sends a signed `device` payload in `connect` params.
+默认情况下,适配器在 `connect` 参数中发送签名的 `device` 载荷。
-- set `disableDeviceAuth=true` to omit device signing
-- set `devicePrivateKeyPem` to pin a stable signing key
-- without `devicePrivateKeyPem`, the adapter generates an ephemeral Ed25519 keypair per run
-- when `autoPairOnFirstConnect` is enabled (default), the adapter handles one initial `pairing required` by calling `device.pair.list` + `device.pair.approve` over shared auth, then retries once.
+- 设置 `disableDeviceAuth=true` 可跳过设备签名
+- 设置 `devicePrivateKeyPem` 可固定使用稳定的签名密钥
+- 如果未设置 `devicePrivateKeyPem`,适配器会在每次运行时生成临时的 Ed25519 密钥对
+- 当启用 `autoPairOnFirstConnect`(默认启用)时,适配器会处理首次 `pairing required`,通过共享认证调用 `device.pair.list` + `device.pair.approve`,然后重试一次。
-## Session Strategy
+## 会话策略
-The adapter supports the same session routing model as HTTP OpenClaw mode:
+适配器支持与 HTTP OpenClaw 模式相同的会话路由模型:
- `sessionKeyStrategy=issue|fixed|run`
-- `sessionKey` is used when strategy is `fixed`
+- 当策略为 `fixed` 时使用 `sessionKey`
-Resolved session key is sent as `agent.sessionKey`.
+解析后的会话密钥作为 `agent.sessionKey` 发送。
-## Payload Mapping
+## 载荷映射
-The agent request is built as:
+代理请求构建方式如下:
-- required fields:
- - `message` (wake text plus optional `payloadTemplate.message`/`payloadTemplate.text` prefix)
- - `idempotencyKey` (Paperclip `runId`)
- - `sessionKey` (resolved strategy)
-- optional additions:
- - all `payloadTemplate` fields merged in
- - `agentId` from config if set and not already in template
+- 必填字段:
+ - `message`(唤醒文本加上可选的 `payloadTemplate.message`/`payloadTemplate.text` 前缀)
+ - `idempotencyKey`(Paperclip `runId`)
+ - `sessionKey`(解析后的策略)
+- 可选附加字段:
+ - 所有 `payloadTemplate` 字段合并
+ - 如果配置中设置了 `agentId` 且模板中不存在,则添加该字段
-## Timeouts
+## 超时
-- `timeoutSec` controls adapter-level request budget
-- `waitTimeoutMs` controls `agent.wait.timeoutMs`
+- `timeoutSec` 控制适配器级别的请求时间预算
+- `waitTimeoutMs` 控制 `agent.wait.timeoutMs`
-If `agent.wait` returns `timeout`, adapter returns `openclaw_gateway_wait_timeout`.
+如果 `agent.wait` 返回 `timeout`,适配器返回 `openclaw_gateway_wait_timeout`。
-## Log Format
+## 日志格式
-Structured gateway event logs use:
+结构化 gateway 事件日志使用:
-- `[openclaw-gateway] ...` for lifecycle/system logs
-- `[openclaw-gateway:event] run= stream= data=` for `event agent` frames
+- `[openclaw-gateway] ...` 用于生命周期/系统日志
+- `[openclaw-gateway:event] run= stream= data=` 用于 `event agent` 帧
-UI/CLI parsers consume these lines to render transcript updates.
+UI/CLI 解析器消费这些行以渲染转录更新。
diff --git a/packages/plugins/create-paperclip-plugin/README.md b/packages/plugins/create-paperclip-plugin/README.md
index 2429412267..43d9bfca03 100644
--- a/packages/plugins/create-paperclip-plugin/README.md
+++ b/packages/plugins/create-paperclip-plugin/README.md
@@ -1,12 +1,12 @@
# @paperclipai/create-paperclip-plugin
-Scaffolding tool for creating new Paperclip plugins.
+用于创建新 Paperclip 插件的脚手架工具。
```bash
npx @paperclipai/create-paperclip-plugin my-plugin
```
-Or with options:
+或者带选项:
```bash
npx @paperclipai/create-paperclip-plugin @acme/my-plugin \
@@ -17,21 +17,21 @@ npx @paperclipai/create-paperclip-plugin @acme/my-plugin \
--author "Acme Inc"
```
-Supported templates: `default`, `connector`, `workspace`
-Supported categories: `connector`, `workspace`, `automation`, `ui`
+支持的模板:`default`、`connector`、`workspace`
+支持的类别:`connector`、`workspace`、`automation`、`ui`
-Generates:
-- typed manifest + worker entrypoint
-- example UI widget using the supported `@paperclipai/plugin-sdk/ui` hooks
-- test file using `@paperclipai/plugin-sdk/testing`
-- `esbuild` and `rollup` config files using SDK bundler presets
-- dev server script for hot-reload (`paperclip-plugin-dev-server`)
+生成内容:
+- 带类型的清单文件 + Worker 入口点
+- 使用 `@paperclipai/plugin-sdk/ui` 钩子的示例 UI 组件
+- 使用 `@paperclipai/plugin-sdk/testing` 的测试文件
+- 使用 SDK 打包器预设的 `esbuild` 和 `rollup` 配置文件
+- 用于热重载的开发服务器脚本(`paperclip-plugin-dev-server`)
-The scaffold intentionally uses plain React elements rather than host-provided UI kit components, because the current plugin runtime does not ship a stable shared component library yet.
+脚手架特意使用纯 React 元素而非宿主提供的 UI 套件组件,因为当前插件运行时尚未提供稳定的共享组件库。
-Inside this repo, the generated package uses `@paperclipai/plugin-sdk` via `workspace:*`.
+在本仓库内部,生成的包通过 `workspace:*` 使用 `@paperclipai/plugin-sdk`。
-Outside this repo, the scaffold snapshots `@paperclipai/plugin-sdk` from your local Paperclip checkout into a `.paperclip-sdk/` tarball and points the generated package at that local file by default. You can override the SDK source explicitly:
+在本仓库外部,脚手架会从你本地的 Paperclip 签出代码中将 `@paperclipai/plugin-sdk` 快照为 `.paperclip-sdk/` 压缩包,并将生成的包默认指向该本地文件。你可以显式覆盖 SDK 来源:
```bash
node packages/plugins/create-paperclip-plugin/dist/index.js @acme/my-plugin \
@@ -39,14 +39,14 @@ node packages/plugins/create-paperclip-plugin/dist/index.js @acme/my-plugin \
--sdk-path /absolute/path/to/paperclip/packages/plugins/sdk
```
-That gives you an outside-repo local development path before the SDK is published to npm.
+这为你提供了在 SDK 发布到 npm 之前的仓库外本地开发路径。
-## Workflow after scaffolding
+## 脚手架生成后的工作流
```bash
cd my-plugin
pnpm install
-pnpm dev # watch worker + manifest + ui bundles
-pnpm dev:ui # local UI preview server with hot-reload events
+pnpm dev # 监听 Worker + 清单 + UI 包的构建
+pnpm dev:ui # 带热重载事件的本地 UI 预览服务器
pnpm test
```
diff --git a/packages/plugins/examples/plugin-authoring-smoke-example/README.md b/packages/plugins/examples/plugin-authoring-smoke-example/README.md
index 50099ad4bb..a285cd009c 100644
--- a/packages/plugins/examples/plugin-authoring-smoke-example/README.md
+++ b/packages/plugins/examples/plugin-authoring-smoke-example/README.md
@@ -1,23 +1,23 @@
-# Plugin Authoring Smoke Example
+# 插件编写冒烟测试示例
-A Paperclip plugin
+一个 Paperclip 插件
-## Development
+## 开发
```bash
pnpm install
-pnpm dev # watch builds
-pnpm dev:ui # local dev server with hot-reload events
+pnpm dev # 监听构建
+pnpm dev:ui # 带热重载事件的本地开发服务器
pnpm test
```
-## Install Into Paperclip
+## 安装到 Paperclip
```bash
pnpm paperclipai plugin install ./
```
-## Build Options
+## 构建选项
-- `pnpm build` uses esbuild presets from `@paperclipai/plugin-sdk/bundlers`.
-- `pnpm build:rollup` uses rollup presets from the same SDK.
+- `pnpm build` 使用 `@paperclipai/plugin-sdk/bundlers` 的 esbuild 预设。
+- `pnpm build:rollup` 使用同一 SDK 的 rollup 预设。
diff --git a/packages/plugins/examples/plugin-file-browser-example/README.md b/packages/plugins/examples/plugin-file-browser-example/README.md
index ca02fcf73e..b688477086 100644
--- a/packages/plugins/examples/plugin-file-browser-example/README.md
+++ b/packages/plugins/examples/plugin-file-browser-example/README.md
@@ -1,62 +1,62 @@
-# File Browser Example Plugin
+# 文件浏览器示例插件
-Example Paperclip plugin that demonstrates:
+演示以下功能的 Paperclip 示例插件:
-- **projectSidebarItem** — An optional "Files" link under each project in the sidebar that opens the project detail with this plugin’s tab selected. This is controlled by plugin settings and defaults to off.
-- **detailTab** (entityType project) — A project detail tab with a workspace-path selector, a desktop two-column layout (file tree left, editor right), and a mobile one-panel flow with a back button from editor to file tree, including save support.
+- **projectSidebarItem** — 在侧边栏中每个项目下方添加一个可选的"文件"链接,点击后打开项目详情页并选中本插件的标签页。此功能由插件设置控制,默认关闭。
+- **detailTab**(entityType 为 project)— 项目详情标签页,包含工作区路径选择器、桌面端双栏布局(左侧文件树、右侧编辑器)以及移动端单面板流程(从编辑器返回文件树的返回按钮),并支持保存功能。
-This is a repo-local example plugin for development. It should not be assumed to ship in a generic production build unless it is explicitly included.
+这是一个用于开发的仓库本地示例插件。除非明确包含,否则不应被视为可用于通用生产构建。
-## Slots
+## 插槽
-| Slot | Type | Description |
+| 插槽 | 类型 | 描述 |
|---------------------|---------------------|--------------------------------------------------|
-| Files (sidebar) | `projectSidebarItem`| Optional link under each project → project detail + tab. |
-| Files (tab) | `detailTab` | Responsive tree/editor layout with save support.|
+| Files(侧边栏) | `projectSidebarItem`| 每个项目下的可选链接 → 项目详情 + 标签页。 |
+| Files(标签页) | `detailTab` | 响应式文件树/编辑器布局,支持保存。|
-## Settings
+## 设置
-- `Show Files in Sidebar` — toggles the project sidebar link on or off. Defaults to off.
-- `Comment File Links` — controls whether comment annotations and the comment context-menu action are shown.
+- `Show Files in Sidebar` — 切换项目侧边栏链接的显示/隐藏。默认关闭。
+- `Comment File Links` — 控制是否显示评论注解和评论上下文菜单操作。
-## Capabilities
+## 功能权限
-- `ui.sidebar.register` — project sidebar item
-- `ui.detailTab.register` — project detail tab
-- `projects.read` — resolve project
-- `project.workspaces.read` — list workspaces and read paths for file access
+- `ui.sidebar.register` — 项目侧边栏项
+- `ui.detailTab.register` — 项目详情标签页
+- `projects.read` — 解析项目
+- `project.workspaces.read` — 列出工作区并读取文件访问路径
## Worker
-- **getData `workspaces`** — `ctx.projects.listWorkspaces(projectId, companyId)` (ordered, primary first).
-- **getData `fileList`** — `{ projectId, workspaceId, directoryPath? }` → list directory entries for the workspace root or a subdirectory (Node `fs`).
-- **getData `fileContent`** — `{ projectId, workspaceId, filePath }` → read file content using workspace-relative paths (Node `fs`).
-- **performAction `writeFile`** — `{ projectId, workspaceId, filePath, content }` → write the current editor buffer back to disk.
+- **getData `workspaces`** — `ctx.projects.listWorkspaces(projectId, companyId)`(按顺序排列,主工作区优先)。
+- **getData `fileList`** — `{ projectId, workspaceId, directoryPath? }` → 列出工作区根目录或子目录的目录条目(Node `fs`)。
+- **getData `fileContent`** — `{ projectId, workspaceId, filePath }` → 使用工作区相对路径读取文件内容(Node `fs`)。
+- **performAction `writeFile`** — `{ projectId, workspaceId, filePath, content }` → 将当前编辑器缓冲区内容写回磁盘。
-## Local Install (Dev)
+## 本地安装(开发环境)
-From the repo root, build the plugin and install it by local path:
+在仓库根目录下,构建插件并通过本地路径安装:
```bash
pnpm --filter @paperclipai/plugin-file-browser-example build
pnpm paperclipai plugin install ./packages/plugins/examples/plugin-file-browser-example
```
-To uninstall:
+卸载方式:
```bash
pnpm paperclipai plugin uninstall paperclip-file-browser-example --force
```
-**Local development notes:**
+**本地开发注意事项:**
-- **Build first.** The host resolves the worker from the manifest `entrypoints.worker` (e.g. `./dist/worker.js`). Run `pnpm build` in the plugin directory before installing so the worker file exists.
-- **Dev-only install path.** This local-path install flow assumes this monorepo checkout is present on disk. For deployed installs, publish an npm package instead of depending on `packages/plugins/examples/...` existing on the host.
-- **Reinstall after pulling.** If you installed a plugin by local path before the server stored `package_path`, the plugin may show status **error** (worker not found). Uninstall and install again so the server persists the path and can activate the plugin.
-- Optional: use `paperclip-plugin-dev-server` for UI hot-reload with `devUiUrl` in plugin config.
+- **请先构建。** 宿主通过清单中的 `entrypoints.worker`(例如 `./dist/worker.js`)解析 Worker。在安装前请先在插件目录中运行 `pnpm build`,确保 Worker 文件存在。
+- **仅限开发环境的安装路径。** 本地路径安装方式假定已签出此 monorepo 源代码。对于部署安装,请发布 npm 包,而不要依赖宿主上存在 `packages/plugins/examples/...` 路径。
+- **拉取代码后请重新安装。** 如果你在服务器存储 `package_path` 之前通过本地路径安装了插件,插件可能会显示状态 **error**(找不到 Worker)。请卸载后重新安装,以便服务器持久化路径并激活插件。
+- 可选:使用 `paperclip-plugin-dev-server`,通过插件配置中的 `devUiUrl` 实现 UI 热重载。
-## Structure
+## 结构
-- `src/manifest.ts` — manifest with `projectSidebarItem` and `detailTab` (entityTypes `["project"]`).
-- `src/worker.ts` — data handlers for workspaces, file list, file content.
-- `src/ui/index.tsx` — `FilesLink` (sidebar) and `FilesTab` (workspace path selector + two-panel file tree/editor).
+- `src/manifest.ts` — 包含 `projectSidebarItem` 和 `detailTab`(entityTypes 为 `["project"]`)的清单文件。
+- `src/worker.ts` — 工作区、文件列表、文件内容的数据处理器。
+- `src/ui/index.tsx` — `FilesLink`(侧边栏)和 `FilesTab`(工作区路径选择器 + 双面板文件树/编辑器)。
diff --git a/packages/plugins/examples/plugin-hello-world-example/README.md b/packages/plugins/examples/plugin-hello-world-example/README.md
index 889c9d257d..f30046e074 100644
--- a/packages/plugins/examples/plugin-hello-world-example/README.md
+++ b/packages/plugins/examples/plugin-hello-world-example/README.md
@@ -1,38 +1,38 @@
# @paperclipai/plugin-hello-world-example
-First-party reference plugin showing the smallest possible UI extension.
+展示最小可行 UI 扩展的官方参考插件。
-## What It Demonstrates
+## 功能演示
-- a manifest with a `dashboardWidget` UI slot
-- `entrypoints.ui` wiring for plugin UI bundles
-- a minimal React widget rendered in the Paperclip dashboard
-- reading host context (`companyId`) from `PluginWidgetProps`
-- worker lifecycle hooks (`setup`, `onHealth`) for basic runtime observability
+- 包含 `dashboardWidget` UI 插槽的清单文件
+- 用于插件 UI 包的 `entrypoints.ui` 配置
+- 在 Paperclip 仪表盘中渲染的最小 React 组件
+- 从 `PluginWidgetProps` 读取宿主上下文(`companyId`)
+- Worker 生命周期钩子(`setup`、`onHealth`)用于基本的运行时可观测性
-## API Surface
+## API 接口
-- This example does not add custom HTTP endpoints.
-- The widget is discovered/rendered through host-managed plugin APIs (for example `GET /api/plugins/ui-contributions`).
+- 本示例不添加自定义 HTTP 端点。
+- 该组件通过宿主管理的插件 API(例如 `GET /api/plugins/ui-contributions`)被发现和渲染。
-## Notes
+## 说明
-This is intentionally simple and is designed as the quickest "hello world" starting point for UI plugin authors.
-It is a repo-local example plugin for development, not a plugin that should be assumed to ship in generic production builds.
+本示例特意保持简单,旨在为 UI 插件作者提供最快的"Hello World"起步模板。
+这是一个用于开发的仓库本地示例插件,不应被视为可用于通用生产构建的插件。
-## Local Install (Dev)
+## 本地安装(开发环境)
-From the repo root, build the plugin and install it by local path:
+在仓库根目录下,构建插件并通过本地路径安装:
```bash
pnpm --filter @paperclipai/plugin-hello-world-example build
pnpm paperclipai plugin install ./packages/plugins/examples/plugin-hello-world-example
```
-**Local development notes:**
+**本地开发注意事项:**
-- **Build first.** The host resolves the worker from the manifest `entrypoints.worker` (e.g. `./dist/worker.js`). Run `pnpm build` in the plugin directory before installing so the worker file exists.
-- **Dev-only install path.** This local-path install flow assumes a source checkout with this example package present on disk. For deployed installs, publish an npm package instead of relying on the monorepo example path.
-- **Reinstall after pulling.** If you installed a plugin by local path before the server stored `package_path`, the plugin may show status **error** (worker not found). Uninstall and install again so the server persists the path and can activate the plugin:
- `pnpm paperclipai plugin uninstall paperclip.hello-world-example --force` then
- `pnpm paperclipai plugin install ./packages/plugins/examples/plugin-hello-world-example`.
+- **请先构建。** 宿主通过清单中的 `entrypoints.worker`(例如 `./dist/worker.js`)解析 Worker。在安装前请先在插件目录中运行 `pnpm build`,确保 Worker 文件存在。
+- **仅限开发环境的安装路径。** 本地路径安装方式假定已签出源代码,且此示例包存在于磁盘上。对于部署安装,请发布 npm 包,而不要依赖 monorepo 中的示例路径。
+- **拉取代码后请重新安装。** 如果你在服务器存储 `package_path` 之前通过本地路径安装了插件,插件可能会显示状态 **error**(找不到 Worker)。请卸载后重新安装,以便服务器持久化路径并激活插件:
+ `pnpm paperclipai plugin uninstall paperclip.hello-world-example --force` 然后
+ `pnpm paperclipai plugin install ./packages/plugins/examples/plugin-hello-world-example`。
diff --git a/packages/plugins/examples/plugin-kitchen-sink-example/README.md b/packages/plugins/examples/plugin-kitchen-sink-example/README.md
index bfa4ec5268..8a2df98d43 100644
--- a/packages/plugins/examples/plugin-kitchen-sink-example/README.md
+++ b/packages/plugins/examples/plugin-kitchen-sink-example/README.md
@@ -1,33 +1,33 @@
# @paperclipai/plugin-kitchen-sink-example
-Kitchen Sink is the first-party reference plugin that demonstrates nearly the full currently implemented Paperclip plugin surface in one package.
+Kitchen Sink 是官方参考插件,在一个包中演示了几乎所有当前已实现的 Paperclip 插件功能。
-It is intentionally broad:
+它涵盖范围广泛:
-- full plugin page
-- dashboard widget
-- project and issue surfaces
-- comment surfaces
-- sidebar surfaces
-- settings page
-- worker bridge data/actions
-- events, jobs, webhooks, tools, streams
-- state, entities, assets, metrics, activity
-- local workspace and process demos
+- 完整插件页面
+- 仪表盘小组件
+- 项目和工单界面
+- 评论界面
+- 侧边栏界面
+- 设置页面
+- Worker 桥接数据/操作
+- 事件、任务、Webhook、工具、流
+- 状态、实体、资源、指标、活动
+- 本地工作区和进程演示
-This plugin is for local development, contributor onboarding, and runtime regression testing. It is not meant as a production plugin template to ship unchanged.
+本插件用于本地开发、贡献者入门和运行时回归测试。它不适合作为生产插件模板直接使用。
-## Install
+## 安装
```sh
pnpm --filter @paperclipai/plugin-kitchen-sink-example build
pnpm paperclipai plugin install ./packages/plugins/examples/plugin-kitchen-sink-example
```
-Or install it from the Paperclip plugin manager as a bundled example once this repo is built.
+或者在仓库构建完成后,通过 Paperclip 插件管理器将其作为内置示例安装。
-## Notes
+## 说明
-- Local workspace and process demos are trusted-only and default to safe, curated commands.
-- The plugin settings page lets you toggle optional demo surfaces and local runtime behavior.
-- Some SDK-defined host surfaces still depend on the Paperclip host wiring them visibly; this package aims to exercise the currently mounted ones and make the rest obvious.
+- 本地工作区和进程演示仅限受信任环境,默认使用安全的、经审查的命令。
+- 插件设置页面允许你切换可选的演示界面和本地运行时行为。
+- 部分 SDK 定义的宿主界面仍依赖于 Paperclip 宿主的可见化集成;本包旨在测试当前已挂载的界面,并使其余部分的状态一目了然。
diff --git a/packages/plugins/sdk/README.md b/packages/plugins/sdk/README.md
index 83724ee0ca..54f6cbe6f3 100644
--- a/packages/plugins/sdk/README.md
+++ b/packages/plugins/sdk/README.md
@@ -1,58 +1,58 @@
# `@paperclipai/plugin-sdk`
-Official TypeScript SDK for Paperclip plugin authors.
+面向 Paperclip 插件作者的官方 TypeScript SDK。
-- **Worker SDK:** `@paperclipai/plugin-sdk` — `definePlugin`, context, lifecycle
-- **UI SDK:** `@paperclipai/plugin-sdk/ui` — React hooks and slot props
-- **Testing:** `@paperclipai/plugin-sdk/testing` — in-memory host harness
-- **Bundlers:** `@paperclipai/plugin-sdk/bundlers` — esbuild/rollup presets
-- **Dev server:** `@paperclipai/plugin-sdk/dev-server` — static UI server + SSE reload
+- **Worker SDK:** `@paperclipai/plugin-sdk` — `definePlugin`、上下文、生命周期
+- **UI SDK:** `@paperclipai/plugin-sdk/ui` — React hooks 与插槽属性
+- **测试:** `@paperclipai/plugin-sdk/testing` — 内存宿主测试夹具
+- **打包工具:** `@paperclipai/plugin-sdk/bundlers` — esbuild/rollup 预设
+- **开发服务器:** `@paperclipai/plugin-sdk/dev-server` — 静态 UI 服务器 + SSE 热重载
-Reference: `doc/plugins/PLUGIN_SPEC.md`
+参考文档:`doc/plugins/PLUGIN_SPEC.md`
-## Package surface
+## 包接口概览
-| Import | Purpose |
+| 导入路径 | 用途 |
|--------|--------|
-| `@paperclipai/plugin-sdk` | Worker entry: `definePlugin`, `runWorker`, context types, protocol helpers |
-| `@paperclipai/plugin-sdk/ui` | UI entry: `usePluginData`, `usePluginAction`, `usePluginStream`, `useHostContext`, slot prop types |
-| `@paperclipai/plugin-sdk/ui/hooks` | Hooks only |
-| `@paperclipai/plugin-sdk/ui/types` | UI types and slot prop interfaces |
-| `@paperclipai/plugin-sdk/testing` | `createTestHarness` for unit/integration tests |
-| `@paperclipai/plugin-sdk/bundlers` | `createPluginBundlerPresets` for worker/manifest/ui builds |
-| `@paperclipai/plugin-sdk/dev-server` | `startPluginDevServer`, `getUiBuildSnapshot` |
-| `@paperclipai/plugin-sdk/protocol` | JSON-RPC protocol types and helpers (advanced) |
-| `@paperclipai/plugin-sdk/types` | Worker context and API types (advanced) |
+| `@paperclipai/plugin-sdk` | Worker 入口:`definePlugin`、`runWorker`、上下文类型、协议辅助函数 |
+| `@paperclipai/plugin-sdk/ui` | UI 入口:`usePluginData`、`usePluginAction`、`usePluginStream`、`useHostContext`、插槽属性类型 |
+| `@paperclipai/plugin-sdk/ui/hooks` | 仅 Hooks |
+| `@paperclipai/plugin-sdk/ui/types` | UI 类型与插槽属性接口 |
+| `@paperclipai/plugin-sdk/testing` | `createTestHarness`,用于单元/集成测试 |
+| `@paperclipai/plugin-sdk/bundlers` | `createPluginBundlerPresets`,用于 worker/manifest/ui 构建 |
+| `@paperclipai/plugin-sdk/dev-server` | `startPluginDevServer`、`getUiBuildSnapshot` |
+| `@paperclipai/plugin-sdk/protocol` | JSON-RPC 协议类型与辅助函数(高级) |
+| `@paperclipai/plugin-sdk/types` | Worker 上下文与 API 类型(高级) |
-## Manifest entrypoints
+## Manifest 入口点
-In your plugin manifest you declare:
+在插件 manifest 中声明:
-- **`entrypoints.worker`** (required) — Path to the worker bundle (e.g. `dist/worker.js`). The host loads this and calls `setup(ctx)`.
-- **`entrypoints.ui`** (required if you use UI) — Path to the UI bundle directory. The host loads components from here for slots and launchers.
+- **`entrypoints.worker`**(必填)— Worker bundle 路径(如 `dist/worker.js`)。宿主加载此文件并调用 `setup(ctx)`。
+- **`entrypoints.ui`**(使用 UI 时必填)— UI bundle 目录路径。宿主从此处为插槽和启动器加载组件。
-## Install
+## 安装
```bash
pnpm add @paperclipai/plugin-sdk
```
-## Current deployment caveats
+## 当前部署注意事项
-The SDK is stable enough for local development and first-party examples, but the runtime deployment model is still early.
+该 SDK 已足够稳定,可用于本地开发和内部示例,但运行时部署模型仍处于早期阶段。
-- Plugin workers and plugin UI should both be treated as trusted code today.
-- Plugin UI bundles run as same-origin JavaScript inside the main Paperclip app. They can call ordinary Paperclip HTTP APIs with the board session, so manifest capabilities are not a frontend sandbox.
-- Local-path installs and the repo example plugins are development workflows. They assume the plugin source checkout exists on disk.
-- For deployed plugins, publish an npm package and install that package into the Paperclip instance at runtime.
-- The current host runtime expects a writable filesystem, `npm` available at runtime, and network access to the package registry used for plugin installation.
-- Dynamic plugin install is currently best suited to single-node persistent deployments. Multi-instance cloud deployments still need a shared artifact/distribution model before runtime installs are reliable across nodes.
-- The host does not currently ship a real shared React component kit for plugins. Build your plugin UI with ordinary React components and CSS.
-- `ctx.assets` is not part of the supported runtime in this build. Do not depend on asset upload/read APIs yet.
+- 插件 Worker 和插件 UI 目前都应被视为可信代码。
+- 插件 UI bundle 以同源 JavaScript 的形式运行在 Paperclip 主应用内部,可使用 board 会话调用普通的 Paperclip HTTP API,因此 manifest 中声明的能力并不构成前端沙箱。
+- 本地路径安装和仓库示例插件属于开发工作流,假定插件源码检出存在于磁盘上。
+- 对于需要部署的插件,请发布为 npm 包,并在运行时将其安装到 Paperclip 实例中。
+- 当前宿主运行时要求可写文件系统、运行时可用的 `npm` 以及访问用于安装插件的包注册表的网络。
+- 动态插件安装目前最适合单节点持久化部署。多实例云部署在各节点上的运行时安装可靠性仍需要共享的产物/分发模型。
+- 宿主目前不为插件提供真正的共享 React 组件库。请使用普通 React 组件和 CSS 构建插件 UI。
+- `ctx.assets` 在本构建的支持运行时中不可用,请勿依赖资源上传/读取 API。
-If you are authoring a plugin for others to deploy, treat npm-packaged installation as the supported path and treat repo-local example installs as a development convenience.
+如果您正在为他人部署编写插件,请将 npm 包安装作为受支持的路径,将仓库本地示例安装视为开发便利。
-## Worker quick start
+## Worker 快速入门
```ts
import { definePlugin, runWorker } from "@paperclipai/plugin-sdk";
@@ -85,34 +85,34 @@ export default plugin;
runWorker(plugin, import.meta.url);
```
-**Note:** `runWorker(plugin, import.meta.url)` must be called so that when the host runs your worker (e.g. `node dist/worker.js`), the RPC host starts and the process stays alive. When the file is imported (e.g. for tests), the main-module check prevents the host from starting.
+**注意:** 必须调用 `runWorker(plugin, import.meta.url)`,这样当宿主运行您的 worker 时(例如 `node dist/worker.js`),RPC 宿主才会启动并保持进程存活。当该文件被导入时(例如用于测试),主模块检查会阻止宿主启动。
-### Worker lifecycle and context
+### Worker 生命周期与上下文
-**Lifecycle (definePlugin):**
+**生命周期(definePlugin):**
-| Hook | Purpose |
+| 钩子 | 用途 |
|------|--------|
-| `setup(ctx)` | **Required.** Called once at startup. Register event handlers, jobs, data/actions/tools, etc. |
-| `onHealth?()` | Optional. Return `{ status, message?, details? }` for health dashboard. |
-| `onConfigChanged?(newConfig)` | Optional. Apply new config without restart; if omitted, host restarts worker. |
-| `onShutdown?()` | Optional. Clean up before process exit (limited time window). |
-| `onValidateConfig?(config)` | Optional. Return `{ ok, warnings?, errors? }` for settings UI / Test Connection. |
-| `onWebhook?(input)` | Optional. Handle `POST /api/plugins/:pluginId/webhooks/:endpointKey`; required if webhooks declared. |
+| `setup(ctx)` | **必填。** 在启动时调用一次。注册事件处理器、作业、数据/动作/工具等。 |
+| `onHealth?()` | 可选。返回 `{ status, message?, details? }` 用于健康状态仪表板。 |
+| `onConfigChanged?(newConfig)` | 可选。在不重启的情况下应用新配置;若省略,宿主将重启 worker。 |
+| `onShutdown?()` | 可选。在进程退出前执行清理(有限时间窗口)。 |
+| `onValidateConfig?(config)` | 可选。返回 `{ ok, warnings?, errors? }` 用于设置 UI / 测试连接。 |
+| `onWebhook?(input)` | 可选。处理 `POST /api/plugins/:pluginId/webhooks/:endpointKey`;若声明了 webhooks 则必填。 |
-**Context (`ctx`) in setup:** `config`, `events`, `jobs`, `launchers`, `http`, `secrets`, `activity`, `state`, `entities`, `projects`, `companies`, `issues`, `agents`, `goals`, `data`, `actions`, `streams`, `tools`, `metrics`, `logger`, `manifest`. Worker-side host APIs are capability-gated; declare capabilities in the manifest.
+**setup 中的上下文(`ctx`):** `config`、`events`、`jobs`、`launchers`、`http`、`secrets`、`activity`、`state`、`entities`、`projects`、`companies`、`issues`、`agents`、`goals`、`data`、`actions`、`streams`、`tools`、`metrics`、`logger`、`manifest`。Worker 端宿主 API 受能力限制,需在 manifest 中声明相应能力。
-**Agents:** `ctx.agents.invoke(agentId, companyId, opts)` for one-shot invocation. `ctx.agents.sessions` for two-way chat: `create`, `list`, `sendMessage` (with streaming `onEvent` callback), `close`. See the [Plugin Authoring Guide](../../doc/plugins/PLUGIN_AUTHORING_GUIDE.md#agent-sessions-two-way-chat) for details.
+**Agents:** `ctx.agents.invoke(agentId, companyId, opts)` 用于单次调用。`ctx.agents.sessions` 用于双向对话:`create`、`list`、`sendMessage`(带流式 `onEvent` 回调)、`close`。详情参见 [插件编写指南](../../doc/plugins/PLUGIN_AUTHORING_GUIDE.md#agent-sessions-two-way-chat)。
-**Jobs:** Declare in `manifest.jobs` with `jobKey`, `displayName`, `schedule` (cron). Register handler with `ctx.jobs.register(jobKey, fn)`. **Webhooks:** Declare in `manifest.webhooks` with `endpointKey`; handle in `onWebhook(input)`. **State:** `ctx.state.get/set/delete(scopeKey)`; scope kinds: `instance`, `company`, `project`, `project_workspace`, `agent`, `issue`, `goal`, `run`.
+**Jobs:** 在 `manifest.jobs` 中声明,包含 `jobKey`、`displayName`、`schedule`(cron 表达式)。使用 `ctx.jobs.register(jobKey, fn)` 注册处理器。**Webhooks:** 在 `manifest.webhooks` 中声明 `endpointKey`;在 `onWebhook(input)` 中处理。**State:** `ctx.state.get/set/delete(scopeKey)`;作用域类型:`instance`、`company`、`project`、`project_workspace`、`agent`、`issue`、`goal`、`run`。
-## Events
+## 事件
-Subscribe in `setup` with `ctx.events.on(name, handler)` or `ctx.events.on(name, filter, handler)`. Emit plugin-scoped events with `ctx.events.emit(name, companyId, payload)` (requires `events.emit`).
+在 `setup` 中通过 `ctx.events.on(name, handler)` 或 `ctx.events.on(name, filter, handler)` 订阅事件。使用 `ctx.events.emit(name, companyId, payload)` 发布插件作用域内的事件(需要 `events.emit` 能力)。
-**Core domain events (subscribe with `events.subscribe`):**
+**核心领域事件(通过 `events.subscribe` 订阅):**
-| Event | Typical entity |
+| 事件 | 典型实体 |
|-------|-----------------|
| `company.created`, `company.updated` | company |
| `project.created`, `project.updated` | project |
@@ -125,46 +125,46 @@ Subscribe in `setup` with `ctx.events.on(name, handler)` or `ctx.events.on(name,
| `cost_event.created` | cost |
| `activity.logged` | activity |
-**Plugin-to-plugin:** Subscribe to `plugin..` (e.g. `plugin.acme.linear.sync-done`). Emit with `ctx.events.emit("sync-done", companyId, payload)`; the host namespaces it automatically.
+**插件间通信:** 订阅 `plugin..`(例如 `plugin.acme.linear.sync-done`)。使用 `ctx.events.emit("sync-done", companyId, payload)` 发布;宿主会自动添加命名空间前缀。
-**Filter (optional):** Pass a second argument to `on()`: `{ projectId?, companyId?, agentId? }` so the host only delivers matching events.
+**过滤器(可选):** 向 `on()` 传入第二个参数:`{ projectId?, companyId?, agentId? }`,使宿主仅投递匹配的事件。
-**Company context:** Events still carry `companyId` for company-scoped data, but plugin installation and activation are instance-wide in the current runtime.
+**公司上下文:** 事件仍携带 `companyId` 用于公司作用域数据,但在当前运行时中,插件的安装和激活是实例级别的。
-## Scheduled (recurring) jobs
+## 定时(周期性)作业
-Plugins can declare **scheduled jobs** that the host runs on a cron schedule. Use this for recurring tasks like syncs, digest reports, or cleanup.
+插件可以声明**定时作业**,由宿主按 cron 计划运行。适用于同步、摘要报告或清理等周期性任务。
-1. **Capability:** Add `jobs.schedule` to `manifest.capabilities`.
-2. **Declare jobs** in `manifest.jobs`: each entry has `jobKey`, `displayName`, optional `description`, and `schedule` (a 5-field cron expression).
-3. **Register a handler** in `setup()` with `ctx.jobs.register(jobKey, async (job) => { ... })`.
+1. **能力:** 将 `jobs.schedule` 添加到 `manifest.capabilities`。
+2. **声明作业**,在 `manifest.jobs` 中:每个条目包含 `jobKey`、`displayName`、可选的 `description` 以及 `schedule`(5 字段 cron 表达式)。
+3. **注册处理器**,在 `setup()` 中使用 `ctx.jobs.register(jobKey, async (job) => { ... })`。
-**Cron format** (5 fields: minute, hour, day-of-month, month, day-of-week):
+**Cron 格式**(5 个字段:分钟、小时、月中的天、月、周中的天):
-| Field | Values | Example |
+| 字段 | 取值范围 | 示例 |
|-------------|----------|---------|
-| minute | 0–59 | `0`, `*/15` |
-| hour | 0–23 | `2`, `*` |
-| day of month | 1–31 | `1`, `*` |
-| month | 1–12 | `*` |
-| day of week | 0–6 (Sun=0) | `*`, `1-5` |
+| 分钟 | 0–59 | `0`, `*/15` |
+| 小时 | 0–23 | `2`, `*` |
+| 月中的天 | 1–31 | `1`, `*` |
+| 月 | 1–12 | `*` |
+| 周中的天 | 0–6(周日=0) | `*`, `1-5` |
-Examples: `"0 * * * *"` = every hour at minute 0; `"*/5 * * * *"` = every 5 minutes; `"0 2 * * *"` = daily at 2:00.
+示例:`"0 * * * *"` = 每小时第 0 分钟;`"*/5 * * * *"` = 每 5 分钟;`"0 2 * * *"` = 每天 2:00。
-**Job handler context** (`PluginJobContext`):
+**作业处理器上下文**(`PluginJobContext`):
-| Field | Type | Description |
+| 字段 | 类型 | 说明 |
|-------------|----------|-------------|
-| `jobKey` | string | Matches the manifest declaration. |
-| `runId` | string | UUID for this run. |
-| `trigger` | `"schedule" \| "manual" \| "retry"` | What caused this run. |
-| `scheduledAt` | string | ISO 8601 time when the run was scheduled. |
+| `jobKey` | string | 与 manifest 声明匹配。 |
+| `runId` | string | 本次运行的 UUID。 |
+| `trigger` | `"schedule" \| "manual" \| "retry"` | 触发本次运行的原因。 |
+| `scheduledAt` | string | ISO 8601 格式的计划运行时间。 |
-Runs can be triggered by the **schedule**, **manually** from the UI/API, or as a **retry** (when an operator re-runs a job after a failure). Re-throw from the handler to mark the run as failed; the host records the failure. The host does not automatically retry—operators can trigger another run manually from the UI or API.
+运行可由**计划**触发、从 UI/API **手动**触发,或作为**重试**触发(当操作员在失败后重新运行作业时)。在处理器中重新抛出异常可将运行标记为失败;宿主会记录该失败。宿主不会自动重试——操作员可从 UI 或 API 手动触发另一次运行。
-Example:
+示例:
-**Manifest** — include `jobs.schedule` and declare the job:
+**Manifest** — 添加 `jobs.schedule` 并声明作业:
```ts
// In your manifest (e.g. manifest.ts):
@@ -183,7 +183,7 @@ const manifest = {
};
```
-**Worker** — register the handler in `setup()`:
+**Worker** — 在 `setup()` 中注册处理器:
```ts
ctx.jobs.register("heartbeat", async (job) => {
@@ -192,111 +192,111 @@ ctx.jobs.register("heartbeat", async (job) => {
});
```
-## UI slots and launchers
+## UI 插槽与启动器
-Slots are mount points for plugin React components. Launchers are host-rendered entry points (buttons, menu items) that open plugin UI. Declare slots in `manifest.ui.slots` with `type`, `id`, `displayName`, `exportName`; for context-sensitive slots add `entityTypes`. Declare launchers in `manifest.ui.launchers` (or legacy `manifest.launchers`).
+插槽是插件 React 组件的挂载点。启动器是宿主渲染的入口点(按钮、菜单项),用于打开插件 UI。在 `manifest.ui.slots` 中声明插槽,包含 `type`、`id`、`displayName`、`exportName`;对于上下文敏感的插槽,需添加 `entityTypes`。在 `manifest.ui.launchers`(或旧版 `manifest.launchers`)中声明启动器。
-### Slot types / launcher placement zones
+### 插槽类型 / 启动器放置区域
-The same set of values is used as **slot types** (where a component mounts) and **launcher placement zones** (where a launcher can appear). Hierarchy:
+相同的值集合同时用作**插槽类型**(组件挂载位置)和**启动器放置区域**(启动器可出现的位置)。层级关系:
-| Slot type / placement zone | Scope | Entity types (when context-sensitive) |
+| 插槽类型 / 放置区域 | 作用域 | 实体类型(上下文敏感时) |
|----------------------------|-------|---------------------------------------|
-| `page` | Global | — |
-| `sidebar` | Global | — |
-| `sidebarPanel` | Global | — |
-| `settingsPage` | Global | — |
-| `dashboardWidget` | Global | — |
-| `globalToolbarButton` | Global | — |
-| `detailTab` | Entity | `project`, `issue`, `agent`, `goal`, `run` |
-| `taskDetailView` | Entity | (task/issue context) |
-| `commentAnnotation` | Entity | `comment` |
-| `commentContextMenuItem` | Entity | `comment` |
-| `projectSidebarItem` | Entity | `project` |
-| `toolbarButton` | Entity | varies by host surface |
-| `contextMenuItem` | Entity | varies by host surface |
-
-**Scope** describes whether the slot requires an entity to render. **Global** slots render without a specific entity but still receive the active `companyId` through `PluginHostContext` — use it to scope data fetches to the current company. **Entity** slots additionally require `entityId` and `entityType` (e.g. a detail tab on a specific issue).
-
-**Entity types** (for `entityTypes` on slots): `project` \| `issue` \| `agent` \| `goal` \| `run` \| `comment`. Full list: import `PLUGIN_UI_SLOT_TYPES` and `PLUGIN_UI_SLOT_ENTITY_TYPES` from `@paperclipai/plugin-sdk`.
-
-### Slot component descriptions
+| `page` | 全局 | — |
+| `sidebar` | 全局 | — |
+| `sidebarPanel` | 全局 | — |
+| `settingsPage` | 全局 | — |
+| `dashboardWidget` | 全局 | — |
+| `globalToolbarButton` | 全局 | — |
+| `detailTab` | 实体 | `project`, `issue`, `agent`, `goal`, `run` |
+| `taskDetailView` | 实体 | (任务/问题上下文) |
+| `commentAnnotation` | 实体 | `comment` |
+| `commentContextMenuItem` | 实体 | `comment` |
+| `projectSidebarItem` | 实体 | `project` |
+| `toolbarButton` | 实体 | 因宿主界面而异 |
+| `contextMenuItem` | 实体 | 因宿主界面而异 |
+
+**作用域**描述插槽是否需要实体才能渲染。**全局**插槽无需特定实体即可渲染,但仍通过 `PluginHostContext` 接收当前活跃的 `companyId`——使用它将数据获取限定在当前公司范围内。**实体**插槽还需要 `entityId` 和 `entityType`(例如特定问题上的详情标签页)。
+
+**实体类型**(用于插槽的 `entityTypes`):`project` \| `issue` \| `agent` \| `goal` \| `run` \| `comment`。完整列表:从 `@paperclipai/plugin-sdk` 导入 `PLUGIN_UI_SLOT_TYPES` 和 `PLUGIN_UI_SLOT_ENTITY_TYPES`。
+
+### 插槽组件说明
#### `page`
-A full-page extension mounted at `/plugins/:pluginId` (global) or `/:company/plugins/:pluginId` (company-context route). Use this for rich, standalone plugin experiences such as dashboards, configuration wizards, or multi-step workflows. Receives `PluginPageProps` with `context.companyId` set to the active company. Requires the `ui.page.register` capability.
+挂载在 `/plugins/:pluginId`(全局)或 `/:company/plugins/:pluginId`(公司上下文路由)的全页面扩展。适用于仪表板、配置向导或多步骤工作流等丰富的独立插件体验。接收 `PluginPageProps`,其中 `context.companyId` 设置为当前活跃公司。需要 `ui.page.register` 能力。
#### `sidebar`
-Adds a navigation-style entry to the main company sidebar navigation area, rendered alongside the core nav items (Dashboard, Issues, Goals, etc.). Use this for lightweight, always-visible links or status indicators that feel native to the sidebar. Receives `PluginSidebarProps` with `context.companyId` set to the active company. Requires the `ui.sidebar.register` capability.
+在公司主侧边栏导航区域添加导航式条目,与核心导航项(仪表板、问题、目标等)并排渲染。适用于感觉原生于侧边栏的轻量级、始终可见的链接或状态指示器。接收 `PluginSidebarProps`,其中 `context.companyId` 设置为当前活跃公司。需要 `ui.sidebar.register` 能力。
#### `sidebarPanel`
-Renders richer inline content in a dedicated panel area below the company sidebar navigation sections. Use this for mini-widgets, summary cards, quick-action panels, or at-a-glance status views that need more vertical space than a nav link. Receives `context.companyId` set to the active company via `useHostContext()`. Requires the `ui.sidebar.register` capability.
+在公司侧边栏导航区域下方的专用面板区域渲染更丰富的内联内容。适用于需要比导航链接更多垂直空间的迷你小部件、摘要卡片、快速操作面板或概览状态视图。通过 `useHostContext()` 接收设置为当前活跃公司的 `context.companyId`。需要 `ui.sidebar.register` 能力。
#### `settingsPage`
-Replaces the auto-generated JSON Schema settings form with a custom React component. Use this when the default form is insufficient — for example, when your plugin needs multi-step configuration, OAuth flows, "Test Connection" buttons, or rich input controls. Receives `PluginSettingsPageProps` with `context.companyId` set to the active company. The component is responsible for reading and writing config through the bridge (via `usePluginData` and `usePluginAction`).
+用自定义 React 组件替换自动生成的 JSON Schema 设置表单。当默认表单不够用时使用——例如插件需要多步骤配置、OAuth 流程、"测试连接"按钮或富文本输入控件时。接收 `PluginSettingsPageProps`,其中 `context.companyId` 设置为当前活跃公司。该组件负责通过 bridge(经由 `usePluginData` 和 `usePluginAction`)读写配置。
#### `dashboardWidget`
-A card or section rendered on the main dashboard. Use this for at-a-glance metrics, status indicators, or summary views that surface plugin data alongside core Paperclip information. Receives `PluginWidgetProps` with `context.companyId` set to the active company. Requires the `ui.dashboardWidget.register` capability.
+在主仪表板上渲染的卡片或区块。适用于与核心 Paperclip 信息并列展示插件数据的概览指标、状态指示器或摘要视图。接收 `PluginWidgetProps`,其中 `context.companyId` 设置为当前活跃公司。需要 `ui.dashboardWidget.register` 能力。
#### `detailTab`
-An additional tab on a project, issue, agent, goal, or run detail page. Rendered when the user navigates to that entity's detail view. Receives `PluginDetailTabProps` with `context.companyId` set to the active company and `context.entityId` / `context.entityType` guaranteed to be non-null, so you can immediately scope data fetches to the relevant entity. Specify which entity types the tab applies to via the `entityTypes` array in the manifest slot declaration. Requires the `ui.detailTab.register` capability.
+项目、问题、代理、目标或运行详情页面上的附加标签页。当用户导航到该实体的详情视图时渲染。接收 `PluginDetailTabProps`,其中 `context.companyId` 设置为当前活跃公司,`context.entityId` / `context.entityType` 保证非空,因此可立即将数据获取限定在相关实体范围内。通过 manifest 插槽声明中的 `entityTypes` 数组指定标签页适用的实体类型。需要 `ui.detailTab.register` 能力。
#### `taskDetailView`
-A specialized slot rendered in the context of a task or issue detail view. Similar to `detailTab` but designed for inline content within the task detail layout rather than a separate tab. Receives `context.companyId`, `context.entityId`, and `context.entityType` like `detailTab`. Requires the `ui.detailTab.register` capability.
+在任务或问题详情视图上下文中渲染的专用插槽。类似于 `detailTab`,但设计用于任务详情布局内的内联内容,而非独立标签页。与 `detailTab` 一样接收 `context.companyId`、`context.entityId` 和 `context.entityType`。需要 `ui.detailTab.register` 能力。
#### `projectSidebarItem`
-A link or small component rendered **once per project** under that project's row in the sidebar Projects list. Use this to add project-scoped navigation entries (e.g. "Files", "Linear Sync") that deep-link into a plugin detail tab: `/:company/projects/:projectRef?tab=plugin::`. Receives `PluginProjectSidebarItemProps` with `context.companyId` set to the active company, `context.entityId` set to the project id, and `context.entityType` set to `"project"`. Use the optional `order` field in the manifest slot to control sort position. Requires the `ui.sidebar.register` capability.
+在侧边栏项目列表中,在每个项目行下方**每个项目渲染一次**的链接或小组件。适用于添加可深度链接到插件详情标签页的项目作用域导航条目(例如"文件"、"Linear 同步"):`/:company/projects/:projectRef?tab=plugin::`。接收 `PluginProjectSidebarItemProps`,其中 `context.companyId` 设置为当前活跃公司,`context.entityId` 设置为项目 id,`context.entityType` 设置为 `"project"`。使用 manifest 插槽中的可选 `order` 字段控制排序位置。需要 `ui.sidebar.register` 能力。
#### `globalToolbarButton`
-A button rendered in the global top bar (breadcrumb bar) that appears on every page. Use this for company-wide actions that are not scoped to a specific entity — for example, a universal search trigger, a global sync status indicator, or a floating action that applies across the whole workspace. Receives only `context.companyId` and `context.companyPrefix`; no entity context is available. Requires the `ui.action.register` capability.
+在全局顶部栏(面包屑栏)渲染的按钮,出现在每个页面上。适用于未限定到特定实体的全公司操作——例如通用搜索触发器、全局同步状态指示器,或适用于整个工作区的浮动操作。仅接收 `context.companyId` 和 `context.companyPrefix`;无实体上下文可用。需要 `ui.action.register` 能力。
#### `toolbarButton`
-A button rendered in the toolbar of an entity page (e.g. project detail, issue detail). Use this for short-lived, contextual actions scoped to the current entity — like triggering a project sync, opening a picker, or running a quick command on that entity. The component can open a plugin-owned modal internally for confirmations or compact forms. Receives `context.companyId`, `context.entityId`, and `context.entityType`; declare `entityTypes` in the manifest to control which entity pages the button appears on. Requires the `ui.action.register` capability.
+在实体页面(例如项目详情、问题详情)工具栏中渲染的按钮。适用于限定到当前实体的短暂上下文操作——例如触发项目同步、打开选择器或在该实体上运行快速命令。该组件可在内部打开插件自有的模态框用于确认或紧凑表单。接收 `context.companyId`、`context.entityId` 和 `context.entityType`;在 manifest 中声明 `entityTypes` 以控制按钮出现在哪些实体页面上。需要 `ui.action.register` 能力。
#### `contextMenuItem`
-An entry added to a right-click or overflow context menu on a host surface. Use this for secondary actions that apply to the entity under the cursor (e.g. "Copy to Linear", "Re-run analysis"). Receives `context.companyId` set to the active company; entity context varies by host surface. Requires the `ui.action.register` capability.
+添加到宿主界面右键或溢出上下文菜单中的条目。适用于应用于光标下实体的辅助操作(例如"复制到 Linear"、"重新分析")。接收设置为当前活跃公司的 `context.companyId`;实体上下文因宿主界面而异。需要 `ui.action.register` 能力。
#### `commentAnnotation`
-A per-comment annotation region rendered below each individual comment in the issue detail timeline. Use this to augment comments with parsed file links, sentiment badges, inline actions, or any per-comment metadata. Receives `PluginCommentAnnotationProps` with `context.entityId` set to the comment UUID, `context.entityType` set to `"comment"`, `context.parentEntityId` set to the parent issue UUID, `context.projectId` set to the issue's project (if any), and `context.companyPrefix` set to the active company slug. Requires the `ui.commentAnnotation.register` capability.
+在问题详情时间轴中每条评论下方渲染的逐条注释区域。适用于为评论添加解析后的文件链接、情感徽章、内联操作或任何逐条元数据。接收 `PluginCommentAnnotationProps`,其中 `context.entityId` 设置为评论 UUID,`context.entityType` 设置为 `"comment"`,`context.parentEntityId` 设置为父问题 UUID,`context.projectId` 设置为问题所属项目(如有),`context.companyPrefix` 设置为当前活跃公司的 slug。需要 `ui.commentAnnotation.register` 能力。
#### `commentContextMenuItem`
-A per-comment context menu item rendered in the "more" dropdown menu (⋮) on each comment in the issue detail timeline. Use this to add per-comment actions such as "Create sub-issue from comment", "Translate", "Flag for review", or custom plugin actions. Receives `PluginCommentContextMenuItemProps` with `context.entityId` set to the comment UUID, `context.entityType` set to `"comment"`, `context.parentEntityId` set to the parent issue UUID, `context.projectId` set to the issue's project (if any), and `context.companyPrefix` set to the active company slug. Plugins can open drawers, modals, or popovers scoped to that comment. The ⋮ menu button only appears on comments where at least one plugin renders visible content. Requires the `ui.action.register` capability.
+在问题详情时间轴中每条评论的"更多"下拉菜单(⋮)中渲染的逐条上下文菜单项。适用于添加逐条操作,例如"从评论创建子问题"、"翻译"、"标记审阅"或自定义插件操作。接收 `PluginCommentContextMenuItemProps`,其中 `context.entityId` 设置为评论 UUID,`context.entityType` 设置为 `"comment"`,`context.parentEntityId` 设置为父问题 UUID,`context.projectId` 设置为问题所属项目(如有),`context.companyPrefix` 设置为当前活跃公司的 slug。插件可以打开限定到该评论的抽屉、模态框或弹出框。⋮ 菜单按钮仅在至少有一个插件渲染可见内容的评论上显示。需要 `ui.action.register` 能力。
-### Launcher actions and render options
+### 启动器操作与渲染选项
-| Launcher action | Description |
+| 启动器操作 | 说明 |
|-----------------|-------------|
-| `navigate` | Navigate to a route (plugin or host). |
-| `openModal` | Open a modal. |
-| `openDrawer` | Open a drawer. |
-| `openPopover` | Open a popover. |
-| `performAction` | Run an action (e.g. call plugin). |
-| `deepLink` | Deep link to plugin or external URL. |
-
-| Render option | Values | Description |
+| `navigate` | 导航到一个路由(插件或宿主)。 |
+| `openModal` | 打开一个模态框。 |
+| `openDrawer` | 打开一个抽屉。 |
+| `openPopover` | 打开一个弹出框。 |
+| `performAction` | 执行一个操作(例如调用插件)。 |
+| `deepLink` | 深度链接到插件或外部 URL。 |
+
+| 渲染选项 | 取值 | 说明 |
|---------------|--------|-------------|
-| `environment` | `hostInline`, `hostOverlay`, `hostRoute`, `external`, `iframe` | Container the launcher expects after activation. |
-| `bounds` | `inline`, `compact`, `default`, `wide`, `full` | Size hint for overlays/drawers. |
+| `environment` | `hostInline`, `hostOverlay`, `hostRoute`, `external`, `iframe` | 启动器激活后期望的容器类型。 |
+| `bounds` | `inline`, `compact`, `default`, `wide`, `full` | 叠加层/抽屉的尺寸提示。 |
-### Capabilities
+### 能力
-Declare in `manifest.capabilities`. Grouped by scope:
+在 `manifest.capabilities` 中声明。按作用域分组:
-| Scope | Capability |
+| 作用域 | 能力 |
|-------|------------|
-| **Company** | `companies.read` |
+| **公司** | `companies.read` |
| | `projects.read` |
| | `project.workspaces.read` |
| | `issues.read` |
@@ -312,16 +312,16 @@ Declare in `manifest.capabilities`. Grouped by scope:
| | `issue.comments.create` |
| | `activity.log.write` |
| | `metrics.write` |
-| **Instance** | `instance.settings.register` |
+| **实例** | `instance.settings.register` |
| | `plugin.state.read` |
| | `plugin.state.write` |
-| **Runtime** | `events.subscribe` |
+| **运行时** | `events.subscribe` |
| | `events.emit` |
| | `jobs.schedule` |
| | `webhooks.receive` |
| | `http.outbound` |
| | `secrets.read-ref` |
-| **Agent** | `agent.tools.register` |
+| **代理** | `agent.tools.register` |
| | `agents.invoke` |
| | `agent.sessions.create` |
| | `agent.sessions.list` |
@@ -334,9 +334,9 @@ Declare in `manifest.capabilities`. Grouped by scope:
| | `ui.commentAnnotation.register` |
| | `ui.action.register` |
-Full list in code: import `PLUGIN_CAPABILITIES` from `@paperclipai/plugin-sdk`.
+完整列表见代码:从 `@paperclipai/plugin-sdk` 导入 `PLUGIN_CAPABILITIES`。
-## UI quick start
+## UI 快速入门
```tsx
import { usePluginData, usePluginAction } from "@paperclipai/plugin-sdk/ui";
@@ -354,11 +354,11 @@ export function DashboardWidget() {
}
```
-### Hooks reference
+### Hooks 参考
#### `usePluginData(key, params?)`
-Fetches data from the worker's registered `getData` handler. Re-fetches when `params` changes. Returns `{ data, loading, error, refresh }`.
+从 worker 注册的 `getData` 处理器获取数据。当 `params` 变化时重新获取。返回 `{ data, loading, error, refresh }`。
```tsx
import { usePluginData } from "@paperclipai/plugin-sdk/ui";
@@ -390,7 +390,7 @@ export function SyncStatusWidget({ context }: PluginWidgetProps) {
#### `usePluginAction(key)`
-Returns an async function that calls the worker's `performAction` handler. Throws `PluginBridgeError` on failure.
+返回一个异步函数,用于调用 worker 的 `performAction` 处理器。失败时抛出 `PluginBridgeError`。
```tsx
import { useState } from "react";
@@ -426,7 +426,7 @@ export function ResyncButton({ context }: PluginWidgetProps) {
#### `useHostContext()`
-Reads the active company, project, entity, and user context. Use this to scope data fetches and actions.
+读取当前活跃的公司、项目、实体和用户上下文。使用此 hook 将数据获取和操作限定在相应范围内。
```tsx
import { useHostContext, usePluginData } from "@paperclipai/plugin-sdk/ui";
@@ -446,7 +446,7 @@ export function IssueLinearLink({ context }: PluginDetailTabProps) {
#### `usePluginStream(channel, options?)`
-Subscribes to a real-time event stream pushed from the plugin worker via SSE. The worker pushes events using `ctx.streams.emit(channel, event)` and the hook receives them as they arrive. Returns `{ events, lastEvent, connecting, connected, error, close }`.
+订阅由插件 worker 通过 SSE 推送的实时事件流。Worker 使用 `ctx.streams.emit(channel, event)` 推送事件,hook 在事件到达时接收。返回 `{ events, lastEvent, connecting, connected, error, close }`。
```tsx
import { usePluginStream } from "@paperclipai/plugin-sdk/ui";
@@ -470,17 +470,17 @@ export function ChatMessages({ context }: PluginWidgetProps) {
}
```
-The SSE connection targets `GET /api/plugins/:pluginId/bridge/stream/:channel?companyId=...`. The host bridge manages the EventSource lifecycle; `close()` terminates the connection.
+SSE 连接目标为 `GET /api/plugins/:pluginId/bridge/stream/:channel?companyId=...`。宿主 bridge 管理 EventSource 的生命周期;`close()` 用于终止连接。
-### UI authoring note
+### UI 编写说明
-The current host does **not** provide a real shared component library to plugins yet. Use normal React components, your own CSS, or your own small design primitives inside the plugin package.
+当前宿主**尚未**为插件提供真正的共享组件库。请在插件包内使用普通 React 组件、自定义 CSS 或自定义的轻量设计基元。
-### Slot component props
+### 插槽组件 Props
-Each slot type receives a typed props object with `context: PluginHostContext`. Import from `@paperclipai/plugin-sdk/ui`.
+每种插槽类型均接收一个带有 `context: PluginHostContext` 的类型化 props 对象。从 `@paperclipai/plugin-sdk/ui` 导入。
-| Slot type | Props interface | `context` extras |
+| 插槽类型 | Props 接口 | `context` 额外字段 |
|-----------|----------------|------------------|
| `page` | `PluginPageProps` | — |
| `sidebar` | `PluginSidebarProps` | — |
@@ -493,7 +493,7 @@ Each slot type receives a typed props object with `context: PluginHostContext`.
| `commentContextMenuItem` | `PluginCommentContextMenuItemProps` | `entityId: string`, `entityType: "comment"`, `parentEntityId: string`, `projectId`, `companyPrefix` |
| `projectSidebarItem` | `PluginProjectSidebarItemProps` | `entityId: string`, `entityType: "project"` |
-Example detail tab with entity context:
+带实体上下文的详情标签页示例:
```tsx
import type { PluginDetailTabProps } from "@paperclipai/plugin-sdk/ui";
@@ -521,16 +521,16 @@ export function AgentMetricsTab({ context }: PluginDetailTabProps) {
}
```
-## Launcher surfaces and modals
+## 启动器挂载区域与模态框
-V1 does not provide a dedicated `modal` slot. Plugins can either:
+V1 不提供专用的 `modal` 插槽。插件可以:
-- declare concrete UI mount points in `ui.slots`
-- declare host-rendered entry points in `ui.launchers`
+- 在 `ui.slots` 中声明具体的 UI 挂载点
+- 在 `ui.launchers` 中声明由宿主渲染的入口点
-Supported launcher placement zones currently mirror the major host surfaces such as `projectSidebarItem`, `globalToolbarButton`, `toolbarButton`, `detailTab`, `settingsPage`, and `contextMenuItem`. Plugins may still open their own local modal from those entry points when needed.
+目前支持的启动器放置区域与主要宿主界面对应,包括 `projectSidebarItem`、`globalToolbarButton`、`toolbarButton`、`detailTab`、`settingsPage` 和 `contextMenuItem`。插件仍可在需要时从这些入口点打开自有的本地模态框。
-Declarative launcher example:
+声明式启动器示例:
```json
{
@@ -555,16 +555,13 @@ Declarative launcher example:
}
```
-The host returns launcher metadata from `GET /api/plugins/ui-contributions` alongside slot declarations.
+宿主通过 `GET /api/plugins/ui-contributions` 返回启动器元数据以及插槽声明。
-When a launcher opens a host-owned overlay or page, `useHostContext()`,
-`usePluginData()`, and `usePluginAction()` receive the current
-`renderEnvironment` through the bridge. Use that to tailor compact modal UI vs.
-full-page layouts without adding custom route parsing in the plugin.
+当启动器打开宿主拥有的叠加层或页面时,`useHostContext()`、`usePluginData()` 和 `usePluginAction()` 会通过 bridge 接收当前的 `renderEnvironment`。使用该值来定制紧凑模态框 UI 与全页面布局,而无需在插件中添加自定义路由解析。
-## Project sidebar item
+## 项目侧边栏条目
-Plugins can add a link under each project in the sidebar via the `projectSidebarItem` slot. This is the recommended slot-based launcher pattern for project-scoped workflows because it can deep-link into a richer plugin tab. The component is rendered once per project with that project’s id in `context.entityId`. Declare the slot and capability in your manifest:
+插件可以通过 `projectSidebarItem` 插槽在侧边栏中每个项目下方添加链接。这是面向项目作用域工作流的推荐插槽式启动器模式,因为它可以深度链接到更丰富的插件标签页。该组件为每个项目渲染一次,项目 id 在 `context.entityId` 中。在 manifest 中声明插槽和能力:
```json
{
@@ -583,7 +580,7 @@ Plugins can add a link under each project in the sidebar via the `projectSidebar
}
```
-Minimal React component that links to the project’s plugin tab (see project detail tabs in the spec):
+链接到项目插件标签页的最简 React 组件(参见规范中的项目详情标签页):
```tsx
import type { PluginProjectSidebarItemProps } from "@paperclipai/plugin-sdk/ui";
@@ -600,18 +597,18 @@ export function FilesLink({ context }: PluginProjectSidebarItemProps) {
}
```
-Use optional `order` in the slot to sort among other project sidebar items. See §19.5.1 in the plugin spec and project detail plugin tabs (§19.3) for the full flow.
+在插槽中使用可选的 `order` 字段可控制与其他项目侧边栏条目的排序位置。完整流程请参见插件规范 §19.5.1 和项目详情插件标签页(§19.3)。
-## Toolbar launcher with a local modal
+## 带本地模态框的工具栏启动器
-Two toolbar slot types are available depending on where the button should appear:
+可用的工具栏插槽类型有两种,取决于按钮应出现的位置:
-- **`globalToolbarButton`** — renders in the top bar on every page, scoped to the company. No entity context. Use for workspace-wide actions.
-- **`toolbarButton`** — renders on entity detail pages (project, issue, etc.). Receives `entityId` and `entityType`. Declare `entityTypes` to control which pages the button appears on.
+- **`globalToolbarButton`** — 在每个页面的顶部栏渲染,作用域为公司级别。无实体上下文。用于工作区范围的操作。
+- **`toolbarButton`** — 在实体详情页(项目、问题等)的工具栏渲染。接收 `entityId` 和 `entityType`。声明 `entityTypes` 可控制按钮出现在哪些页面。
-For short-lived actions, mount the appropriate slot type and open a plugin-owned modal inside the component. Use `useHostContext()` to scope the action to the current company or entity.
+对于短暂的操作,挂载适当的插槽类型并在组件内部打开插件自有的模态框。使用 `useHostContext()` 将操作限定到当前公司或实体。
-Project-scoped example (appears only on project detail pages):
+项目作用域示例(仅出现在项目详情页面):
```json
{
@@ -697,15 +694,15 @@ export function SyncToolbarButton() {
}
```
-Prefer deep-linkable tabs and pages for primary workflows. Reserve plugin-owned modals for confirmations, pickers, and compact editors.
+对于主要工作流,优先使用可深度链接的标签页和页面。将插件自有的模态框保留用于确认、选择器和紧凑编辑器。
-## Real-time streaming (`ctx.streams`)
+## 实时流式传输(`ctx.streams`)
-Plugins can push real-time events from the worker to the UI using server-sent events (SSE). This is useful for streaming LLM tokens, live sync progress, or any push-based data.
+插件可以使用服务端推送事件(SSE)将实时事件从 worker 推送到 UI。这对于流式传输 LLM token、实时同步进度或任何基于推送的数据非常有用。
-### Worker side
+### Worker 端
-In `setup()`, use `ctx.streams` to open a channel, emit events, and close when done:
+在 `setup()` 中,使用 `ctx.streams` 打开频道、发出事件并在完成时关闭:
```ts
const plugin = definePlugin({
@@ -725,42 +722,42 @@ const plugin = definePlugin({
});
```
-**API:**
+**API:**
-| Method | Description |
+| 方法 | 说明 |
|--------|-------------|
-| `ctx.streams.open(channel, companyId)` | Open a named stream channel and associate it with a company. Sends a `streams.open` notification to the host. |
-| `ctx.streams.emit(channel, event)` | Push an event to the channel. The `companyId` is automatically resolved from the prior `open()` call. |
-| `ctx.streams.close(channel)` | Close the channel and clear the company mapping. Sends a `streams.close` notification. |
+| `ctx.streams.open(channel, companyId)` | 打开一个命名的流频道并将其与某个公司关联。向宿主发送 `streams.open` 通知。 |
+| `ctx.streams.emit(channel, event)` | 向频道推送事件。`companyId` 会自动从之前的 `open()` 调用中解析。 |
+| `ctx.streams.close(channel)` | 关闭频道并清除公司映射。发送 `streams.close` 通知。 |
-Stream notifications are fire-and-forget JSON-RPC messages (no `id` field). They are sent via `notifyHost()` synchronously during handler execution.
+流式通知是即发即忘的 JSON-RPC 消息(无 `id` 字段)。它们在处理器执行期间通过 `notifyHost()` 同步发送。
-### UI side
+### UI 端
-Use the `usePluginStream` hook (see [Hooks reference](#usepluginstreamtchannel-options) above) to subscribe to events from the UI.
+使用 `usePluginStream` hook(参见上方的 [Hooks 参考](#usepluginstreamtchannel-options))从 UI 订阅事件。
-### Host-side architecture
+### 宿主端架构
-The host maintains an in-memory `PluginStreamBus` that fans out worker notifications to connected SSE clients:
+宿主维护一个内存中的 `PluginStreamBus`,将 worker 通知扇出到已连接的 SSE 客户端:
-1. Worker emits `streams.emit` notification via stdout
-2. Host (`plugin-worker-manager`) receives the notification and publishes to `PluginStreamBus`
-3. SSE endpoint (`GET /api/plugins/:pluginId/bridge/stream/:channel?companyId=...`) subscribes to the bus and writes events to the response
+1. Worker 通过 stdout 发出 `streams.emit` 通知
+2. 宿主(`plugin-worker-manager`)接收通知并发布到 `PluginStreamBus`
+3. SSE 端点(`GET /api/plugins/:pluginId/bridge/stream/:channel?companyId=...`)订阅总线并将事件写入响应
-The bus is keyed by `pluginId:channel:companyId`, so multiple UI clients can subscribe to the same stream independently.
+总线以 `pluginId:channel:companyId` 为键,因此多个 UI 客户端可以独立订阅同一个流。
-### Streaming agent responses to the UI
+### 向 UI 流式传输代理响应
-`ctx.streams` and `ctx.agents.sessions` are complementary. The worker sits between them, relaying agent events to the browser in real time:
+`ctx.streams` 和 `ctx.agents.sessions` 是互补的。Worker 处于两者之间,将代理事件实时中继到浏览器:
```
UI ──usePluginAction──▶ Worker ──sessions.sendMessage──▶ Agent
UI ◀──usePluginStream── Worker ◀──onEvent callback────── Agent
```
-The agent doesn't know about streams — the worker decides what to relay. Encode the agent ID in the channel name to scope streams per agent.
+代理不了解流的存在——由 worker 决定中继什么内容。在频道名称中编码代理 ID 以按代理限定流的作用域。
-**Worker:**
+**Worker:**
```ts
ctx.actions.register("ask-agent", async (params) => {
@@ -788,7 +785,7 @@ ctx.actions.register("ask-agent", async (params) => {
});
```
-**UI:**
+**UI:**
```tsx
import { useState } from "react";
@@ -820,15 +817,15 @@ export function AgentChat({ agentId, companyId }: { agentId: string; companyId:
}
```
-## Agent sessions (two-way chat)
+## 代理会话(双向对话)
-Plugins can hold multi-turn conversational sessions with agents:
+插件可以与代理进行多轮对话会话:
```ts
-// Create a session
+// 创建会话
const session = await ctx.agents.sessions.create(agentId, companyId);
-// Send a message and stream the response
+// 发送消息并流式接收响应
await ctx.agents.sessions.sendMessage(session.sessionId, companyId, {
prompt: "Help me triage this issue",
onEvent: (event) => {
@@ -837,18 +834,18 @@ await ctx.agents.sessions.sendMessage(session.sessionId, companyId, {
},
});
-// List active sessions
+// 列出活跃会话
const sessions = await ctx.agents.sessions.list(agentId, companyId);
-// Close when done
+// 完成后关闭
await ctx.agents.sessions.close(session.sessionId, companyId);
```
-Requires capabilities: `agent.sessions.create`, `agent.sessions.list`, `agent.sessions.send`, `agent.sessions.close`.
+所需能力:`agent.sessions.create`、`agent.sessions.list`、`agent.sessions.send`、`agent.sessions.close`。
-Exported types: `AgentSession`, `AgentSessionEvent`, `AgentSessionSendResult`, `PluginAgentSessionsClient`.
+导出类型:`AgentSession`、`AgentSessionEvent`、`AgentSessionSendResult`、`PluginAgentSessionsClient`。
-## Testing utilities
+## 测试工具
```ts
import { createTestHarness } from "@paperclipai/plugin-sdk/testing";
@@ -860,7 +857,7 @@ await plugin.definition.setup(harness.ctx);
await harness.emit("issue.created", { issueId: "iss_1" }, { entityId: "iss_1", entityType: "issue" });
```
-## Bundler presets
+## 打包工具预设
```ts
import { createPluginBundlerPresets } from "@paperclipai/plugin-sdk/bundlers";
@@ -870,19 +867,19 @@ const presets = createPluginBundlerPresets({ uiEntry: "src/ui/index.tsx" });
// presets.rollup.worker / presets.rollup.manifest / presets.rollup.ui
```
-## Local dev server (hot-reload events)
+## 本地开发服务器(热重载事件)
```bash
paperclip-plugin-dev-server --root . --ui-dir dist/ui --port 4177
```
-Or programmatically:
+或通过编程方式:
```ts
import { startPluginDevServer } from "@paperclipai/plugin-sdk/dev-server";
const server = await startPluginDevServer({ rootDir: process.cwd() });
```
-Dev server endpoints:
-- `GET /__paperclip__/health` returns `{ ok, rootDir, uiDir }`
-- `GET /__paperclip__/events` streams `reload` SSE events on UI build changes
+开发服务器端点:
+- `GET /__paperclip__/health` 返回 `{ ok, rootDir, uiDir }`
+- `GET /__paperclip__/events` 在 UI 构建变化时流式传输 `reload` SSE 事件
diff --git a/ui/README.md b/ui/README.md
index 0e688669e3..d51f34ea04 100644
--- a/ui/README.md
+++ b/ui/README.md
@@ -1,11 +1,11 @@
# @paperclipai/ui
-Published static assets for the Paperclip board UI.
+Paperclip 面板 UI 的已发布静态资源。
-## What gets published
+## 发布内容
-The npm package contains the production build under `dist/`. It does not ship the UI source tree or workspace-only dependencies.
+npm 包包含 `dist/` 下的生产构建。它不包含 UI 源代码树或仅工作区依赖。
-## Typical use
+## 典型用法
-Install the package, then serve or copy the built files from `node_modules/@paperclipai/ui/dist`.
+安装该包,然后从 `node_modules/@paperclipai/ui/dist` 提供或复制构建后的文件。
diff --git a/ui/src/App.tsx b/ui/src/App.tsx
index 38b5f4bc88..40e2ff804c 100644
--- a/ui/src/App.tsx
+++ b/ui/src/App.tsx
@@ -52,11 +52,11 @@ function BootstrapPendingPage({ hasActiveInvite = false }: { hasActiveInvite?: b
return (
-