
前情提要: 上一季造了 OPC——一个人的 AI 工程团队。核心机制三条:
- 做的人不评自己。 AI 写完代码后,由另一组独立 AI 审查——安全审查者不知道实现细节,测试审查者不看实现方案。每个审查者在独立上下文中工作,没有”碍于面子放你一马”这回事。
- 机械门禁。 审查结果用 emoji 机械计数——🔴 = 严重,🟡 = 警告。数数,不做判断。门禁不关心”我觉得可以”,只关心红色和黄色的数量。这是 S1 最核心的信任设计:最后一关不能交给 AI 的主观判断。
- 循环直到过关。 plan → build → test → review → 门禁。门禁不过就循环回去改,过了才进入下一个节点。整条流水线是一个有向图,不是线性脚本。
这三条合在一起:AI 能写代码,但不让它自己说自己写得好;质量判断用机械规则而非 AI 判断;不达标就打回去重做。信任不是给予的,是约束出来的。
一次 OPC 执行的流程:人定方向 → OPC 拆任务 → AI 写代码 → 独立 AI 审查 → 机械门禁 → 不过就回去改,过了就继续。整个循环可以无人值守地反复执行,一个循环周期叫一个 tick。
这一季把它拉上战场。S1 造了机器,S2 用机器做产品——但每个产品都暴露机器的短板,短板倒逼升级,升级后再做下一个产品。螺旋往上转:
- EP01-02:用机器做两个产品,发现方向决策和停机问题
- EP03:审查全过不是好事——加角色来挑刺
- EP04:升级之前先看别人怎么做
- EP05-06:核心代码发胖——拆出扩展系统,装上设计审查员
- EP07-08:看不到过程就不能信结果——让过程可见,再用工具审自己
S1E10 讲了五个”人必须介入”的信号——方向跑偏、上下文溢出、协议拒绝、环境崩溃、循环停不下来。那是事后的归纳。S2 是正面经历这些信号的过程,以及每次介入之后工具链怎么长出新的能力。
产品暴露工具的短板,短板驱动工具的进化——这是 S2 的主线。不是一套可复制的方法论,是一个人的演化实验,所有数据都是 N=1。
“做个家庭日历,家庭成员登录,图片/语音/文字输入,大模型解析,通知提醒。”
一句话需求。没有 PRD,没有设计稿,没有竞品分析。就这一句话,我扔给了 OPC loop(一个自动化的 AI 构建流水线——AI 智能体按 plan → build → test → review 的循环自主执行任务)。
两天后:
- 23 小时 9 分钟 AI 执行时间
- $92 API 费用(Claude Opus,95% 缓存命中(cache hit)——长会话的关键,后面会讲)
- 44 个子智能体(subagent,每个是一次独立的 AI 智能体调用),35 个 git commit
- 103 个 vitest 单元测试 + 52 个端到端测试(E2E)全通过,tsc 零报错
一个能跑的家庭 AI 日历最小可行产品(MVP)站在屏幕上。但这个过程一点都不顺利。
第一天晚上:AI 的默认选择
OPC loop 接到需求后,AI 搭了 Next.js 14 + Vercel Postgres + NextAuth + Web Push 的骨架。选型没问题。
前端出了问题。第一版交付的主界面是一个标准的月视图日历网格(Calendar grid)——周一到周日表头,格子加事件,点格子弹出事件表单,增删改拖拽一应俱全,测试全绿。S1E10 讲过这个方向翻转的故事:我凌晨两点一句”主界面应该是 agent feed”推翻了 21 个 tick 的工作。这里不重复那个故事——重要的是 AI 为什么会做这个选择,以及为什么这个选择是错的。
这个产品给谁用?我的家人。家人打开手机想看到的是”今天有什么事”——不是一个 Google Calendar 克隆。他们不会每天主动点开一个日历网格查看,就像没有人会每天主动去看墙上的纸质日历一样。家庭日历的核心问题不是”事件存在哪”,而是”为什么家人每天愿意打开这个 app”。Calendar grid 回答了第一个问题,完全没触及第二个。
AI 选训练数据里最常见的界面模式(UI pattern)。 “家庭日历” → Calendar grid,大概率是训练数据中最常见的关联。功能上没错,方向上全错。需求说”做个家庭日历”——AI 正确执行了一个模糊的 spec。两件事同时成立:需求本身不够具体,AI 的默认选择需要人来校准。如果需求一开始就写”主界面是推送流,不是日历网格”,AI 不会走弯路——但写出这句话本身就需要产品判断力,这恰恰是 AI 不具备的。
产品方向只能人来定。AI 执行计划,不生成计划。
重建:智能推送流(Agent Feed)
新的主屏设计:今日概览(HeroHeader)+ AI 主动推送的提醒卡片(AgentCardList)+ 今天的任务(TodayTaskList)+ 未来几天预览(UpcomingChips)+ 快速输入栏(FabBar)。
不再是人去查日历,而是日历来找人。
图片和语音输入也搭好了——但这篇的重点是方向决策和产品打磨的故事,多模态输入的技术细节留给以后。
13 个 OPC 任务并行/串行执行,35 个 commit 在循环中自动提交。中间出了一个典型问题:FabBar 的端到端测试(E2E)直接调用了真实的 Claude 接口——写测试的智能体不知道”这不是一个测试,这是一个祈祷”。审查智能体在代码审查轮次发现了问题,改成 page.route() mock。这就是”做事的智能体不能评价自己做的事”——写端到端测试的智能体不会质疑自己的选择,因为在它的上下文里,调用真实 API 和 mock API 都能让测试通过。区别只在于:前者让你的测试结果取决于一个第三方 API 的心情,后者让你测到你真正想测的东西。这种区别需要工程判断力,审查智能体在独立上下文中才能看到写测试的智能体看不到的盲区。
LLM Pool:够用就好
家庭日历用 LLM 解析自然语言输入(“周六下午带妈去看牙”→ 结构化事件)。单一提供商(provider)不够可靠——任何一家 API 都可能限流、宕机或临时维护,对家庭产品来说”解析失败请稍后重试”就等于”这东西不好用”。需要回退机制(fallback)。最终实现:135 行 TypeScript,零外部依赖,三个提供商按优先级自动切换——Anthropic Opus → Anthropic Sonnet → DashScope Qwen。第一个失败自动切到第二个,第二个失败切第三个。全链路失败时报每个提供商的具体原因,而不是一个笼统的”服务不可用”。
代码里没有一个 any,没有用 LangChain。为什么不用 LangChain?因为 LangChain 为这个场景带来的是抽象层的复杂度而不是价值——3 个提供商的线性回退链,一个 for 循环就能搞定,不需要一个框架来帮你”管理”它。对一个家庭产品来说,硬编码回退就够了——不需要注册中心、不需要插件系统。这是 YAGNI(不提前构建不需要的东西),不是架构信仰。等提供商需要加到第 4 个的时候,再抽象也不迟。
设计语言:从 Dashboard 到家庭产品
功能就绪后我第一次全屏查看——感觉不对。
Tailwind 的默认样式让它看起来像一个管理后台(admin dashboard),不像一个每天要打开的家庭产品。功能上没问题,信任感不够。打开一个 app,不到一秒就能感觉到”这是认真做的”还是”这是凑合做的”。这不是玄学,是视觉系统的一致性给人的潜意识信号。管理后台可以长成管理后台的样子,因为用它的人是被逼用的——但一个家庭产品必须让人愿意打开,而不是能打开。
引入了 Apple 风格的设计令牌(design token)系统:CSS 变量体系(accent color、三级 label 层级、4pt spacing grid)、backdrop-blur-xl 毛玻璃效果、dark class 手动切换暗色模式、Spring 弹性动画曲线。
无障碍的墙
Apple 风格引入了一个连带问题:WCAG 对比度。
Apple 的 secondary label 用的是 rgba(60,60,67,0.36)——对比度只有 1.7:1,远低于 WCAG(Web 内容无障碍指南)AA 标准(4.5:1)。更糟的是:axe-core(无障碍扫描工具)在半透明颜色叠加多层背景时算不准对比度,会出现误报和漏报。误报意味着你以为有问题的地方其实没问题,浪费时间去修;漏报意味着真正有问题的地方被放过了,上线后才被用户发现。两种情况都在破坏你对自动化工具的信任。
最终方案:文字 token 全部改 solid hex(#6e6e75 替代 rgba(60,60,67,0.36)),rgba 只保留给装饰性元素(背景模糊、阴影)。视觉上文字颜色变深了一些(从 1.7:1 到 4.65:1),但可读性大幅提升,axe-core 也能正确计算了。这个取舍的本质是:宁可牺牲一点 Apple 原版设计的”朦胧感”,也要确保工具链能可靠地守住无障碍底线。
无障碍不是加分项,是底线。 家人中可能有人视力不好。如果他们看不清界面文字,这个 app 对他们来说就是废品。
暗色模式的无障碍测试是审查智能体在代码审查时补的,不是一开始就有的。如果无障碍真的是底线,它应该出现在最初的规格里。这是需要改进的地方。
两天的账
$92 是 API 费用,不是全部成本。我自己花了大约 3-4 小时做方向审查、设计决策和质量把关——如果按资深工程师(senior engineer)的市场价算,这部分的机会成本是 $200-$600。所以真实成本大约是 $300-$700,取决于怎么给自己的时间定价。
95% 的缓存命中率是长会话的命脉——115M 词元里有 109M 是从缓存读的,这得益于 OPC 循环的长会话架构。为什么缓存命中率这么重要?因为 OPC 循环中每轮迭代都要把整个项目上下文重新送给模型——输出词元虽然单价更高,但输入词元的体量远大于输出,所以总账单的大头是输入侧。如果每次都按全价计费,23 小时的执行时间会产生 $276-$460 的 API 费用。长会话让模型能复用之前的上下文缓存,把输入成本压缩到原来的五分之一。短对话模式下缓存命中率会低很多,API 费用会接近那个上界。这些数字都是这一次运行的结果,不是可复现的基准——换一个需求,换一次 session,数字可能差很远。
从产品角度看:一个全栈 app,OAuth(开放授权)登录,三路大语言模型回退,Apple 风格 UI,暗色模式,渐进式网页应用(PWA)通知,无障碍达标,全覆盖测试。完美吗?不算——LLM Pool 的 require() 是技术债,暗色模式无障碍是后补的。
部署到 Vercel 后还没有真正给家人用起来。103 个测试全绿、tsc 零报错——技术指标全过了,但从 MVP 到真正被人日常使用之间,还有一段没走完的路。测试能验证功能正确,但不能验证家人是否愿意每天打开它。
OPC 循环提供的不是完美,是在两天内从一句话变成一个能跑的应用的执行力。方向必须人来定,标准必须人来守。这两件事之间的执行工作,在这个案例中 AI 的交付速度远超手动编写——但前提是方向没有跑偏。EP01 的方向就跑偏了一次,21 个 tick 的工作被推翻重来。这是最贵的一课:方向错了,执行力越强,浪费越大。AI 不会叫停自己。
硅基团队 S2: 在实战中进化工具链 ← S1E11: 翻车之后怎么办 | S2E02: 40 个 Tick 推上线 →