这不是一份“AI 很强”“Rust 很严格”的感想录,也不是开发流水账。
这份文档只回答 3 个问题:
- 如果想主要靠 vibecoding 把一个 Rust 项目做出来,开始前到底要准备什么。
- 在这个仓库里,哪些工程约束是真正救命的,少了会立刻失控。
- 这次实际踩过哪些坑,后面如果再做一次,哪些地方必须提前规避。
先说结论:
Rust 项目可以大量用 vibecoding 做,但前提不是“AI 一直写”,而是“你先把项目变成一个有边界、有门禁、有回滚点的系统”。
如果没有这套系统,AI 写得越快,项目只会越快跑偏。
如果要全程 vibecoding,这个仓库里真正有价值的,不是 AI 一次写了多少行,而是下面这些基础设施先落好了。
这个仓库里先固定的是:
- Rust toolchain:
1.94.1 - 组件:
rustfmt、clippy、rust-analyzer、rust-src、rust-docs - 扩展工具:
just、cargo-nextest、cargo-llvm-cov、cargo-deny - 性能辅助:
cargo-sweep、sccache、cargo-watch、mold
对应文档和入口已经在:
为什么这一步这么关键?
因为 AI 最怕的不是不会写,而是在不同机器、不同版本、不同命令结果下继续沿着错的方向写。
如果工具链不固定,AI 看到一次能过、下一次不过,就会开始“补丁式”修复,最后把项目修成一团偶然成立的东西。
这个仓库最重要的不是“有测试”,而是验证入口已经提前统一:
just env-checkjust verify-basicjust verifygit diff --check
这是 vibecoding 里最容易被低估的一步。
如果没有这套命令,AI 每次说“应该好了”时,你根本没有一个统一的裁决标准。
在这个项目里,真正有用的经验不是“多写测试”,而是:
- 先定义哪条命令代表“基础可交付”
- 再定义哪条命令代表“完整门禁”
- 然后所有完成声明都以这两条命令为准
没有这个前提,AI 会持续输出“语义上像完成、工程上其实没完成”的结果。
这个仓库里最容易被忽略、但其实非常有用的是 Git hooks:
pre-commit:拦cargo fmt --all --checkcommit-msg:拦提交标题格式pre-push:拦just verify-basic
路径在:
vibecoding 最大的风险之一,是你以为“先 commit 再说”。
但如果 hook 已经在仓库里,AI 和人都会被迫接受同一套节奏:
- 先格式化
- 先保证提交标题规范
- 先过基础门禁
- 然后再允许进入 Git 历史
这会显著减少“先提交一个半成品再慢慢补”的坏习惯。
如果是手工开发,很多边界可以放脑子里。 但如果是 vibecoding,脑子里的边界不算边界,写进仓库里的边界才算边界。
这个仓库里真正发挥控制作用的文档,不是 README,而是这些:
- AGENTS.md
- migration-strategy.md
- module-map.md
- invariants.md
- acceptance-matrix.md
- project-completion.md
这些文件的作用不是“写给别人看”,而是防止 AI 把项目目标自行脑补成另一个东西。
最容易失败的方式是上来列一堆功能:
- 抓取
- 通知
- AI
- MCP
- 多领域
- 多输出
- 多存储
这会让 AI 默认把项目理解成“功能填空题”。
更好的方式是先定义阶段:
- 当前阶段只做主链路闭环
- 当前阶段只做真实运行、真实日志、真实验证
- 当前阶段不追 Python 100% 对齐
- 当前阶段做完后进入维护模式
阶段比功能列表更重要,因为它定义了什么可以不做。
如果让 AI 同时做太多事,它会天然开始顺手扩 scope。
这次项目里,多次出现过这种倾向:
- 本来只是改日志
- 顺手改输出模型
- 顺手改过滤逻辑
- 再顺手改文档和示例配置
最后一次提交虽然看起来“很完整”,但中间如果不持续校准,很容易从单一任务膨胀成半个里程碑。
更稳的规则是:
- 主目标:这轮真正要交付的东西
- 副目标:允许顺带完成的一类小修
- 超出这两类,一律下轮再说
如果要 vibecoding,推荐固定为一条机械流程:
- 先找边界文档
- 先看现有测试/fixture
- 先补失败测试
- 再写实现
- 再补示例配置或运行入口
- 再改文档
- 最后跑统一验证
这条链不是仪式感,而是为了防止 AI 先把代码写散,再补文档和测试时已经收不回来了。
这次项目里一个很典型的问题就是:
- 本地 fixture 跑通了
- 但用户问的是“真实抓取今天新闻”
- 如果继续只拿 fixture 讲结果,其实已经偏题了
所以一个很重要的方法论是:
- fixture 用来保回归
- 真实运行用来保产品语义
两者不能互相替代。
如果你做的是抓取/聚合/通知类项目,这条尤其重要。
下面这些坑,不是泛泛经验,而是这次仓库里实际撞到过的。
这次实际出现过的情况包括:
- README 写 8 个 crate,但实际已经 11 个
- README、roadmap、runtime-stability 里的测试数不一致
- 某些文档还在写“进入收尾阶段”,另一些文档已经写“收口完成”
- 配置迁移指南和真实当前能力不一致
这说明一件事:
AI 不会自动维护文档一致性。
只要你不主动做“状态校准”回合,文档会越来越像一层旧皮。
处理方法:
- 定期做专门的口径校准轮次
- 把 README、roadmap、migration-guide、closeout/status 文档一起比对
- 不要等功能做完才想起来统一口径
这次真实出现过:
- CLI 用
--output json - 但 tracing 也往 stdout 打
- 最后 stdout 里是“日志 + JSON 混在一起”
- 机器端根本没法直接解析
这类问题很典型:
- 功能上“看起来没问题”
- 手工看也能看懂
- 但产品上其实已经坏了
最后的修法是:
- tracing 全部改到 stderr
- stdout 只保留真正的结构化输出
- 另外提供
--run-log写完整结构化日志
这里的经验是:
vibecoding 特别容易做出“人类看起来像能用、程序接起来其实不能用”的半成品。
这次真实发生过:
- 代码和文档都准备好了
git commit被commit-msghook 拦下- 原因是提交标题不符合
<type>(<scope>): <summary>
这类坑很小,但很典型。
如果你不提前知道仓库的 hook 规则,AI 会在最后一刻被这种“流程问题”卡住,然后浪费一轮重新提交。
所以经验很明确:
- 开始前先看
.githooks/ - 别把 hook 当最后才处理的事情
- 提交格式本身也是开发环境的一部分
这次新加测试时,just verify 没过,不是功能错,而是:
- 测试里用了
expect - 测试文件没有处理
missing_docs - 被
clippy -D warnings和 workspace lint 一起拦住了
这类坑说明:
在 Rust 项目里,测试文件不是“随便写”的临时脚本,它同样受工程质量约束。
如果准备全程 vibecoding,最好一开始就约定:
- 测试要么显式允许某些 lint
- 要么就按生产级规范写
否则每次新增测试都会在最后一轮门禁里返工。
一开始只做 fixture 时,看不出来什么问题。 一旦上真实 RSS 源和多领域源:
- 同一新闻会在多个来源桶里重复出现
- 不同来源名称不同,但标题完全一样
- 如果不做去重,输出会显得很蠢
这次真实跑多领域配置时,抓到 25 条,去重后变成 21/22 条,实际移除了 3 到 4 条重复新闻。
这里的经验是:
真实数据的复杂度,永远高于 fixture。
所以:
- fixture 证明“链路能跑”
- 真实抓取才会逼你补“产品必须有的逻辑”
最开始做领域分类时,很容易以为:
- 标题里有 OpenAI / Anthropic / AI,就算 AI
但真实数据一上来就冲突了:
- “OpenAI 的生命科学模型”到底算 AI 还是 Science?
- “财政部长讨论 Mythos AI 风险”到底算 AI 还是 Finance?
- “政府接入 Anthropic 模型”到底算 AI 还是 World?
这次实际修了至少一轮优先级,最后才把:
- Finance n- Health
- Sports
- World
- Ai
- Science
- Technology
- Business
这样一套优先级排顺。
这说明:
分类逻辑不是技术问题,是业务定义问题。
编译器不会告诉你该怎么分,只能靠真实样本和业务判断反复校准。
这次最明显的体验是:
- 你问一个需求
- AI 很自然会把它延展到“顺手再补一些周边”
例如:
- 先补运行日志
- 再补来源保底
- 再补领域保底
- 再补去重
- 再补文档
- 再补示例配置
这些事单看都合理,但如果没人持续收边界,项目会被“合理的顺手优化”拖着一直往前滚。
这不是 AI 的恶意,而是默认倾向。
所以真正重要的不是让 AI 更积极,而是你要不断问:
- 这个改动是不是当前主目标的一部分?
- 如果不是,为什么不是下一轮再做?
至少写清:
- 当前阶段目标
- 不做什么
- 允许跑什么命令
- 文档同步要求
- 完成标准
在这个仓库里,这个角色就是 AGENTS.md。
你必须让任何新会话都能快速知道:
- 工具链版本
- 扩展工具
- Git hooks
- 验证命令
在这个仓库里,对应的是:
没有 fixture,AI 会靠想象写逻辑。 没有真实运行入口,AI 会把 fixture 成功误当成产品成功。
这两者必须同时存在。
这是最关键的一条。
如果没有停止规则,vibecoding 的默认终点就是:
- “再补一点点”
- “这个也顺手做了吧”
- “既然已经做到这里,不如再加一个”
最后项目永远处在“差一点更完整”的状态。
这个仓库最后能收住,不是因为功能做完了,而是因为补了 project-completion.md,明确把项目切到维护模式。
边界、阶段和停止条件,必须由人先定。
产品是不是越来越像你要的东西,要靠文档、真实运行和人工判断,不靠编译器。
只做 fixture 成功,最后一定会误判项目成熟度。
对 vibecoding 项目来说,文档不是总结,而是防项目失控的控制面。
如果这次项目真的只是为了验证:
能不能主要依靠 vibecoding 做出一个 Rust 项目
那答案已经够明确了:
能。
但更重要的附加结论是:
如果没有环境约束、验证门禁、文档基线和停止规则,vibecoding 最后练到的不是工程能力,而是如何把项目做散。