# ARR1 历史文档 — Super Agent 结果回写与业务落库合同

> 仅作兼容与迁移审计。ARR2.0 没有 Agent 回调路由，本地工件直接进入通用 `DeliveryEnvelope` 验证边界。

更新时间：2026-07-28

## 结论

业务系统已提供机器回写入口：

```text
POST /api/integrations/super-agent/results
Content-Type: application/json
```

请求体必须符合 `prompts/arr_opera_daily_processing_result.schema.json`，并由受信任的 Agent runtime adapter 使用独立 HMAC-SHA256 密钥签名。普通聊天文本、Agent 本地路径、未签名 JSON 或仅有 `run success` 的状态都不会入库。

## 完整链路

```text
业务任务已登记并绑定 remote_run_id
  -> Agent 从 OSS 获取源 XML 并执行 arr-opera-daily-ingest
  -> runtime adapter 校验 FROZEN_AGENT_RESULT 的输出目录
  -> 将日报 / result.json / structured-result.json / 异常清单发布到 OSS 交换前缀
  -> 生成稳定 file_handle、delivery_id 和签名回调
  -> ARR 验签并核对 job / attempt / remote_run
  -> 从 OSS 重新读取每个产物，重算 SHA-256 和大小
  -> ARR 独立 validator 重放业务规则
  -> PostgreSQL SERIALIZABLE 事务写 ingestion + finance
  -> 最后切换 current_daily_versions
```

输入方向是 ARR 代码直接上传 XML，把 committed 源对象设为 `public-read`，然后在 Agent message 中传入一个 `oss_attachments` 描述对象。对象包含 bucket、public endpoint、object key、ARR 生成的无签名 HTTPS URL、哈希、字节数与任务 ID；`fetch_oss_file` 原样读取该公网 URL，不使用 OSS Provider。ARR 的写入 AccessKey 只存在 ARR 进程中。

结果方向采用 runtime 主动回调，不依赖 Open API 的 `final_content`。后者在真实服务上可能为 `null`，也无法让 ARR 读取 Agent 沙箱的本地文件。

Agent 和 Super Agent 不持有 PostgreSQL 凭据。数据库写入只发生在 ARR 后端。

## ID 对应

- `job_id`：`ingestion.processing_runs.run_key`，由业务系统创建任务时生成。
- `attempt_no`：`ingestion.processing_attempts.attempt_no`，同一任务重试递增。
- `remote_run_id`：该 attempt 绑定的 Super Agent Run ID。
- `delivery_id`：runtime adapter 按 job / attempt / remote run 稳定生成；重复发送同一 delivery 幂等。
- `file_handle`：只解析为 `ARR_AGENT_OUTPUT_PREFIX/<file_handle>`，不能携带 URL、OSS key 或本机路径。
- `source_file_id`：只用于 Agent 取源文件，不进入 Finance 事实表。

## 成功与失败

- HTTP `200`：结果已提交，或同一 delivery 已提交；响应 `data` 含 `status`、`job_id`、`business_date`、`daily_version_id`、`version_no`、`callback_replayed`。
- HTTP `401`：签名错误、密钥 ID 不匹配或签名过期；不得盲目重试。
- HTTP `404`：job / attempt 不存在；先修复任务登记和 ID 关联。
- HTTP `409`：delivery、run 或现有任务状态冲突；必须人工核对身份。
- HTTP `422`：Schema、文件身份或独立业务验收失败；不得写 Finance current 事实。
- HTTP `503` / 网络失败 / `408` / `429`：使用完全相同的签名请求体有界重试。

Agent 的业务失败也可以回写，但只记录失败 delivery、工件和安全错误，不会创建或激活日报版本。

## 运行配置

业务后端需要：

- `booking-test-db.env`：当前远程 `booking_test`；
- 本机 LaunchAgent 可把下列回写变量放在 `/path/to/private/agent-writeback.env`；该文件必须为当前用户所有的普通文件且权限为 `0600`；
- `ARR_AGENT_RESULT_HMAC_KEY_ID`、`ARR_AGENT_RESULT_HMAC_KEY_B64`；
- `ARR_OSS_REGION`、`ARR_OSS_ENDPOINT`、`ARR_OSS_BUCKET`；
- `ARR_OBJECT_PREFIX`、`ARR_AGENT_OUTPUT_PREFIX`；
- OSS SDK 的 RAM/STS 凭据环境变量。

HMAC 密钥不能复用 `DEERFLOW_OPEN_API_KEY`。本集成要求 OSS bucket 为用户确认的 `public-read`、配置服务端加密并保持 versioning Off；`private` 与 `public-read-write` bucket 都会被 readiness 拒绝。只有 committed 源 XML 显式设置 `public-read` ACL，暂存对象和处理输出显式设置 `private` ACL。

本机部署把 OSS AccessKey、Agent Open API key 和回调 HMAC 保存到 macOS 登录钥匙串，`agent-writeback.env` 只保存非敏感路由。LaunchAgent 固定使用 Keychain account `arr-web`，读取的 service 分别为 `com.chillishark.arr.oss-access-key-id`、`com.chillishark.arr.oss-access-key-secret`、`com.chillishark.arr.deerflow-open-api-key` 和 `com.chillishark.arr.agent-result-hmac`；任何交接文档、日志和项目文件都不得写出实际值。

当前本机 launchd label 仍为历史名 `com.chillishark.opera-arr-report`，实际 launcher 仍位于旧项目路径，但启动的是本项目 `arr_web.run`。后续应将 launcher/日志迁入目标项目或独立部署目录，避免路径归属混淆。

业务后端启动：

```bash
.venv/bin/python -m arr_web.run \
  --host 0.0.0.0 \
  --port 8765 \
  --db-config /path/to/private/booking-test-db.env \
  --enable-agent-writeback
```

Agent runtime 在 Skill 已完成并产出 `FROZEN_AGENT_RESULT` 后执行：

```bash
.venv/bin/python -m arr_processing.runtime_writeback \
  --frozen-result /isolated/output/frozen-agent-result.json \
  --output-root /isolated/output \
  --attempt-no 1 \
  --remote-run-id run_xxx \
  --processor-version 3.0.0 \
  --rule-set-sha256 <当前64位规则哈希>
```

`GET /api/health` 只有在数据库与 OSS/HMAC 装配都成功时才返回 `agent_writeback_ready=true`。该字段是“结果能真实落库”的运行门槛，而不是以代码存在或 Agent 能聊天来代替。

## 当前验证

- OSS SDK V2 adapter、前缀隔离、条件防覆盖和 versioning fail-closed 已有自动化测试。
- runtime 发布、HMAC 签名、同请求体重试和回调响应解析已有自动化测试。
- fake Agent -> 真实 Skill -> ARR 独立复验 -> 原子落库的全链路测试通过。
- 当前远程测试库已用合成 DeliveryEnvelope 完成幂等重放，表计数未增加重复数据。
- 真正线上竖切仍需注入实际 OSS region / bucket / RAM(STS) 与独立 HMAC 后执行一笔无隐私测试任务。
