# oh-my-open-pi 迁移溯源

本文件记录 `oh-my-openagent` 到 `oh-my-open-pi` 的迁移依据。迁移目标是把 OpenCode 插件里的可复用能力转成 Pi Coding Agent package：扩展入口、工具、hook、provider 注册、技能和 prompt 资源都走 Pi 原生扩展机制。

逐文件审计清单见 [`docs/original-code-file-audit.json`](original-code-file-audit.json)。该清单覆盖原始仓全部 2050 个跟踪文件 — 包括 1832 个代码文件（`*.ts`、`*.tsx`、`*.js`、`*.mjs`、`*.cjs`、`*.d.ts`、`*.css`、`*.graphql`）和 218 个非代码文件（`*.md`、`*.json`、`*.yml`、`*.png`、`*.jpg`、`*.jsonc`、`*.lock`、`*.toml`、`.gitignore`、GitHub CI 配置等）——  总计 340590 行、27203453 字节，记录每个文件的 `sha256`、行数、字节数、迁移分组、处置方式、目标位置和理由。原始来源固定为 `/Volumes/JJZ/jerryjiang/unicom/dev/oh-my-openagent` 的 `dev` 分支提交 `9ba3b574a7d14b1e3037c32df7b3708f78be5970`。

## 依据代码

| 来源 | 证据路径 | 用途 |
| --- | --- | --- |
| 原始 OpenCode 插件入口 | `/Volumes/JJZ/jerryjiang/unicom/dev/oh-my-openagent/src/index.ts` | 原始插件加载 config、tools、hooks、plugin interface 的主流程 |
| 原始 config 合并 | `/Volumes/JJZ/jerryjiang/unicom/dev/oh-my-openagent/src/plugin-config.ts` | user/project 配置合并、数组去重、agents/categories 深合并 |
| 原始 agent 名称 schema | `/Volumes/JJZ/jerryjiang/unicom/dev/oh-my-openagent/src/config/schema/agent-names.ts` | `BuiltinAgentNameSchema` 和 `AgentNameSchema` 作为迁移 agent 清单真相源 |
| 原始 agent 构建 handler | `/Volumes/JJZ/jerryjiang/unicom/dev/oh-my-openagent/src/plugin-handlers/agent-config-handler.ts` | Prometheus 专用构建、OpenCode 默认 build/plan 兼容处理和 Sisyphus agent 装配边界 |
| 原始工具注册 | `/Volumes/JJZ/jerryjiang/unicom/dev/oh-my-openagent/src/plugin/tool-registry.ts` | grep、glob、ast-grep、session、background、skill、task、hashline edit 等工具来源 |
| 原始 hook 聚合 | `/Volumes/JJZ/jerryjiang/unicom/dev/oh-my-openagent/src/create-hooks.ts` | core、continuation、skill hook 的组合方式 |
| Pi 扩展文档 | `/Volumes/JJZ/jerryjiang/unicom/dev/pi-mono/packages/coding-agent/docs/extensions.md` | default factory、`pi.registerTool()`、`pi.on()`、`pi.registerCommand()` |
| Pi 快捷键文档 | `/Volumes/JJZ/jerryjiang/unicom/dev/pi-mono/packages/coding-agent/docs/keybindings.md` | `registerShortcut()` 可用 key 格式、Tab/autocomplete 和模型思考等级快捷键边界 |
| Pi package 文档 | `/Volumes/JJZ/jerryjiang/unicom/dev/pi-mono/packages/coding-agent/docs/packages.md` | `package.json#pi` 的 extensions/skills/prompts 声明 |
| Pi 扩展类型 | `/Volumes/JJZ/jerryjiang/unicom/dev/pi-mono/packages/coding-agent/src/core/extensions/types.ts` | `ExtensionAPI`、`ToolDefinition<TSchema>`、事件返回值和 provider config contract |
| Pi loader | `/Volumes/JJZ/jerryjiang/unicom/dev/pi-mono/packages/coding-agent/src/core/extensions/loader.ts` | package manifest extension entry 发现逻辑 |
| Pi runner | `/Volumes/JJZ/jerryjiang/unicom/dev/pi-mono/packages/coding-agent/src/core/extensions/runner.ts` | `before_provider_request`、`before_agent_start`、`tool_call`、`tool_result` 的执行语义 |
| Pi package manager | `/Volumes/JJZ/jerryjiang/unicom/dev/pi-mono/packages/coding-agent/src/core/package-manager.ts` | package resources 解析和启用逻辑 |

## 功能映射

| 原始能力 | Pi native 映射 | 当前实现 | 验证 |
| --- | --- | --- | --- |
| OpenCode plugin module | Pi default extension factory | `src/index.ts` 导出 default factory，`package.json#pi.extensions` 指向 `src/index.ts` | `tests/pi-contract.test.ts` 使用 Pi `discoverAndLoadExtensions()` 加载包 |
| user/project 配置合并 | Pi 扩展加载时读取全局 agent dir 和项目 `.pi` 配置 | `src/config.ts` 支持 JSON/JSONC、数组去重、agents/categories/routing 深合并 | `test/config.test.ts` |
| agents/categories 模型路由 | `before_agent_start` 设置 Pi model/thinking level，`before_provider_request` 改写 provider payload，`pi.registerCommand()` 和 `pi.registerShortcut()` 提供交互式 agent 切换 | `src/hooks.ts` 的 model router 和 provider payload router，`src/extension.ts` 的 `/oh-my-open-pi-agent` 命令与 `Ctrl+Shift+A` 循环切换快捷键 | `test/hooks.test.ts`、`test/extension.test.ts` |
| 内置 agent profile | Pi `before_agent_start` system prompt chaining 和 active tools API | `src/agent-profiles.ts` 内置 Sisyphus、Hephaestus、Prometheus、Oracle、Librarian、Explore、Multimodal-Looker、Metis、Momus、Atlas、Sisyphus-Junior 的 profile、提示词、mode 和工具策略 | `test/agent-profiles.test.ts`、`test/hooks.test.ts`、`test/extension.test.ts` |
| provider 注册 | `pi.registerProvider()` | `src/extension.ts` 读取 `providers` 并注册到 Pi | `test/extension.test.ts` |
| grep/glob | Pi 自定义工具 | `src/tools/search.ts`，参数 schema 使用 TypeBox | `test/search-tools.test.ts`、`tests/pi-contract.test.ts` |
| ast-grep search/replace | Pi 自定义工具 | `src/tools/ast-grep.ts`，支持 search、dry-run replace、apply replace，并识别 postinstall shim | `test/ast-grep-tools.test.ts` |
| session 工具 | Pi `SessionManager` | `src/tools/session.ts` 的 list/read/search/info | `test/session-tools.test.ts` |
| background agent | Pi 子进程后台任务。agent 路由**显式指定**（不传 agent、空串或纯空白视为未指定，不设 `OH_MY_OPEN_PI_AGENT`；非空白字符串原样透传给子进程解析，未知路由安全降级）。启动后台任务不继承、不覆盖父进程当前 agent 路由 | `src/background/manager.ts` 和 `src/tools/background.ts`，有并发上限、状态持久化、输出读取、取消和 agent 路由 | `test/background-manager.test.ts` |
| runtime reload/status/agent switch | Pi command context、extension shortcut、API active tools 和 model/thinking level API | `src/tools/runtime.ts`、`src/extension.ts` | `test/runtime-tools.test.ts`、`test/extension.test.ts`、`tests/pi-contract.test.ts` |
| tool_call guard | Pi `tool_call` event | `src/hooks.ts` 阻断 bash deny pattern 和 protected paths | `test/hooks.test.ts` |
| tool_result truncation | Pi `tool_result` event | `src/hooks.ts` 按配置截断文本结果 | `test/hooks.test.ts` |
| context injection | Pi `before_agent_start` event message injection | `src/hooks.ts` 注入隐藏 custom message | `test/hooks.test.ts` |
| skills/prompts package resources | `package.json#pi.skills`、`package.json#pi.prompts` | `package.json`、`skills/oh-my-open-pi/SKILL.md`、`prompts/oh-my-open-pi.md` | `tests/pi-contract.test.ts` |
| disabled tools | Pi 注册前过滤工具 | `src/extension.ts` 读取 `disabled_tools` | `test/extension.test.ts` |

## 内置 Profile 来源语义溯源

每个内置 Pi agent profile 在 `src/agent-profiles.ts` 的 `builtinProfileSources` 中记录原始来源路径和代表性来源片段，使迁移可机器校验。Source kind 分类：

- **prompt**：直接从原始 agent prompt 迁移，保留身份、模式、触发规则、读写/委托规范、输出形状和验证指南。
- **adaptation**：保留原始语义但适配了 Pi 原生行为差异的迁移。
- **summary**：有意简化的迁移，原始语义未完全保留；来源映射和审计中包含显式的简化理由。

### Atlas — 有意简化迁移

Atlas 从 OhMyOpenCode Master Orchestrator（`src/agents/atlas/`）简化为 Pi 原生计划执行和会话连续性 agent。原始 Atlas 设计围绕 OpenCode 的 `task()` 委托系统构建，包含：

- **严格的禁止自行编码规则**："You never write code yourself. You orchestrate specialists who do."
- **6 部分委托 prompt 模板**（TASK、EXPECTED OUTCOME、REQUIRED TOOLS、MUST DO、MUST NOT DO、CONTEXT）
- **Notepad 协议**用于委托间的累积智能（`.sisyphus/notepads/{plan-name}/`）
- **强制手动代码审查**每次委托后（逐行 Read 每个变更文件）
- **最终验证波次**包含多个审批关卡审查者（F1-F4），需全部 APPROVE 才完成
- **计划复选框编辑语义**：每次委托完成后编辑 `- [ ]` 为 `- [x]`
- **自动继续策略**：绝不询问用户"是否继续"，立即自动转到下一个任务

Pi 原生 Atlas 将这些简化为：从现有计划或 todo 结构执行，保留沿袭（决策、已完成工作、阻断项），跨会话保持任务推进，并在推进前验证每一波次。有意省略的行为反映了 Pi 原生在任务委托、子 agent 架构和工具策略接口方面的差异。

直接迁移的 profile（sisyphus、hephaestus、oracle、librarian、explore、multimodal-looker、prometheus、metis、momus）在 `builtinProfileSources` 中以 `sourceKind: "prompt"` 记录，并附带原始来源路径和代表性片段。

Sisyphus-Junior 以 `sourceKind: "adaptation"` 记录：保留原始直接执行语义但适配了 Pi 原生行为差异，包括将原始角色化 prompt 格式扁平化为自然语言指令、添加有界作用域语义、以及将 OpenCode 专属 task/todo/lsp_diagnostics 规则替换为 Pi 原生验证方式。

`test/agent-profiles.test.ts` 验证每个 profile 的来源路径、片段和 Atlas 的简化理由。

## Pi 原生边界

这些 OpenCode 专属能力在当前 Pi package 中保留为配置兼容或由 Pi 原生机制承接：

| OpenCode 能力 | 当前处理 |
| --- | --- |
| Claude Code/OpenCode hook 兼容层 | Pi 的 lifecycle events 承接当前已迁移的 guard、routing、context、result 处理 |
| OpenCode MCP 管理 | Pi package resources 和 Pi 自身扩展生态承接技能、prompt、extension 分发 |
| OpenCode task/agent 专用 UI | Pi commands、extension shortcuts、tools、system prompt chaining、active tools 和后台 Pi 进程承接当前可验证的运行路径 |
| OpenCode Tab agent 切换 | Pi `registerCommand()`、`getArgumentCompletions()` 和 `registerShortcut()` 承接；默认快捷键是 `ctrl+shift+a`，可通过 `agent_switch.shortcut` 改绑定或关闭 |
| OpenCode telemetry/OpenClaw/tmux | 运行时外部系统集成留在 OpenCode 侧，Pi package 当前聚焦 Pi 原生扩展 contract |

## Hook Family 迁移和省略边界

原始 OpenCode hook 系统包含多个 hook 系列。迁移后的 Pi package 仅注册 Pi 原生 lifecycle 事件（`before_agent_start`、`before_provider_request`、`tool_call`、`tool_result`），其余 OpenCode hook 系列因 Pi 原生无对应事件合约而省略，省略理由如下：

| Hook 系列 | 分类 | Pi 映射 | 省略/边界理由 |
| --- | --- | --- | --- |
| `lifecycle` (before_agent_start, before_provider_request) | **迁移** | `pi.on('before_agent_start')`, `pi.on('before_provider_request')` | 直接映射为 Pi lifecycle 事件，含 model/router 和 prompt/context 处理器 |
| `safety` (tool_call, tool_result) | **迁移** | `pi.on('tool_call')`, `pi.on('tool_result')` | 直接映射为 Pi lifecycle 事件，含 bash deny pattern、protected path guard 和输出截断 |
| `chat` (chat.message) | **省略** | 无 | Pi 原生无 chat-event 合约；OpenCode chat.message 生命周期事件在 Pi 中无等价事件。相关 chat-message-handler 文件审计为 pi-native-boundary |
| `session` (session.idle) | **省略** | 无 | OpenCode session.idle 事件用于后台 agent 转换；Pi 原生 session 生命周期不同。省略并记录在审计边界 |
| `notification` (toast, session.notification) | **省略** | 无 | OpenCode toast/session 通知 hook 系统；Pi 原生使用 `ui.notify()` 而非事件订阅模型。省略并记录在审计边界 |
| `request-pipeline` (chat.params, chat.headers) | **省略** | 无 | OpenCode chat 请求参数/头部修改 hook；Pi 原生 provider request routing 通过 `before_provider_request` 覆盖参数修改，无 header-injection 合约。省略并记录在审计边界 |
| `wrapper` (command.wrapper, tool.wrapper) | **省略** | 无 | OpenCode 命令/工具中间件式包装 hook；Pi 原生命令和工具不支持中间件式包装。省略并记录在审计边界 |
| `agent` (continuation) | **省略** | 无 | OpenCode agent continuation hook 用于多轮 chat 会话；Pi 原生 agent 生命周期不同。省略并记录在审计边界 |
| `skill` (skill) | **省略** | 无 | OpenCode skill 注册/执行 hook 系统；Pi 原生通过 `package.json#pi` skills/prompts 资源替代运行时 skill hook。省略并记录在审计边界 |
| `experimental` (experimental.transform) | **省略** | 无 | OpenCode 实验性 transform hook 用于 payload/response 修改；Pi 原生无实验性 transform 合约。省略并记录在审计边界 |
| `fallback` (model.fallback, runtime.fallback, delegate-task-retry) | **省略** | 无 | OpenCode model fallback 链式重试和 runtime session 重试 hook；Pi 原生 model routing 不支持自动 fallback 链重试。原始 `fallback_models`、`model_fallback`、`runtime_fallback` 配置字段在 Pi 兼容性配置中解析为 inert（不触发 retry hook、网络请求、provider 请求修改）。省略并记录在审计边界 |

所有省略的 hook 系列在 `docs/original-code-file-audit.json` 中有对应的审计条目，理由与 `VAL-HOOK-018`（`tests/runtime-surface-inventory.test.ts`）的 hook inventory 分类一致。

## 配置兼容性边界

以下 OpenCode 原始配置字段在 Pi package 中的兼容性处理：

| 原始字段 | 当前处理 | 验证 |
| --- | --- | --- |
| `provider` (单数) | 合并到 `providers`，与 `pi.registerProvider()` 一致；`providers` 同名 key 覆盖 `provider` 的值 | `test/config-compatibility.test.ts` |
| `disabled_agents` | 被 `resolveConfiguredAgentRoutes()` 全部路由面拦截（default_run_agent、命令选择、环境变量 seed、快捷键循环、补全） | `test/config-compatibility.test.ts` |
| `agents.<name>.disable` | 在路由解析中排除单个 agent | `test/config-compatibility.test.ts` |
| `categories.<name>.disable` | 在路由解析中排除单个 category（provider request 中 category.disable=true 回退到 selected/default agent routing） | `test/config-compatibility.test.ts`、`test/hooks.test.ts` |
| `fallback_models` | 安全解析并合并字符串数组（去重），不作 Pi 内重试。对象数组、单字符串、混合数组均解析通过但保持 inert（不触发 retry hook、网络请求、provider 请求修改） | `test/config-compatibility.test.ts` |
| `model_fallback` | 布尔字段，安全 inert。不注册 OpenCode chat/session 重试逻辑 | `test/config-compatibility.test.ts` |
| route `permission` (allow/deny/ask, `*` 通配, delegate_task, external_directory) | 完整解析但保持 inert。不改变 Pi active-tool policy、不触发 tool_call guard、不产生部分副作用 | `test/config-compatibility.test.ts` |
| `agents.<name>.category` | 字段解析通过但保持 inert。Agent 路由始终使用自身配置，不继承 category 的 model/variant/temperature/prompt/tools 等字段 | `test/config-compatibility.test.ts` |
| category 扩展字段 (`prompt`, `prompt_append`, `tools`, `fallback_models` 等) | 解析并保留在路由视图中但保持 inert。仅在 Pi 原生 lifecycle 有明确语义时才进入行为路径 | `test/config-compatibility.test.ts` |
| `disabled_skills`, `disabled_hooks`, `disabled_commands` | 安全 inert 兼容字段，解析通过但不影响 Pi runtime hook/command 注册 | `test/config-compatibility.test.ts` |
| `$schema`, `new_task_system_enabled`, `agent_definitions`, `hashline_edit`, `runtime_fallback`, `experimental` | OpenCode 专属字段，安全 inert。不引发进程启动、网络请求、MCP 注册或 route mutation | `test/config-compatibility.test.ts` |

所有兼容性字段均可在 JSONC 配置中出现而不导致插件崩溃、不触发隐藏的进程/网络/MCP/OpenCode 行为。API key 字符串不被 dereference、不被日志输出、不被转换（保持原值 pass-through）。

## 非代码审计覆盖

审计清单覆盖原始仓全部 218 个非代码文件，按组分类：

| 分组 | 说明 |
| --- | --- |
| `docs-and-readme` | README、CLA、CONTRIBUTING、AGENTS.md 等根级文档和 `docs/`、`drafts/` 中的原始文档文件 |
| `ci-and-templates` | GitHub Actions 工作流、Issue/PR 模板、FUNDING.yml |
| `project-assets` | `.github/assets/`、`assets/` 和 `docs/` 中的图像资源（PNG、JPG） |
| `root-support` | `package.json`、`tsconfig.json`、`bunfig.toml`、`bun.lock`、`.gitignore`、`signatures/` |
| `test-fixtures-non-code` | 测试 fixture 中的非代码文件（package.json、lock 文件、snapshot、Python 脚本） |
| `opencode-plugin-runtime` | OpenCode 内部配置和运行时文件（`.opencode/`） |
| `cli-packaging` | OpenCode 打包、发布、二进制构建相关文件（`packages/`、`patches/`、`migrations/`） |

所有非代码文件处置方式：
- `package-boundary`：OpenCode 打包/发布基础设施，替换为 Pi 包清单分发
- `audit-only`：文档、CI、资产文件仅供审计参考，不进入 Pi 运行时
- `selectively-adapted`：根级配置文件有选择地适配到 Pi 包
- `pi-native-boundary`：OpenCode 专属运行时配置，替换为 Pi 配置路径
- `test-evidence`：测试 fixture 作为迁移证据审查

## 审计分组全量清单

审计 JSON `taxonomy.groups` 定义了 28 个分组，覆盖原始仓全部 2050 个跟踪文件。每个分组必须在迁移溯源中提到：

| 分组 | 文件数 | 总行数 | 说明 |
| --- | --- | --- | --- |
| `agent-profiles` | audit.groups | audit.groups | 原始 agent profile 定义、prompt 语义、模式描述和工具策略 |
| `ast-grep-tools` | audit.groups | audit.groups | AST-grep 搜索和替换工具实现，语法感知代码匹配 |
| `background-agent` | audit.groups | audit.groups | 后台任务子系统：委托、并发、状态持久化、输出捕获和取消 |
| `ci-and-templates` | audit.groups | audit.groups | GitHub Actions 工作流、Issue/PR 模板和 CI 配置 |
| `claude-code-compat` | audit.groups | audit.groups | Claude Code 兼容层，提供 OpenCode 兼容的 agent 和工具接口 |
| `cli-packaging` | audit.groups | audit.groups | OpenCode CLI 打包、二进制分发、子包、补丁和迁移脚本 |
| `commands` | audit.groups | audit.groups | 在 OpenCode 命令界面注册的斜杠命令处理器 |
| `configuration` | audit.groups | audit.groups | 插件配置加载、合并、schema 定义和配置文件处理 |
| `docs-and-readme` | audit.groups | audit.groups | 文档、README 文件、设计草稿和迁移规划文档 |
| `hashline-edit` | audit.groups | audit.groups | 基于 Hashline 的代码编辑集成，内联 diff 应用 |
| `hooks` | audit.groups | audit.groups | 生命周期 hook 处理器：agent 启动、provider 请求、工具调用/结果、上下文注入和安全防护 |
| `lsp-tools` | audit.groups | audit.groups | Language Server Protocol 集成工具，IDE 风格代码智能 |
| `mcp` | audit.groups | audit.groups | Model Context Protocol 服务端/客户端管理和工具注册 |
| `media-tools` | audit.groups | audit.groups | 媒体处理工具：图像、视频和截图处理 |
| `openclaw` | audit.groups | audit.groups | OpenClaw 守护进程和外部运行时系统集成 |
| `opencode-plugin-runtime` | audit.groups | audit.groups | OpenCode 内部插件运行时：配置文件、会话管理和插件基础设施 |
| `plugin-entry` | audit.groups | audit.groups | 插件入口点、注册编排和顶层扩展界面 |
| `project-assets` | audit.groups | audit.groups | 项目图像资产、品牌和视觉资源 |
| `root-support` | audit.groups | audit.groups | 根级项目配置文件：package.json、tsconfig、lockfile、gitignore 和签名 |
| `search-tools` | audit.groups | audit.groups | Grep 和 glob 搜索工具实现，文件系统匹配 |
| `session-tools` | audit.groups | audit.groups | 会话管理工具：列表、读取、搜索和信息操作 |
| `shared-features` | audit.groups | audit.groups | 共享工具模块、通用 helper、deep-merge 和跨切面关注点 |
| `skills` | audit.groups | audit.groups | 技能定义，提供专业化的 agent 能力和工具组合 |
| `task-tools` | audit.groups | audit.groups | OpenCode 任务系统，agent 任务创建、列出和状态管理 |
| `test-fixtures-non-code` | audit.groups | audit.groups | 非代码测试 fixture 文件，用作迁移证据：lock 文件、快照和测试数据 |
| `testing-support` | audit.groups | audit.groups | 测试基础设施和共享测试工具 |
| `tests-and-fixtures` | audit.groups | audit.groups | 原始测试套件和测试 fixture 目录，覆盖所有迁移行为 |
| `tool-support` | audit.groups | audit.groups | 工具基础设施支持：结果格式化、错误处理和输出工具 |

（上表中 `audit.groups` 表示该值从审计 JSON 的 `groups.<name>.files` 和 `groups.<name>.lines` 动态读取，当前实际值见 [`docs/original-code-file-audit.json`](original-code-file-audit.json)。）

## 当前验证闸门

```bash
rtk bun test test tests
rtk bun run typecheck
rtk npm pack --dry-run --json
rtk git diff --check
```

`tests/pi-contract.test.ts` 是 Pi 对接主闸门：它直接调用 Pi Coding Agent 导出的 `discoverAndLoadExtensions()` 和 `DefaultPackageManager.resolveExtensionSources()`，验证本包能被 Pi loader 识别，所有工具参数都是 TypeBox schema，并且 extension、skill、prompt 都能按 package manifest 解析。
