第11课

快速技巧 — 只需知道这些就能上手

应用崩了。昨天还能用的登录今天不行了。付款被扣了两次。每改一处代码,别处就出问题。让 AI “修一下"只会越修越坏。

不要重建。 重建三个月后会在同一个地方崩。先把当前状态锁定下来。

三个结构性工具:

  • codistill — 诊断。自动从现有代码中提取 API 端点、DB 模式和认证流程。
  • huma — 锁定。对所有端点加上回归测试,保护当前行为。
  • yongol — 迁移。从 SSOT 生成新后端,并用现有测试证明行为一致。

从左到右推进。用 codistill 诊断,用 huma 锁定,准备好后用 yongol 迁移。

告诉代理:“运行 codist scan,提取这个项目的端点、DB 模式和认证流程。”

现状一目了然。25 个端点里有几个存活、几个已死,清清楚楚。

告诉代理:“运行 huma verify,检查所有端点状态,并为每个存活端点编写 Hurl 测试。”

这就是回归测试套件。它锁定当前正在运行的内容。只要这些测试通过,代理修改代码也不会破坏现有行为。

告诉代理:“现在修复登录 bug。但所有 Hurl 测试必须全部通过。”

修复 bug,但不破坏其他地方。在 ratchet 咬合的状态下进行维修。


动手体验

没有崩溃的应用也可以体验。在 3 分钟内经历"构建 → 破坏 → 拯救"的完整过程。

第1步 — 构建应用

在 Claude Code 中:

“创建一个简单的待办列表 API。5 个端点:查询待办列表、添加待办、修改待办、删除待办、完成待办。启动服务器。”

第2步 — 用 codist 诊断

“运行 codist scan,提取这个项目的端点列表。”

codist 自动提取 5 个端点的路径、方法和参数。这就是当前地图。

第3步 — 用 huma 锁定

“运行 huma verify,并为所有端点编写 Hurl 测试。”

每个端点都生成了一个 Hurl 文件。当前行为已锁定。

第4步 — 故意破坏它

“修改更新待办端点的响应格式。将 title 字段改为 name。”

修改之后:

“运行 Hurl 测试。”

测试失败了。“期望 title,却收到 name。“漂移被捕获了。ratchet 正在发挥作用。

第5步 — 在 ratchet 咬合状态下进行修复

“修改使所有 Hurl 测试通过。但使用 name 字段的新功能也要保留。”

代理在保持向后兼容的同时完成修复。Hurl 通过,说明现有行为得到了保护。

这是 codistill → huma → 修复 的缩小版。真实崩溃的应用只是把这个过程扩展到 25 个、50 个、200 个端点,原理完全相同。


为什么要这样做

引言:你的应用崩溃的真正原因

2025 年,170 个用 Lovable 构建的应用数据库被完全暴露在互联网上——邮箱、API 密钥、支付信息。原因不是代码 bug。AI 在没有安全策略的情况下构建了应用,没有人做验证。

2026 年 1 月,AI 社交网络 Moltbook 泄露了 150 万个 API token。同样的原因。AI 构建,人类没有检查。

这不是别人的故事。用 vibe coding 构建应用的人,都坐在同样的结构之上。

“做个登录” — 30 秒。“加上支付” — 2 分钟。“添加管理后台” — 5 分钟。三个月后,AI 在"整理"支付逻辑时修改了折扣计算,添加新功能时认证崩了,昨天还正常的页面今天返回 500 错误。

你面临两个选择:

  1. 重建
  2. 拯救

三个月前就可以重建了。问题是重建也会重复同样的模式。漂移不是代码问题,而是结构问题。

你需要学会如何拯救。


遇难者自救法 — 5 步骤

拯救崩溃的应用就像应对登山遇险。不要跑。确认当前位置,保证安全,一步一步前进。


第1步. 诊断 — 现在什么还活着

第一件事不是修代码,而是了解当前状态

告诉代理:"扫描这个项目的所有 API 端点。
向每个端点实际发送请求,
记录响应状态码。
将结果整理成表格:路径、方法、状态码、响应时间。"

如果 25 个端点中 18 个返回 200,4 个返回 401,3 个返回 500——这就是当前地图。没有地图就开始修复,修好的地方会破坏其他地方。

codistill 的 codist scan 自动化了这项工作。它从现有代码中提取端点、数据模型和认证流程。


第2步. 锁定 — 先保护活着的端点

诊断完成后,锁定存活的端点。

告诉代理:"为 18 个返回 200 的端点各写一个 Hurl 测试。
用当前响应作为期望值。
需要认证的端点,先运行登录序列获取 token 再使用。"

这 18 个 Hurl 文件就是安全网。无论之后做什么修改,只要这些测试通过,现有行为就得到了保护。

huma 的 huma verify 将这个过程系统化。它按端点追踪状态,并判定 PASS/IMPROVE/FAIL。

重要:部分锁定不起作用。 如果 18 个中只锁定了 10 个,另外 8 个在维修过程中崩了也不知道。全量锁定是原则。


第3步. 修复 — 在 ratchet 咬合状态下修bug

有了安全网,现在可以修复 bug 了。

告诉代理:"找出登录失败的原因并修复。
但所有 Hurl 测试必须通过。
如果有测试失败,撤销修改。"

这是第6课 Ratchet Pattern 的实战应用。修复但不破坏。每修一个 bug 就跑一次 Hurl。通过——进行下一个 bug。失败——撤销。

返回 500 错误的 3 个端点也用同样的方式修复。修复完成后添加新的 Hurl 测试。ratchet 又咬紧了一格。


第4步. 提取 — 从黑盒中取出逻辑

这是关键步骤。应用崩溃的根本原因通常在这里。

如果你在用 Supabase:

  • RLS 策略只在控制台里,不在代码中
  • 业务逻辑藏在 Edge Functions 里
  • 认证逻辑被绑定在 Supabase Auth 上

如果你在用 Firebase:

  • Security Rules 只在控制台里
  • 逻辑分散在 Cloud Functions 中

无论用哪种 BaaS,结构都一样。业务逻辑在代码库之外。

告诉代理:"从 Supabase 控制台提取所有 RLS 策略。
把每张表的 SELECT、INSERT、UPDATE、DELETE 策略
保存为 SQL 文件。提交到 git。"
告诉代理:"分析 Edge Functions 中的业务逻辑。
整理文档,说明哪些函数实现了哪些业务规则。"

这是把逻辑从黑盒中取出放入代码库。取出来之后,代理才能读取、测试,并用 ratchet 锁定。

codistill 的 codist ddl 从现有数据库中提取 DDL。codist scan 从代码中提取 SSOT。这些都是从黑盒迁移到声明式层的工具。


第5步. 迁移 — 只在准备好时进行

完成第1到4步后,应用处于以下状态:

  • 每个端点都有 Hurl 回归测试
  • bug 已修复
  • 黑盒中的逻辑已在代码库中文档化
  • ratchet 已咬合,新修改不会破坏现有行为

在这个状态下决定迁移。从 Supabase 迁到自建后端,从 Deno 迁到 Go,随你选择。

迁移的安全网是第2步编写的 Hurl 测试。在新服务器上运行同样的 Hurl,全部通过——就证明了与遗留系统行为一致。

告诉代理:"用 yongol generate 生成 Go+Gin 后端。
让现有所有 Hurl 测试全部通过。"

迁移是第5步,不是第1步。在第1步就尝试迁移会失败。这是在事故复盘中确认的教训。


如何从 Supabase 脱身

第11课最常见的场景就是 Supabase。从 vibe coding 开始,全押在 Supabase 上,三个月后崩了。

脱身顺序:

1. 保留 DB,只加 ratchet

Supabase 的 PostgreSQL 照用不动。更换 DB 是最后一步。

codist ddl → 从现有表中提取 DDL
huma verify → 评估端点状态
hurl → 全量锁定所有存活 API

2. 把逻辑迁入代码

RLS 策略 → Rego 文件。Edge Functions → SSaC 注解。从控制台迁移到代码库。

3. 解耦认证

Supabase Auth 是最后才拆除的。由于无法从 auth.users 提取密码哈希,若还没有用户,立即迁移;若已有用户,运行双重认证过渡期。

4. 启动新服务器并用 Hurl 验证

yongol generate → 生成 Go+Gin 后端
全量运行 hurl 测试 → 证明与遗留系统行为一致

Hurl 全部通过后,切换流量。


为什么不能重建

“就重新做一个不行吗?”

不行。三个原因:

1. 同样的模式会重复

漂移是结构问题,不是代码问题。没有 ratchet 就重建,三个月后还是在同一个地方崩。

2. 遗留代码中埋藏着知识

三个月 vibe coding 积累的业务规则藏在代码里。重建意味着要从记忆中重构这些规则。记忆会出错。

3. 可能已经有用户了

原型变成生产环境的时刻是存在的。哪怕只有一个用户,“重建"就意味着数据迁移、认证切换和停机时间。

学会拯救比学会重建更有价值。 因为遗留代码永远存在,新代码六个月后也会变成遗留代码。


第11课与第1至10课的关系

从一开始就做对的方法第11课:拯救崩溃的应用
第3课 Hurl声明 API 契约将现有行为锁定为回归测试
第4课 yongol从 SSOT 生成从现有代码中提取 SSOT
第6课 Ratchet通过则锁定修复但不破坏
第8课 filefunc结构化代码整理遗留代码
第10课 DDL声明模式从现有 DB 中提取 DDL

相同的工具,相反的方向。 第1至10课是"自上而下”(声明 → 生成),第11课是"自下而上”(现有代码 → 提取 → 声明)。

codistill 是自动化这种"自下而上"提取的工具。它从现有代码中提炼出 SSOT。


从遇难者到救援者

完成这个过程后,你拥有两种能力:

  1. 从零开始构建的方法(第1至10课)— 声明、验证、锁定、持久化
  2. 拯救崩溃应用的方法(第11课)— 诊断、锁定、修复、提取、迁移

世界上大多数代码都是遗留代码。从零开始的项目很少见。拯救的能力会被更频繁地用到。

Vibe coding 并没有结束。你已经学会了如何握住缰绳。


相关文章


Reins Engineering 全部课程

标题
第1课如何向 AI 下达指令
第2课如何不信任 AI
第3课不会崩溃的应用
第4课将决策移出代码
第5课有缰绳的 AI
第6课通过则锁定
第7课翻转奉承的方法
第8课代理的工厂
第9课超越代码的自动化
第10课数据之法
第11课如何拯救崩溃的 Vibe Coding 应用

出处

  • Feathers, M. (2004). Working Effectively with Legacy Code. Prentice Hall. — Characterization testing 的原典。将遗留代码包裹在测试中以锁定当前行为的技术。第11课第2步的理论基础。
  • CVE-2025-48757 (2025). Lovable 生成的 170+ 应用因缺少 RLS 导致 Supabase DB 暴露。ameeba.com
  • OG William (2026). “Moltbook Hack: Supabase Vibe Coding.” 150万 API token 泄露。blog.ogwilliam.com
  • Cursino, D. et al. (2026). “Speed at the Cost of Quality? The Impact of AI Coding on Software.” MSR 2026. arxiv.org/abs/2511.04427 — 引入 Cursor 后代码复杂度永久增加 41.6%。vibe coding 崩溃的量化依据。
  • Liu, Z. et al. (2026). “Debt Behind the AI Boom: A Large-Scale Empirical Study of AI-Generated Code in the Wild.” arxiv.org/abs/2603.28592 — 分析 6,299 个仓库和 302,600 次 AI 提交。未解决的技术债务从 2025 年初的数百件激增至 2026 年 2 月的 110,000 件以上。
  • Storey, M.-A. (2026). “From Technical Debt to Cognitive and Intent Debt.” arxiv.org/abs/2603.22106 — 将漂移的根本原因理论化为"认知债务”(共识侵蚀)和"意图债务”(根据未外部化)。
  • Nguyen, H. et al. (2025). “Vibe Coding in Practice: Flow, Technical Debt, and Guidelines for Sustainable Use.” arxiv.org/abs/2512.11922 — 首篇记录 vibe coding flow-debt 权衡的学术论文。
  • Cloud Security Alliance (2026). “Vibe Coding Security Crisis: Credential Sprawl and SDLC Debt.” labs.cloudsecurityalliance.org — 45% 的 AI 生成代码包含 OWASP Top 10 漏洞。AI 提交中的密钥泄露率是普通代码的 2 倍。
  • GitClear (2025). “AI Copilot Code Quality 2025.” gitclear.com — 分析 2.11 亿行代码。代码重复增加 4 倍,重构比例从 25% 降至 10%。
  • Encore (2026). “Backend as a Service (BaaS) in 2026: Providers, Tradeoffs, and Migration Paths.” encore.dev — BaaS 迁出不是移植,而是后端重写。