和 Claude Code 死磕 3B token 的家庭记账 APP,聊聊 vibe coding 和 spec coding 在长项目上到底差在哪
一、背景:为什么拿这么个项目来试
家里的钱散得很碎——银行、支付宝、券商、几套房、房贷,一直想要个东西能把全家资产拉成一张全局图,顺便算算真实收益。市面上的 App 要么得把全家底裤交出去,要么是逐笔流水账,都不对路。想自己写很久 ,一直没动手。
正好赶上 Claude Code 这波模型( Opus 4.8 )能力起来了。我就想,与其拿它写个 demo 玩具,不如拿个真要长期迭代的大项目来试——一个人、业余时间,看能不能扛到能上线自己家用。顺便也想搞清楚一件事 大家都在吹的 vibe coding ,放到一个要改几十上百次、半年起步的长项目上,到底扛不扛得住。
先把结论放这:vibe coding 写单个功能是真爽,但扛长项目会塌;后来逼自己上了一套 spec ,才稳住。现在大半年过去,迭代了 8 个版本,线上自己家在用。下面讲怎么塌的、后来怎么做的。
二、vibe coding 的噩梦,切换 spec
最开始就是纯 vibe:对话框里说句人话,它哗哗写,跑一下能用就合并。前两周爽飞了,后面全是债。
最坑的一类就是:“逻辑蒸发”。CC 的记忆是会话级的——这次和它一起想明白的口径、为什么某行代码长这副怪样,会话一关就没了。下次新会话它看到那行怪代码,很自信地”帮你清理一下”,bug 就这么回来了
举个例子。我让 cc 给系统支持多币种,能切换显示币种。”切成港币、美元看,收益率这种比值不该变”——这么个常识,我前后栽了三回:
第一次,SQL 里汇率换算的分支写反,美元视图数字放大七倍,改。 第二次,月支出按本位币存的、换算漏乘汇率,”紧急储备月数”这个比值跟着币种漂,改。 第三次最离谱,加了个看历史账期的筛选器,跨期换算只补了当前期、历史期没补,同一个”本月收益率”在人民币、港币、美元三个视图能差出 -18%、-9%、-88%。
前两次我都是哪个数错改哪个,改完拉倒。问题在于:我从没把”比值必须币种无关”这个结论,写到任何 CC 下次读得到的地方。所以第三次它对前两次毫无记忆,又从零踩了一遍——我自己隔了俩月也早忘了。
这次教训的经验:vibe coding 不是不能用,是它没记性,逻辑会蒸发。要么我每次新会话手动把上下文重喂一遍,要么把决策固化成它每次开局自动读到的东西。后者就是我说的 spec 。它现在不是一份文档,是三层
第一层,版本化的设计文档,放仓库里:
prd/v0.1.md … v0.8.md 用户视角:一条条 FR (用户能看到/做到什么)+ 验收基线
tech-design/v0.1.md … v0.8.md 架构选型 + 取舍(每个决策列备选 + 为什么没选别的)
docs/qa-cases.md 1451 行,每条 case 是一条可执行的验收口径
scripts/qa-run.sh 355 条黑盒断言,直接 curl 真接口、校验渲染出来的 HTML
db/migration/V1…V33.sql 版本化迁移,schema_history 记录,绝不改老迁移
规矩是:任何功能级改动,先写 PRD (我审)→ 拿静态 HTML 把页面原型搭出来(我审长相和交互)→ 写 tech-design (我审选型)→ 才动代码 + QA 。每步我不点头不许往下。改代码必须同步改这几份文档,不许”以 补”——一旦以后补,就再也不补了。
第二层,记忆,这是约束 CC 最关键的东西。 Claude Code 能给项目挂一组长期记忆,每次开会话自动加载。我攒了三十多条,分两类。project* 是项目背景,比如环境拓扑(哪台是 beta 、哪台是 prod 、prod 上的真实数据碰都不许碰,只能查不能写)。feedback* 是踩坑沉淀下来的工作纪律,这才是真正的笼子,挑几条真的:
- 改代码必须同步 PRD / 设计 / QA 三件套,别等我提醒;
- LLM 严禁做任何算术,所有数字工程代码先算好填进 prompt ,它只负责解读那段文字;
- 比值类指标切币种必须完全相等,用一条属性级断言网住整类——这条,就是上面那个币种坑踩到第三次之后我让它写下来的;
- 验收要以用户身份从首页点到底走一遍,别光 curl 接口、跑单测自我感动;
- 打 tag 、push 、发 prod 必须等我回一个精确的确认串,不许自作主张;
- UI 不许用 emoji ,一律手搓 SVG 。
第三层,skill ,把危险流程固化成带硬闸的脚本。 目前就一个:发版。发 prod 最怕手滑,我写了个 release-prod 的 skill ,流程钉死:先自动预检( git 干净、tag 不重复、跑全量测试),然后停下来等我
对话里回一个精确的 release v0.8.0(版本号必须对得上),才打 tag 、推两个 remote 、上 prod 部署、健康验证,挂了自动回滚。skill 里明文写着这道闸不许用脚本喂 yes 绕过。
三、这是我的一些思考和实践
几条踩出来的体会,每条都附一段当时的真实记录(项目里真有这些文件):
1. 决策别留在会话里,写进 CC 每次开局会读的地方。 会话级上下文一定会蒸发,长项目尤其。
踩的坑:同一个币种 bug 隔着 v0.2 / v0.5 / v0.8 犯了三次——修法从没写进它下次读得到的地方,它和我都忘干净了。 落成的:记忆
feedback_currency_invariance——「比值类指标(收益率/紧急储备/负债率/占比/MoM/YoY)切币种必须完全相等;金额类按汇率精确缩放。」
2. 每踩一个坑,当场让它写成一条记忆 + 一条断言。 坑就不踩第二次。我那三十多条记忆、几百条断言,基本全是这么攒出来的。
踩的坑:线上 AI 诊断把「股票占 34%」说成「 3.4%」——让大模型自己算占比,它算错了。 落成的:记忆
feedback_llm_no_math——「 100% 禁止做任何四则运算……所有 ¥ 金额 / % 百分比必须从 prompt 里已存在的数字原样照抄。」数字全工程算好填进去,它只解读。
3. 危险动作用 skill 加硬闸,别靠它自觉。 发版、碰线上这种,固化成带人工确认的流程,比指望模型”懂事”靠谱。
踩的坑:有次它修完直接
git tag了才问要不要 push——tag 推上去就是对外契约,出错代价大。 落成的:记忆feedback_tag_must_verify+ release-prod skill 铁律 ——「停下来等用户回精确的release vX.Y.Z……不能用脚本自动喂 yes 绕过。」
4. 改代码就得同步改 spec ,不许以后补。 文档和测试跟代码同生命周期,才不会跟现实脱节、才敢信。
踩的坑:早期改了字段/接口,但 PRD 、用例没跟,过段时间回看对不上,CC 还按旧文档干活。 落成的:记忆
feedback_doc_sync——「任何代码/数据模型/模板/UX 变更,必须同步写回 PRD / tech-design / qa-cases……不要等用户每次提醒。」
5. 验收走用户真实点击路径,别只测接口。 功能做了但用户够不着,等于没做。
踩的坑:加了个指标设置页,我验了「能打开 + 配置生效 + 单测过」,结果入口只挂在子页侧边栏、没挂到「管理」首页那面卡片墙,家里人根本找不到。 落成的:记忆
feedback_verify_user_path+ 黑盒断言v08-NAV-1——「以用户身份从首页点到终点走一遍……护栏要守用户实际入口,不是守某个等价旁路。」
四、顺便说下这系统
被这么折腾的对象叫家庭账房,自托管。不是流水账,是每月花十分钟,把散在银行、支付宝、券商、房子、房贷的钱拍张快照,然后帮你算真实年化( XIRR / TWR ,还能分清哪些是工资攒的、哪些是钱自己生的), AI 看看配置、点点风险、给个再平衡方向,只解读,不荐产品、不预测涨跌。数据只待在你自己服务器上。
@master/docs/screenshots/feature_summary_total.jpg" alt="家庭账房 · 功能总览(桌面 + 移动)" />
栈很无聊,故意的:Spring Boot 3 + Thymeleaf + HTMX + Chart.js ,没有前端构建,Docker 一键或 systemd 直装。
Demo ,假数据随便造: https://beta.dixi-token.top ( wangergou / demo1234 )
源码,Apache 2.0: https://github.com/LuoDi-Nate/financial-management
完全免费开源,没有课程,没有星球。有问题直接开 issue ,我都会回。