定时触发
GitHub Actions · 21:37 美东 ×2
1定时触发
.github/workflows/daily-digest.yml
触发点已经搬到云端:GitHub Actions 用两条 cron 分别在 UTC 01:37 与 02:37 唤醒——换算成美国东部时间,夏令时、冬令时都落在 21:37,瞄准的是纽约当地 21:00 前后;选在 37 分而非整点,是因为整点是共享 runner 最拥挤的时段,错峰几十分钟能让实际派发更准时。即便如此,GitHub 的定时任务仍常常晚点,这两条实际经常在纽约午夜之后才真正跑起来;工作流里专门写了一道判断——先看今天的 digests/<date>.json 是不是已经发过:发过了就跳过,让另一条 cron 白跑一场当备份;没发过,哪怕已经过了午夜,也照样往下走、生成"新的一天"这一期。这种晚点是预期之内、被工作流本身接住的,不是故障。Zen 笔记本上原来的 launchd 定时任务(com.zen.daily-digest · 20:57 本地时间)还留着,但降格为兜底,且被限定只能出预览,从不碰生产环境。
为何这样设计云端定时不再依赖笔记本电脑是否开机联网,这正是把流程搬上云的初衷——本报才配得上“每晚必到”四个字。
唤起编辑部
claude -p · 云端无头
2唤起编辑部
daily-digest.yml → claude -p
工作流以无头模式(claude -p --dangerously-skip-permissions)在 GitHub Actions 的一次性容器里唤起 Claude Code,读的是 automation/ci-prompt.txt——这是同一份 /daily-digest 技能说明的云端版,只补上云端特有的限制:没有登录态的浏览器,只能扫 YouTube 与文摘两条无头带,X/小红书直接跳过。先用 Sonnet 生成一次,若失败(常见诱因:当晚扫到的安全类新闻触发了模型自身的安全判断,直接拒答)就升级到 Opus 重试两次。
为何这样设计这一步确实带着 --dangerously-skip-permissions 唤起,读起来像不设防——但它能碰到的东西被环境本身圈死了:这一步的环境变量里只有一把用来生成文字的 API key,看不到任何能把内容送上生产环境或对外发消息的密钥(Vercel、Telegram、DeepSeek、Supabase 的 token 都不在这一步的环境表里),它写得出的只是这次运行检出的代码树里的一份 digests/<date>.json。真正握着部署密钥、能把东西送上线的,是紧接着单独跑起来的发布步骤(第9-10步,见06版)。编辑部正在做的下一步,是把生成和发布彻底分居两个互不预热的检出环境,并让生成产物先过一轮字段白名单与 schema 校验,才轮到带着部署密钥的发布步骤登场。
扫读两带
headless × 2 ・ enrichment × 2
3扫读 · 常驻无头双带
YouTube ・ 文摘/Digest
YouTube(9 频道)
通过 RSS 抓取近 48 小时更新,长视频用 yt-dlp取全文转录,由编辑部代读——Zen 不必自己看完每一条长视频。
frontier: Karpathy / Anthropic / OpenAI / Dwarkesh builder: AI Engineer / Latent Space pm-strategy: Lenny's / No Priors curator: Zara Zhang
文摘 / Digest(5 源)
全部走 RSS / 前端页面,headless 可达,不依赖任何登录态——正是这条带的存在,让 9 点无浏览器的自动跑也能凑齐“≥2 来源平台”,几乎不必触发 partial。
Hacker News (front page) ・ Import AI ・ TLDR AI ・ Latent Space(newsletter)・ Simon Willison
为何这样设计YouTube + 文摘两条带都不需要浏览器登录态,是“打不开 Chrome 也能成报”的底线保证。
4扫读 · 选配增强带
X ・ 小红书 · 需要 Chrome,可跳过
X(选配增强)
已登录的 x.com 时间线 + 逐账号页面,用 get_page_text读取推文正文与互动数。仅当 Chrome/claude-in-chrome 可用时才尝试;无头跑通常会跳过。
karpathy ・ simonw ・ swyx ・ bcherny ・ zarazhangrui ・ AnthropicAI ・ OpenAI
小红书 / XHS(选配增强)
同样依赖已登录的浏览器会话,一旦不可达即跳过,不影响成稿——只要 YouTube + 文摘两条底线带已经达标。
⚠ 这两条带明确标注为“可选增强”:能扫到就更丰富,扫不到不拦发布。
提炼成稿
择要 · 去重 · 加料
5提炼
编辑部对当晚扫到的所有条目择要,跨平台去重(一事一处,同一件事在多条带出现时择强合一),归纳出“今日可行动”的具体动作项,并写一段本报社评。
6加料
在正文之外再加四样:头版要图;“今日上手”——一件今晚就能试的具体小事;编辑部 OTA 自我升级(今日所学 + 新增能力);以及全字段的 _en双语版本,供中英切换按钮读取。
为何这样设计本报每天真正“学习”的不是读者,而是 Zen 的 Claude Code:每期 OTA 先读 ota-ledger.md 台账,挑一个建立在昨日之上、不重复的能力落地实现,再追加回台账——能力逐日复利。选题也偏向 AI 的应用 / GTM / 产品面,因为那正是能直接迁进 Zen 工作的部分。
7成稿
digests/YYYY-MM-DD.json
编辑部把当晚的所有内容写成一份 digests/<date>.json,并把这一天追加进 digests/index.json索引——首页正是靠这份索引找到“最新一期”和“往期合订本”里的每一天。
8◆ 质量闸门bin/validate-digest.py · docs/STYLE-ZH.md
发布前,bin/publish.sh 会先跑 bin/validate-digest.py做两重校验:来源多样性,防止一期报纸只靠单一来源撑起门面;反重复,防止同一个链接、同一位作者在报上连轴转。
| 门槛 | 要求 |
| 来源平台数 | ≥ 2 个不同 platform(各至少 1 条) |
| 总条目数 | ≥ 4 条 |
| 链接不重复 | 近 7 期出现过的 URL 不得再上报(发布时硬闸,历史期修订仅提醒) |
| 来源不扎堆 | 同一非平台域名一期至多 1 条(YouTube 等平台域除外) |
选题之外还有文风:docs/STYLE-ZH.md 是本报的中文文案守则,由五个前沿模型联席评审定稿(2026-08-04:Claude 主笔,DeepSeek、Kimi、GPT、Gemini 各自独立重写后匿名互评,主笔裁决合稿)——事实数字一字不差是红线,公文腔、翻译腔、标题党皆不许上版。每晚生成与润色都逐条对照这份守则。
- 达标 → 正常发布,闸门放行。
- 不达标但真的只够 1 个平台(例如纯无头跑,YouTube 都没扫到东西)→ 顶层字段 "partial": true → 首页顶部带出“⚠ 本期部分来源缺席(无头运行),稍后补全”的横幅照常发出,留待下一次交互式运行补全。
- 既不达标、又没设 partial → 发布被直接拦截,退出码 1。
发布晋级
质量自检 → 自动上线 / 留人工复核
9质量自检 · 自动上线
bin/ci-publish.sh → bin/quality-check.py
多样性闸门放行后(第8步,见05版),ci-publish.sh 先渲染出当期头版长图,再跑 bin/quality-check.py——比多样性闸门更高一道门槛:条目数、行动数、摘要长度、图片与 OTA 字段是否齐全。过了这道门槛,脚本直接执行 vercel deploy --prod 把当期送上 mrqb.space,同时把生成结果提交回仓库、发出邮件,并把 Telegram 头版长图发给 Zen——绝大多数晚上,上线这一下都是自动完成的,不等 Zen 醒来点头。
为何这样设计仓库本身没有跟 Vercel 做 Git 集成,生产环境只能靠这一步握着的 VERCEL_TOKEN 部署——这一步不跑,不管前面生成了什么,都碰不到生产环境。
10没过自检,才轮到人工
没过质量自检的当期,脚本改去发一份 vercel deploy 预览,把生成结果提交为草稿,再把预览链接和一张“未达标”的头版长图一并 Telegram 给 Zen——这时才需要 Zen 亲自看一眼预览、判断是否手动把它 promote 到生产环境。全流程里唯一常态化保留的人工步骤,就是这个“没通过才需要你”的例外分支;正常的晚上它根本不会被触发。
为何这样设计把“人工把关”从每晚的必经流程改成只在自检不通过时才出现的例外,报纸才谈得上真正的“每晚必到”。
◆ 继续读下去Where To Next
这篇特稿只讲流程本身。想看流程跑出来的实际内容,请翻
今日头版,或去
往期合订本翻阅此前每一期。
流程最后核对日期:2026-08-04(对照
.github/workflows/daily-digest.yml 与
bin/ci-publish.sh 逐行核实)。