# R2 任务报告

## 结论

第二轮文件编辑展示缺失的首个丢失层位于 AgentRun `codex-stdio` notification reducer，而不是 HWLAB Kafka mapper、SSE 或最终 UI 偶发漏 event。

Codex app-server 产生了 `fileChange` item，但 AgentRun 的 `isVisibleCodexToolItemType` 只接受 `commandExecution`、`webSearch`、`mcpToolCall` 和 `dynamicToolCall`。`fileChange` 的 `item/started`、`item/completed` 被计入 suppressed summary；文件变更只剩无文件身份的 `turn/diff/updated` backend status。因此后续 Kafka/HWLAB 无法恢复 `apply_patch`、文件名或 patch 摘要。

## Identity

- business trace：`trc_9352107b5e8a4125`
- OTel trace：`e8fb030498a68cb2cbbc460c439fc3fd`
- HWLAB session：`ses_d4473d6c-4d7a-4612-a102-254977698bc2`
- AgentRun session：`ses_agentrun_d4473d6c_4d7a_4612_a102_254977698bc2`
- run：`run_cc1bf3a430b14de1b1e147ea95f7773e`
- command：`cmd_dffb545477d145f6bbb66d5500dff7ed`

## 分层证据

### stdio / OTel

- `codex_stdio.notification`：985 spans。
- `codex_stdio.tool_call.started`：29 spans。
- `codex_stdio.tool_call.completed`：28 spans。
- 运行内存在真实文件编辑；AgentRun suppressed summary 的 `itemTypes` 明确包含 `fileChange: 8`。

### AgentRun durable events

- 普通 shell/command 工具被正确投影为成对 `tool_call started/completed`。
- 文件编辑对应多条 `turn/diff/updated`，例如 seq 56、57、59、67、70、71、78、81-88、92、100、105、108、112、115。
- raw durable payload 只有 `phase`、`runnerId`、`attemptId`、`commandId`，没有 file path、itemId、tool name、patch summary 或 diff hash。
- seq 117 suppressed summary：
  - suppressed total 94；
  - `item/started` 24、`item/completed` 24；
  - `fileChange` 8、`reasoning` 38、`userMessage` 2。

### 源码映射

`src/backend/codex-stdio.ts` 的 `isVisibleCodexToolItemType` 只允许四类工具，不包含 `fileChange`。未识别的 `turn/diff/updated` 进入 generic backend status fallback，只保存 phase。

### Kafka CLI replay

- `platform-infra kafka status --node NC01`：broker 与五个相关产品/debug topic ready。
- `codex-stdio.raw.v1` end offset 为 26558；`agentrun.event.v1` end offset 为 6406；`hwlab.event.v1` end offset 为 4906。
- 使用正式 AgentRun CLI 从 Kafka 执行 `regenerate agentrun --no-publish`：
  - 按 AgentRun session + business trace：`inputRecordCount=0`；
  - 按 HWLAB session + business trace：`inputRecordCount=0`；
  - `kafka tail stdio` 按 session/trace 与 run/command 均 matched=0。
- 调试过程没有向产品或 debug topic 追加事件；`topicAppended=false`（由 `--no-publish` 保证）。
- host 直接使用 cluster DNS 首次返回 `getaddrinfo ENOTFOUND`，随后按 `unidesk-kafka` 使用 loopback 临时 port-forward；通道已关闭。
- KafkaJS 出现既有 `TimeoutNegativeWarning`，不作为数据丢失证据。

### HWLAB / Workbench

- OTel 显示 `hwlab.kafka.live.direct_publish` 与 `fanout_receive` 均为 124，产品 Kafka→fanout 没有计数差。
- HWLAB legacy trace store 只保留 7 条 admission diagnostics，projection 仍停在 projecting；durable terminal authority 仍是 AgentRun completed。
- 即使 HWLAB mapper/SSE 完整转发，它收到的文件变更事实已经是降维后的 `turn/diff/updated`，无法生成 `apply_patch`/file edit 展示。

## 判定

- 源 stdio：产生了 fileChange。
- stdio raw Kafka：第二轮没有可重建输入。
- stdio→AgentRun reducer：主动抑制 `fileChange`，是首个确定丢失点。
- AgentRun durable→Kafka→HWLAB：传递的是已降维事件；不是首个根因。
- HWLAB projection：另有滞后，但不影响本次文件编辑缺失根因判定。

## 建议修复边界

- AgentRun 将 `fileChange item/started|completed` 映射为正式 `tool_call` 或 `diff` event，保留脱敏 file identity、itemId、status、changes/file count、bytes/hash 和 failure；不要保存完整 patch 正文。
- `turn/diff/updated` 应保留有界 diff summary/hash，并与 fileChange item lineage 关联。
- stdio raw topic 应提供可验证的 producer/retention 状态与按 run/session/trace 的 replay count，不能让 OTel 有 frame 而 regenerate 输入为 0 时只有 `schema-invalid`。
- HWLAB mapper/UI 在上游事件补齐后再增加 file edit/apply_patch 卡片；不能在 UI 合成上游不存在的工具事件。
