AI复利手记

WORKFLOW · 工作流

机器管每天,人管判断,会话管建设

医械HOT 采集、打分、出报,每天 08:30 自动同步推送上线;收藏在 /admin 在线运营;站本身的三次大改版都是 AI 编程会话完成的。这一页写它现在怎么转,以及建设路上摔过的跤。

这条链路 2026-10-04 才接通,之前是另一条跑了半个月的 AI 新闻管线(已退役)。所以下面写的是它每一步怎么接起来的、建设过程里摔过哪几跤,而不是「最佳实践」。等它跑满一个月,这一页会重写一遍。

PRINCIPLES · 三条原则

先立标准,再看内容

01

机器管每日,人管判断

每天必跑的(采集、同步、构建、部署)全部无人值守;要不要收一条链接、一篇手记怎么写,留给人。两边各干各的,谁也别替谁。

02

建设交给 AI 会话

这个站的三次大改版 —— v2 全站落地、收藏接入数据库并上线、日报切换医械HOT —— 都是 AI 编程会话完成的。人负责验收和决策,会话负责实现与排障。

03

数字可核,出事先留证据

页面上的每个数字要么来自数据库实查,要么注明核对日期;故障先取证再动手 —— 下面三个坑的每条证据都有日期和字节级细节,不写「偶尔会挂」。

PIPELINE · 链路

整条链路长这样

  1. 01
    采集
    Collect

    16 个源 → articles 表

  2. 02
    事实化与打分
    Rank

    articles → facts / stories

  3. 03
    出报
    Report

    facts → reports 表

  4. 04
    同步
    Sync

    reports 表 → daily.json

  5. 05
    发布
    Ship

    daily.json → Vercel 部署

  6. 06
    运营
    Operate

    /admin → Turso → 前台实时

采集、打分、出报、同步、发布五环全自动,每天的 08:00–08:35 之间自己跑完; 运营那环留给人。每一层的输入输出都固定,换掉任何一层不会牵动其他层。

STAGES · 六个环节

每个环节到底在干什么

01

采集

医械HOT 盯住 16 个信源 —— 药监局、器审中心的官方发布页加行业媒体 —— 抓回来的文章连同正文、发布时间、来源一起落进 PostgreSQL。

  • 已累计采集 284 篇(2026-10-04 核对),字段里发布时间和采集时间分开存,混在一起新鲜度会算错
  • 数据库和站点是两个独立项目,凭据只存在医械HOT 的 .env 里,不进任何仓库
  • 采集失败的源当天空缺就空缺,不拿旧数据顶 —— 国庆假期连续几天 0 收录,日报照实出空档
02

事实化与打分

文章被抽成一条条「事实」(谁、做了什么、何时),关联到事件线上;热度和来源性质(官方一手 / 行业)参与打分。

  • 医疗器械领域里,「是不是官方一手」比「几个源在报」更关键 —— 站上日报的红灰方块就取自这个字段
  • 同一事件的多篇报道聚到一条 story 上,不聚会天天重复收录
03

出报

每天 08:00,模型把窗口期内的事实汇成一期日报:一段导语加按类分组的条目,写回 reports 表。没有内容的日子就出一期空档,不硬凑。

  • 导语是当期的综合判断,正文条目带精确发布时间 —— 时间是抓到的真值,不是反推的
  • 报告只增不改:修订走 revision,出了错能追到是哪一版
04

同步

每天 08:30,Windows 计划任务跑同步脚本:读医械HOT 的 PostgreSQL,固化成站点仓库里的 daily.json。

  • 流水线刚起跑时每天生成的空骨架日(无条目也无导语)自动跳过,不然归档里会躺一排「当日无头条」
  • 显示用的时间标签在同步期按上海时区固化,页面端不做任何时区换算 —— 避免 hydration 期服务器和浏览器算出两个值
  • 数据库没在跑就静默退出,不动仓库,第二天接着来
05

发布

daily.json 有变化才 commit + push;GitHub 通知 Vercel 自动构建,1~2 分钟后新版上线。没变化就什么都不发生。

  • 「有变化才推」是脚本里显式判断的 —— 每天一次空提交会让部署历史没法看
  • Vercel 上的环境变量(数据库连接串、管理密码)先配好才推代码,顺序反了线上会挂
06

运营

收藏不进这条自动链 —— 126 条书签存在 Turso 云数据库,/admin 里密码登录直接增删改,前台实时生效,全程不碰代码、不碰部署。

  • 单管理员密码 + HMAC 签名 Cookie,没有注册体系 —— 个人站不需要用户表
  • 首次访问自动建表播种,本地 SQLite 和线上 Turso 走同一套代码,只差一个连接串
16
个信源
官方站 + 行业媒体,医械HOT 盯着
284
篇已采文章
医械HOT PostgreSQL 实数快照
125
条收藏
/admin 在线增删改,实时生效
8
天连续更新
累计 18 条进过日报

PITFALLS · 踩过的坑

建设过程中摔的 3 跤

01

磁盘在悄悄写坏文件

构建报「文件是二进制」「stream did not contain valid UTF-8」。起初以为是依赖坏了,重装后换一批文件继续报 —— 损坏根本不在代码里。

当时的证据

2026-10-04 排查:daily.ts 在第 4094 字节、markdown.tsx 在 4096、notes.ts 在 4098 —— 三份没动过的源文件全部在 4KB 边界被写入垃圾字节;两张 PNG 被清零;.git 的 index 截断、多个对象文件为空。这是磁盘级的损坏,不是提交出来的。

现在怎么防

远端仓库当唯一真身:npm ci 重装依赖,从 GitHub 克隆一份,用好文件覆盖损坏文件、整个换掉坏掉的 .git,再 chkdsk 检查磁盘。恢复后 fsck 全绿、构建一次过。教训:重要工作当天就要有远端提交。

02

同一个仓库连了两次 Vercel

环境变量加好了、代码推上去,线上首页却读不到数据库。检查才发现:GitHub 仓库被导入成两个 Vercel 项目,正式域名挂在 A 项目,环境变量加在 B 项目。

当时的证据

2026-10-04 处理:项目列表里 web 与 ai-coupon-platform 连着同一个仓库;aideals.me 及其跳转都在 web 名下,而 DATABASE_URL 和 ADMIN_PASSWORD 在 ai-coupon-platform 里 —— 两边各对一半,合起来必挂。

现在怎么防

动代码前先理清单一:把 www 与 apex 域名都转到正确的项目(apex 顺带配成 307 跳 www),删掉重复项目,环境变量确认就位之后才 push。顺序错了就是一次可预见的事故。

03

错误被包在 cause 链里,顶层看不到

重复 URL 新增书签,接口该返回 409「已收过」,实际却 500。测试环境里一切正常,唯独这个分支炸。

当时的证据

2026-10-04 实测:libsql 抛的 UNIQUE 约束错误被 Drizzle 包了一层,顶层错误对象的 message 只有 SQL 文本,用 String(e).includes("UNIQUE") 永远匹配不上 —— 真正的错误码在 e.cause.cause 里。

现在怎么防

判断约束冲突沿 cause 链逐层找错误码(message + code 一起查),不信任顶层的字符串。修完同一请求返回 409,管理台能给出「这个 URL 已经收过了」而不是一屏红字。