惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
Lohrmann on Cybersecurity
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recorded Future
Recorded Future
S
Schneier on Security
I
Intezer
Latest news
Latest news
N
News and Events Feed by Topic
Scott Helme
Scott Helme
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
量子位
博客园 - 【当耐特】
S
Security @ Cisco Blogs
Google Online Security Blog
Google Online Security Blog
博客园 - 叶小钗
酷 壳 – CoolShell
酷 壳 – CoolShell
NISL@THU
NISL@THU
The Cloudflare Blog
李成银的技术随笔
T
ThreatConnect
L
LINUX DO - 最新话题
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
有赞技术团队
有赞技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Jina AI
Jina AI
T
Tor Project blog
The Hacker News
The Hacker News
人人都是产品经理
人人都是产品经理
小众软件
小众软件
S
Security Archives - TechRepublic
美团技术团队
博客园 - Franky
Security Latest
Security Latest
J
Java Code Geeks
P
Proofpoint News Feed
V
V2EX
The GitHub Blog
The GitHub Blog
WordPress大学
WordPress大学
Application and Cybersecurity Blog
Application and Cybersecurity Blog
H
Help Net Security
PCI Perspectives
PCI Perspectives
Cyberwarzone
Cyberwarzone
Hugging Face - Blog
Hugging Face - Blog
N
Netflix TechBlog - Medium
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
SecWiki News
SecWiki News
腾讯CDC
爱范儿
爱范儿
D
Docker

掘金

juejin.cn juejin.cn juejin.cn Transformer 原论文怎么训出来的:8 张 P100、12 小时、warmup 4000 步 Hermes 升级后,我的 Telegram 附件突然发不出来了 Transformer 中的前馈网络:那个看似平平无奇的两层 MLP,其实是「记忆」所在 juejin.cn 【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (1)---基础 juejin.cn juejin.cn juejin.cn Manim物理模拟:别自己写欧拉了! 我也该升级了,陪伴了我7年的博客 RAG 实战:从一篇掘金文章出发,拆解检索增强生成的全链路 我搭了个网页工具:输入关键词,SERP API 自动吐出比价 Excel MCP 高德地图实战:当 AI 学会使用工具,一个协议如何重塑大模型的行动边界 用魔法打败魔法:我让AI替我去面试前端岗,AI面试官给我打了92分,还发了offer juejin.cn juejin.cn juejin.cn Android Input Spy Window Claude Code CLI 命令大全:60 个原生命令一次讲清 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn 关于一个新手小白靠claude帮助下的全栈留言板项目开发 juejin.cn juejin.cn juejin.cn 从本地开发到生产部署:用 Docker Compose 跑通 NestJS、MySQL 与 Milvus AI应用开发七:可以替代 RAG 的技术 juejin.cn 小书匠:一款本地优先、去中心化的全能笔记软件 juejin.cn juejin.cn juejin.cn Shadow实战接入与生产落地:从零搭建到稳定运行 Shadow Transform:编译期的魔法——字节码替换实战 juejin.cn juejin.cn Hermes Agent:一个真正“会成长”的开源 AI Agent,正在改变 AI 自动化玩法 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn CryptoJS:数据安全的JavaScript加密利器 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn ArkClaw AI 盯盘管家 —— 从手动口令到自动推送,4 套预置定时任务模版一键启用 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn “杀!杀!杀!”、“我最讨厌事后道歉”——骂“杀哥”之前,谁还没当过情绪崩溃的人 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn Crawlee StagehandCrawler:自然语言点 Load More 的工程化爬虫 juejin.cn juejin.cn juejin.cn juejin.cn 人人都在鼓吹的OPC,我想给你泼盆冷水 juejin.cn juejin.cn juejin.cn Redis内存用爆了,原来我们都忽略了这个配置 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn
我让 AI 加了一个开关,结果代码走了原本不该走的分支
桦说编程 · 2026-05-25 · via 掘金

大家好,我是桦说编程。

最近 code review 发现一个 claude code 写的 bug,感兴趣的读者可以自己试一试能否复现。

真实 case:让 AI 给守卫式分支链加开关,AI 把开关 AND 进了原变量。代码读起来还很顺,但守卫语义已经悄悄塌了。本文复盘这种"语义漂移"为什么是 AI 改代码的高频陷阱,以及人类 reviewer 应当盯什么。

问题背景

业务侧有这样一个守卫式分支链(伪代码,已把场景脱敏成"VIP 用户走快速通道,普通用户走促销校验"):

boolean isVipUser = vipUserSet.contains(userId);
if (isVipUser) {
    // VIP 用户:走快速通道
} else if (isWhitelisted(...)) {
    // 白名单:信任配置值
} else if (inPromotion(...)) {
    // 普通用户 + 命中促销:走促销价校验
} else {
    // 标准流程
}

isVipUser 是一道守卫:VIP 被第一个 if 截胡,永远不会跌进下游分支。下游"促销校验"分支隐式依赖这个事实——只有非 VIP 才走得到。

改动需求:加一个开关

需求很直白:"给 VIP 快速通道加一个开关 vipFastPathEnable,关闭时 VIP 也走原行为。"

AI 拿到这个需求,最短路径是:

boolean isVipUser = fastPathSwitch && vipUserSet.contains(userId);   // 改了语义,没改名
if (isVipUser) { ... }
else if (isWhitelisted(...)) { ... }
else if (inPromotion(...)) { ... }
else { ... }

代码读起来很顺,编译通过,开关打开时行为完全正确。问题在开关关闭时——

isVipUser 此时已经不是"是不是 VIP"的回答,而是"是不是要走快速通道"的回答。变量名是事实,值是决策。 VIP 用户关掉开关后,isVipUser = false,跌入下游"促销校验"分支,被当成普通用户走促销逻辑——守卫失效。

修复:拆成两个变量

boolean isVipUser = vipUserSet.contains(userId);                   // 事实
boolean applyVipFastPath = fastPathSwitch && isVipUser;            // 决策
if (applyVipFastPath) { ... }
else if (isWhitelisted(...)) { ... }
else if (!isVipUser && inPromotion(...)) { ... }                   // 用事实做守卫
else { ... }

两件事变了:

  1. 事实和决策分离isVipUser 回答客观事实,applyVipFastPath 回答策略问题。
  2. 下游守卫显式化。原本依赖"上一个 if 不进 = 非 VIP"的隐式前提,现在写成 !isVipUser && 显式守卫。

显式守卫这一步同样关键。即使你只在变量定义处拆了名字,不动下游 else if,只要开关关闭,VIP 仍会跌入"促销校验"——因为下游分支条件没说"我只接非 VIP",它接所有上游没截走的。守卫是分布式的,集中改一处不够。

为什么 AI 容易踩这个坑

归纳几条:

1. LLM 改代码倾向于"最小局部修改"。 看到"加开关",最短路径就是在变量定义处 AND 一个 bool。它没动 if/else if 链,是因为下游"看起来还能跑"——实际下游的隐式前提已经被破坏。

2. 守卫语义不写在代码里。 else if (inPromotion) 没写"我只接非 VIP",那个前提住在上一个 if (isVipUser) 的 false 分支里。LLM 看不到没写出来的契约。

3. 命名是契约,但 LLM 不天然守约。 isVipUser 这个名字承诺了它回答事实,AI 改完后它回答决策——名字没改,承诺被毁。如果 v2 把变量改名成 shouldUseFastPath,bug 在命名阶段就会暴露,因为下游 else if (inPromotion) 的注释 "// 普通用户走这里" 会立刻变得讲不通。

4. 加开关时人类的本能错觉。 "我只是加了一道筛子,原来能进的现在更少进"——所以分支链应该更安全才对。错。守卫分支链不是筛子,是路由。第一个分支"少进"意味着下游分支"多进"。下游接得住吗? 这是改任何守卫链时必须问的问题。

给人类 reviewer 的 checklist

收到 AI 提交的 PR,看到守卫式分支链有改动,盯这几条:

  1. 变量定义改了,使用点没动? 红旗。大概率是语义偷换。
  2. 开关 / 配置 / 业务策略有没有混进纯事实的变量?混了就拆。建议命名约定:事实变量用 isXxx / hasXxx,决策变量用 shouldXxx / applyXxx / enableXxx
  3. else if 链的每个分支隐式假设是什么? 逐条问"如果上面所有 if 都不进,剩下的子集是什么"。如果剩下的子集和这个分支的语义对不上,把守卫显式化。
  4. 开关关闭后,原本走 A 分支的 case 会跑到哪个分支?那个分支接得住吗? 这是开关类改动的标准测试维度,单测里至少覆盖"开关 ON / OFF × 守卫命中 / 不命中"四象限。
  5. 变量名是契约。语义变了就改名,改名了就 grep 所有 use site 确认每一处都还讲得通。

总结

  • AI 改代码最常见的隐形 bug 之一:给变量加约束时不改名字,把"事实"偷换成"决策"
  • 守卫式分支链对前置条件变量极其敏感——isVipUser 含义一变,下游所有"普通用户走这里"的隐式假设全部塌方。
  • 修复模板:事实变量保留客观语义;决策 / 开关 / 策略走第二个变量;下游守卫从"隐式依赖上一个 if 的 false"升级为"显式 !isFact && 守卫"。
  • Reviewer 的红旗:变量定义改了但所有使用点没动;开关类改动没有覆盖"开关 OFF + 原命中"用例。

如果这篇文章对你有帮助,欢迎关注我,持续分享高质量技术干货,助你更快提升编程能力。