# v6.3.15 AI 自动回复：通知原始上下文彻底修复

## 本次现场错误
旧版提示：
“对应频道已完整分页扫描到游标结束，仍未返回该 feed_id 的 create_time_raw”。

这证明“通过热门/最新帖子列表反查旧原帖”不能作为可靠主路径：
某些互动来自较老帖子，服务端列表窗口可能已经不再返回该帖子。

## 腾讯官方约束
- 非 OpenClaw 环境不能依赖通知自动推送的本地 #ref 上下文。
- do-comment 评论帖子需要 feed_id + feed_create_time。
- do-reply 仅用于已有评论/回复，并需要 comment_id。
- 链式操作应使用 create_time_raw（原始秒级时间戳）。
- get-notices 是互动通知读取入口。

## v6.3.15 新逻辑

### 1. 不再把“帖子列表反查”当主方案
回复上下文解析顺序变为：
1. CLI 本地 #ref（如果存在）
2. 已验证的本地 feed 上下文缓存
3. **get-notices 原始通知数据**
4. get-feed-detail 直接恢复
5. 帖子列表分页仅作为最后兜底

### 2. 支持通知 raw / ext 中的 JSON 字符串
旧版只递归 Python dict/list。
如果 CLI 把内部通知结构放在：
- raw
- ext
- 其他 JSON 字符串字段
则 create_time_raw 会被完全忽略。

本版会安全识别并解析形如 `{...}` / `[...]` 的 JSON 字符串，
再继续递归提取 feed/comment/reply 上下文。

### 3. 不盲信任何 createTime
通知里可能同时出现：
- 原帖时间
- 评论时间
- 回复时间
- 通知时间

因此本版不会把任意 createTime 直接拿去 do-comment/do-reply。

会收集最多24个候选时间，优先级：
1. feed对象自己的 create_time_raw
2. feed_create_time / feedCreateTime
3. raw数据中的 create_time_raw
4. 其他时间字段

### 4. 候选时间必须通过“只读验证”
每个候选在写回复之前先调用：
- get-feed-comments
- 或 get-feed-detail

只有腾讯接口确认 `feed_id + candidate create_time` 是有效上下文后，
才保存为 feed_create_time 并继续 do-comment/do-reply。

因此不会再次把评论时间、通知时间误当帖子时间提交。

### 5. 修复通知对象选错层级
旧版会 walk() 每一个嵌套字典，可能把 feed/comment 子对象误当成完整通知，
导致 sibling raw 上下文丢失。

本版优先选择同时包含 notice_id/msg_id + feed_id 的完整通知对象，
完整原始结构放在 `_raw` 继续参与链式解析。

### 6. 缓存
验证成功的：
`account_id + feed_id -> create_time_raw`
会进入 ai_feed_context_index。
同一个帖子后续再有评论/回复，不再重复探测。

### 7. 失败诊断
如果极少数通知确实没有任何可恢复的帖子时间上下文：
- 不向QQ提交错误写请求
- 写入 data/ai_reply_diagnostics.log
- 日志不记录 Token 或 DeepSeek API Key
- 会记录通知字段结构、候选时间数量和内部帖子/评论ID，便于精确适配

### 8. 旧失败记录
本版本首次启动会再次把历史 status=failed 的 attempt_count 清零，
让之前失败的互动重新执行新解析流程。
已有 DeepSeek reply_text 会继续复用，不会重复调用模型。

## 热更新
- VERSION 继续为 v6.3.15。
- app/updater.py / make_update_package.py / bootstrap.py /
  licensing / license_public_key / 构建脚本保持指定 v6.3.12 原文件字节级不变。
