# 推文日报抓取预检器
## 诊断流程样例
### 输入
- 仓库根目录:`~/Documents/Codex/2026-04-21-https-github-com-haopenglau-skills/repo`
- 配置:`.claude/skills/config.json`
- 环境变量:`SOCIALDATA_API_KEY` 或 `TWITTERAPI_IO_KEY`
- 输出目录:Odyssey 推文日报目标目录
### 运行
```bash
python scripts/twitter_fetcher_preflight.py \
--config .claude/skills/config.json \
--output-dir "$HOME/Library/Mobile Documents/com~apple~CloudDocs/odyssey/twitter-daily" \
--json
```
### 核心检查
1. 读取 `skills.twitter-fetcher.users`,要求账号列表非空、格式合法、去重后数量稳定。
2. 检查 `skills/twitter-fetcher` 或正式 runner 是否存在;不存在时标记 `missing_runner`,不要自动退到 `.codex_tmp`。
3. 检查 `SOCIALDATA_API_KEY`/`TWITTERAPI_IO_KEY` 至少存在一个,并只返回 key 来源,不打印 key 值。
4. 对 provider 域名做 DNS 与 HTTPS smoke test,区分网络不可达、鉴权失败、配额问题。
5. 检查 Odyssey 输出目录存在且可写。
6. 如果 roster 缺失,只在用户传入 `--allow-fallback-roster --fallback-json <path>` 时从上一份成功产物恢复,并在结果里标记 `fallback_roster=true`。
### 成功信号
```json
{
"ready": true,
"users_count": 17,
"provider": "SOCIALDATA_API_KEY",
"runner": "scripts/twitter_fetcher.py",
"output_writable": true,
"fallback_roster": false
}
```
### 失败信号
```json
{
"ready": false,
"errors": [
{"code": "missing_config_users", "message": ".claude/skills/config.json 缺少 skills.twitter-fetcher.users"},
{"code": "missing_runner", "message": "未找到 skills/twitter-fetcher 或正式日报 runner"}
],
"next_action": "补齐 config.example 与正式 runner;如需临时恢复,显式传入 --allow-fallback-roster。"
}
```
### 落地
把日报抓取脚本改成先调用 preflight:只有 `ready=true` 才进入真实抓取;否则把错误 JSON 写入日志并停止。