# Event mapping Pi 原生事件到 HarnessEvent 的转换集中在 `packages/harness/src/pi-event-adapter.ts`。未识别事件安全忽略,不会让 Run 崩溃。 | Pi / Harness fact | HarnessEvent | assistant-ui / UI state | | --- | --- | --- | | message text delta | `assistant.delta` | 按 messageId 合并文本,status running | | assistant message end | `assistant.completed` | message status complete,polite live announcement | | extension `tool_call` preflight | `tool.requested` | Tool part running / approval pending | | tool execution success | `tool.completed` | Tool result success | | tool execution error | `tool.failed` | Tool result error | | canonical Skill `read` request | `skill.requested` | Catalog 高亮 requested | | 同一 read 成功结果 | `skill.loaded` | Catalog 高亮 loaded | | ApprovalBroker request | `approval.required` | Tool card + modal pending | | broker decision/timeout/cancel | `approval.resolved` | approved/denied/expired/cancelled | | registry accepts message | `user.message`, `run.started` | user message + running | | prompt resolves | `run.completed` | run idle | | abort by user/system | `run.cancelled` | incomplete,显示 reason | | prompt/create failure | `run.failed` | incomplete/error | Skill requested/loaded 是 Harness 推导事件,不是 Pi 原生事件。匹配依据是 `DefaultResourceLoader` 已发现的 canonical `SKILL.md` 索引;仅文件名相同不算命中。 `tool.requested` 在 extension preflight 写入,后续 Pi `tool_execution_start` 按 toolCallId 去重。读取类 Tool 的 completed event 只暴露安全摘要,避免把 Skill 正文或文件内容复制到 Timeline。参数会限长、敏感字段脱敏,绝对路径转换为项目相对路径或 ``。 SSE 事件 id 是 eventId,事件名是 HarnessEvent type。`Last-Event-ID` 比 query `afterSequence` 优先;若 cursor 早于 1000 条保留窗口,先发送 `stream.gap`,客户端重新建立可识别边界,而不是静默丢事件。