一次 AI 调试死循环的脱困记录
背景
AI 辅助编程工具在实际使用中展现出了强大的代码生成能力。对于明确的任务——实现一个 API 接口、编写一段数据处理逻辑、翻译一套 UI 组件——AI 通常能在有限的交互轮次内完成工作。然而,当任务目标无法被形式化验证时(例如布局是否”看起来协调”、配色是否”有高级感”),AI 的表现会出现显著的不确定性。这类主观判断驱动的任务天然需要多轮迭代,但迭代的方向是否正确,决定了最终产出效率的天壤之别。
笔者在 Chestnut-Astro 项目中经历了一次典型的对比案例。该项目的教案页面(后更名为”文档”模块)需要一个三栏布局——左侧分类导航、中间文章内容、右侧目录(TOC)。这是一个在 VitePress 和 Astro Starlight 等文档框架中已被广泛验证的布局模式,从技术角度看实现难度不高:固定三列宽度,设置 sticky 定位,处理好响应式断点即可。
然而,这个看似简单的需求耗费了两个完整的 AI 会话。前者持续了 6 小时以上,产生了 30 余次 commit,经历了至少 7 个不同的布局 bug,最终仍未彻底解决布局稳定性问题;后者在引导式提问下 6 次 commit 即告完成。两次会话处理的是同一个项目、同一个页面路由、同一个布局问题,产出效率差距超过五倍。本文基于这两份会话记录(合计约 38,000 行),从交互模式、上下文管理和根因定位三个维度展开分析。
数据来源与方法
两份会话记录来源于 OpenCode 的本地日志文件。会话一(ses_1d3b7301)始于 2026 年 5 月 15 日 23:37,使用模型为 mimo-v2.5-pro,Agent 为 karpathy-build。会话二(ses_1cfaf9b2)始于 2026 年 5 月 16 日 18:23,使用模型为 deepseek-v4-pro,Agent 同为 karpathy-build。两份会话针对的是同一 Git 仓库(Chestnut-Astro)中的同一页面路由(/lessons,后更名为 /docs)。
分析方式为人工复盘:逐轮阅读 AI 的推理过程、工具调用序列、用户反馈及 AI 的回应策略,结合 git log 中的 commit 记录验证代码变更的时间线与内容。需要说明的是,两次会话使用了不同的底层模型,模型能力的差异可能对结果产生了不可忽视的影响。但由于两份会话由同一个用户在同一个项目上、针对同一个问题发起,且笔者的参与方式——即 prompt 的组织策略——是有意调整的变量,本文的分析重点置于交互策略层面。
会话一:六小时循环调试
会话一的起始 prompt 定位为”让我来干”类型:用户描述了想要的效果,AI 直接进入方案设计和实施阶段。AI 在最初的几轮交互中通过 read 工具读取了项目结构、现有布局代码和组件文件,随后提交了第一个 commit。从这一刻开始,对话进入了一个持续六小时的修复循环。
第一个坑:1fr 导致内容区宽度随内容变化
第一个版本的布局代码使用 CSS Grid,中间内容区采用了 1fr:
grid-template-columns: 260px 1fr 220px;
这一方案的核心问题在于 1fr 的含义:中间列的宽度 = 视口宽度 − 侧边栏 260px − TOC 栏 220px − 内外边距。当用户在不同文章之间切换时,侧边栏中标题的换行情况会发生变化——“第1课”仅 3 个字符,而”用 Astro 搭建多主题博客:架构设计与实现”有 17 个字符——这些换行差异导致侧边栏的实际高度变化,进而通过 Astro 的 View Transitions 动画触发 1fr 列的重新计算,产生边界跳动。
用户的反馈是”不同文章切换时边界反复变动”,AI 的回应是在内容区上追加 min-width: 600px。这个修复在原理上部分正确——最小宽度约束确实可以防止内容区完全塌缩——但它没有触及根因。内容区的宽度仍然是一个变量,min-width 只是一个下限。
第二个坑:min-width 导致三栏交叉重叠
加上 min-width: 600px 后,新的问题出现了:侧边栏、内容区和 TOC 三栏交叉重叠在一起。
这根因在于 Grid 的列宽计算逻辑发生了变化。此前三列的总宽度是 260px + 1fr + 220px,加上 min-width: 600px 后,当内容区的最小宽度被强制为 600px 时,如果视口总宽度不足以容纳三列的最小值之和,Grid 会压缩各列或允许内容溢出。而 AI 在添加 min-width 时,没有同步调整其他列的溢出行为,也没有检查视口宽度临界值下的布局表现。
这里可以看到一种典型的”局部思维”:AI 关注的是”内容区不能太窄”这个单一目标,添加了 min-width,但没有考虑这个约束对 Grid 系统整体的影响。Grid 是一个耦合系统,一列的变化会牵动其他列——如果内容区强制保持 600px,那么在窗口宽度不足时,侧边栏或 TOC 就会被挤压或溢出。
AI 的修复方案是拉宽整体容器:max-width 从 1400px 提升到 1600px,各列改为固定宽度 260px 800px 260px,同时移除内容区的 min-width 和 max-width。这相当于用更大的画布来避免冲突,而非解决冲突本身。用户在 1920px 屏幕上测试后反馈”还是小”——场景来到了”在宽屏上内容区仍然显得不够宽”。
第三个坑:比例布局的宽度幻觉
“还是小”这个反馈将 AI 带入了比例布局的探索。AI 认为,如果内容区在固定宽度下不够宽,那么比例布局可以让三列随视口宽度自动缩放,从而在大屏幕上获得更多空间。
于是 grid-template-columns 从 260px 800px 260px 改为 1fr 8fr 1fr。
这一改动的问题在于:用户说的”小”并不是指内容区的绝对像素数不够——在 1920px 屏幕上,内容区即使按 1:8:1 也有 1228px 可用宽度——而是指内容区中文章正文的视觉尺寸偏小。比例布局没有解决这个问题,只是改变了列宽分布。用户的感知是”看起来小”,这个感知涉及字体大小、行距、内容密度的综合视觉效果,单纯调整列宽根本无法触达。
但 AI 的理解是”用户嫌内容区宽度不够,所以要加大内容区占比”。于是出现了以下序列:
| 时间 | commit | grid-template-columns | 内容区占比 |
|---|---|---|---|
| 18:04 | c18832b | 1fr 8fr 1fr | 80% |
| 18:06 | e52a88b | 1fr 6fr 1fr | 75% |
| 18:10 | 102bdae | 1fr 10fr 1fr | 83.3% |
| 18:19 | 29626f6 | 200px 1fr 200px | 回到固定宽度 |
1:8:1 时内容区占 80%,约 1228px,用户说小。AI 调到 1:6:1,内容区降到 75%,用户说更小了。AI 计算:用户说更小 → 需要更大 → 调到 1:10:1,内容区升到 83%。用户反馈:侧边栏缩到 69px,文字显示不全。AI 最终回到固定宽度。
这个序列暴露了两个问题。第一,AI 把用户说的”小”理解成了像素宽度问题,实际上用户描述的是视觉感知。第二,AI 在 1:8:1 和 1:6:1 之间切换时,内容区占比实际上是递减的——用户感知到”更小了”是正确的物理观察,不是错觉。AI 在这个阶段根本没有重新计算各列的绝对像素值,只是机械地调整了 fr 比例。
第四个坑:TOC 组件不接收数据(看不见的 bug)
在布局参数调整之外,还有一个隐藏的 bug:TOC 组件一直不显示。当用户打开教案页面时,右侧的目录区域是空的。
这个问题的根因相当简单——AI 在 LessonLayout.astro 中定义了 headings 作为可选属性,但在教案路由页面([...slug].astro)中调用 LessonLayout 时没有传递这个 prop:
<!-- 错误:没有传递 headings -->
<LessonLayout
title={firstLesson.data.title}
date={firstLesson.data.date}
currentSlug={firstLesson.id}
>
<Content />
</LessonLayout>
<!-- 正确:需要从 render() 中解构 headings -->
<LessonLayout
title={firstLesson.data.title}
date={firstLesson.data.date}
currentSlug={firstLesson.id}
headings={headings}
>
<Content />
</LessonLayout>
这个 bug 被用户以”TOC 不显示”的形式报告。AI 的修复方式是在路由页面中补上 headings 的传递(commit 469bc90)。问题解决了,但它暴露出 AI 在初期搭建组件树时遗漏了一个关键的数据流连接。更值得注意的是:TOC 不显示的问题在第一次出现时,AI 并没有第一时间检查数据流,而是先怀疑 CSS 样式问题——它花了 7 个 commit 调整布局参数后,才回到数据流检查。
第五个坑:手机端 TOC 打开是白屏
TOC 数据显示出来之后,新的问题紧随其后:在手机屏幕上点击右下角的 TOC 切换按钮,弹窗是白色的,没有任何内容。
这个 bug 的成因是 CSS 层叠冲突。TOC 组件(TOC.astro)在小屏幕下使用 max-width: 1200px 的媒体查询将自己隐藏:
/* 在 TOC.astro 中 */
@media (max-width: 1200px) {
.toc { display: none; }
}
而父级布局(LessonLayout.astro)在手机端通过添加 .open 类来重新显示 TOC 容器:
/* 在 LessonLayout.astro 中 */
@media (max-width: 768px) {
.toc-container { display: none; }
.toc-container.open { display: block; }
}
当屏幕宽度 ≤ 768px 时,两组规则同时生效:父级显示 .toc-container.open,但子级 .toc 仍然被自己的 display: none 隐藏。AI 的修复方式是在 TOC 组件中追加 :global() 选择器来覆盖自身的隐藏规则:
:global(.toc-container.open) .toc { display: block; }
这条规则的意思是”当父元素有 .open 类时,强制显示 .toc”。它确实让 TOC 内容出现了,但引入了一个强耦合:TOC 组件的样式现在依赖于父级布局的一个特定 class 名称。如果以后父级的 class 命名发生变化,TOC 组件的样式会静默失效。
这个 bug 的深层原因在于 TOC 组件承担了超出其职责范围的责任——它不应该自己决定什么屏幕宽度下隐藏自己,这个决定应该由父级布局统一管理。但 AI 在初始实现中把 display 逻辑分散在了组件和布局两个层面,后续修复时只能通过 :global() 来桥接。
第六个坑:TOC 浮层关闭按钮被遮挡
TOC 能显示之后,新的问题又出现了:浮层右上角的关闭按钮被遮罩层遮挡,用户无法点击关闭。
这次的原因是 z-index 值设置不合理。AI 在布局中给遮罩层设置了 z-index: 99,给关闭按钮设置了 z-index: 100,表面上看按钮的层级更高。但 TOC 浮层内容本身在一个独立的容器中,其 z-index 上下文相对于遮罩层是隔离的。当浮层内容容器没有显式设置 z-index 时,关闭按钮虽然在自己的容器内 z-index: 100,但整个浮层容器的层级可能低于遮罩层。
AI 的修复方案是将关闭按钮的 z-index 从 100 跳升到 210(commit faef96b):
/* 修改前 */
z-index: 100;
/* 修改后 */
z-index: 210;
这是一个典型的”蒙数字”修复——AI 没有分析 z-index 的层叠上下文关系,而是试图用一个足够大的数字来”压倒”其他元素。大数策略在大多数情况下能工作,但它不是真正的层叠上下文管理。如果以后再有其他浮层组件加入,z-index 的管理会变成一场”谁的数字更大”的竞赛。
第七个坑:Header 宽度与内容区不对齐
布局的主题是教案页面,但 Header 的宽度一直没有对齐。教案页面的 max-width 被先后调整为 1400px 和 1600px,而 Header 的 max-width 始终是 1080px——这是早期主页设计的遗留值。结果就是在宽屏下,Header 的内容(Logo + 导航链接)集中在屏幕中央 1080px 范围内,而页面内容扩展到 1600px,两者之间的边界错位。
AI 的第一次修复是将 Header 的 max-width 从 1080px 增加到 1600px(commit 4c3aaca)。这个修复看起来直接,但问题没有完全解决——因为 Header 内部的导航项布局是居中对齐的,单纯增加 max-width 只是让两侧的留白变大了,导航项本身的位置与下方内容的侧边栏起点并不对齐。
后续 AI 又做了一次调整(commit 6c13772):去掉 Header 的 max-width,改为 width: 100%,撑满整个视口。这样 Header 始终与视口等宽,不再受 max-width 约束,然后通过内边距来对齐内容区。
这种”先固定宽度、发现不对、再去掉固定宽度”的模式,在 AI 的调试过程中反复出现。AI 倾向于用参数调整来解决问题(加一个约束、改一个数值),当参数调整不奏效时再考虑结构变更。这种模式在简单问题上是高效的,但在多个相互依赖的属性(Header 宽度、内容区宽度、侧边栏定位)共同影响布局时,参数调整的成本会快速上升。
第八个坑:分类折叠动画与原生 details 的冲突
在布局框架稳定之后,AI 开始添加侧边栏的功能特性,其中包括分类折叠。AI 使用了原生 HTML 的 <details> 元素来实现折叠功能,然后试图用 CSS max-height 过渡动画来实现平滑展开效果。
<details class="category-group" open>
<summary class="category-name">
{cat}
<span class="category-count">{groups.get(cat)!.length}</span>
</summary>
<div class="category-items">
<!-- 文章列表 -->
</div>
</details>
.category-items {
max-height: 0;
overflow: hidden;
transition: max-height 0.35s ease;
}
.category-group[open] .category-items {
max-height: 600px;
padding: 0.25rem 0;
}
这个方案在概念上是对的,但在实践中行不通。<details> 元素的 open 属性切换是即时的,它的 display 状态在属性变化时立即跳转,不会等待 CSS transition 完成。当用户点击 <summary> 时,[open] 选择器立即生效,max-height 从 0 跳变到 600px,过渡动画没有被触发。
AI 试验了滑动动画、max-height 渐变、transform 旋转等多个方案,最终在 commit 9df9a6d 中放弃了 <details>,改用 div + JavaScript class 切换:
<div class="category-group">
<button class="category-name" onclick="this.parentElement.classList.toggle('collapsed')">
{cat}
<span class="category-count">{groups.get(cat)!.length}</span>
</button>
<div class="category-items">
<!-- 文章列表 -->
</div>
</div>
随后又经历了一次 revert(commit 0dd0db7),把动画全部去掉,只保留最基础的折叠功能。一个简单的折叠动画,AI 花了 4 次 commit(feat → fix → revert → fix)才最终收敛。
九个坑但问题还在:修复循环的总结
把整个调试过程串联起来,可以看到如下链条:
初始布局 (1fr) → 内容区塌缩
→ 加 min-width → 三栏重叠
→ 拉宽到 1600px → 内容区视觉效果小
→ 改比例 1:8:1 → 更小 ← 用户感知方向已偏离
→ 1:6:1 → 更小
→ 1:10:1 → 侧边栏失效
→ 回到固定宽度 → TOC 不显示(数据未传递)
→ 补 headings prop → 手机端 TOC 白屏(display 冲突)
→ 加 :global() 覆盖 → 关闭按钮被遮挡(z-index)
→ z-index 跳升到 210 → Header 宽度不对齐
→ 改 max-width → 分类折叠动画不生效
→ 换 div+class → 折叠动画 revert
→ 放弃动画 ← 还有问题吗?
这条链上有 9 个明确可识别的问题节点,其中 6 个是 AI 修复上一个问题时引入的新问题。这个比率值得注意:AI 的”修复”行为本身,成为了新增缺陷的主要来源。每一次修复都在一套已经不一致的代码上叠加一层新的规则,使得后续问题的诊断成本逐轮上升。
会话二:重置上下文后的破局
起手策略的差异
会话二的起始 prompt 与第一次有一个关键区别——它增加了行动顺序约束:
“请你理解一下这个项目……请根据我的想法先给我出设计方案,我认可后再修订。”
AI 没有像上一次那样在 2-3 轮内进入 edit。它先后调用了 12 次 read 工具(比会话一同一阶段的阅读量高出约一倍),读取了布局组件、样式文件、内容配置和示例数据。完成项目理解后,AI 给出了一个在会话一中从未出现过的诊断:
“当前教案区域使用
grid-template-columns: 200px 1fr 200px……主内容区用1fr,意味着它的宽度 = 视口宽度 - 400px。但这个1fr列本身是流体的——不同的内容长度下会有以下连锁反应……”“Vitepress / Starlight 的做法完全不同:内容区宽度是硬固定(max-width),不是 1fr。剩余空间全部变成左右 margin,侧边栏和 TOC 是’漂浮在 margin 区域里的固定元素’。”
这段话的价值在于它的归因逻辑:问题不在于 grid-template-columns 取什么单位,而在于让 1fr 决定内容区宽度本身就是不稳定的。VitePress 的解法是将内容区宽度固定为一个常量,用 margin 吸收剩余空间。
方案的简洁性
在诊断明确之后,具体实现方案变得极为简单:
.lessons-page {
display: flex;
justify-content: center;
}
.lesson { max-width: 700px; }
整个布局从 CSS Grid 切换为 Flexbox,主内容区放弃 1fr 改为固定最大宽度,三列通过 justify-content: center 居中排列。这个方案不会因为切换文章而改变内容区的宽度——无论侧边栏中哪个标题换行,内容区的 700px 上限始终不变。
这一方案的另一个好处是不再需要 :global() 覆盖和双重 sticky 定位——TOC 组件的显示逻辑完全由父级布局控制,组件本身只负责渲染内容。层叠关系从”组件和布局都在管”变成了”布局统一管,组件只管内容”。
后续的扩展
这一基础方案确立后,会话二在后续的 commit 中还完成了一系列重构工作:
- 统一命名:
lessonSchema→docsSchema,.lesson-*→.doc-* - 提取工具函数:
getPublishedDocs/getPublishedPosts,消除三个文件中重复的getCollection调用 - 提取 CSS 变量:
--header-height/--sidebar-width,消除散落在各组件中的硬编码值 - 类型去重:消除
types/series.ts与config/series.ts中的重复类型定义 - 所有
getCollection调用增加try/catch容错,数据获取失败时回退空数组 - 生成项目架构文档,供后续开发者查看
这些工作在第一会话中从未被触发——AI 的所有注意力都被”调布局参数”消耗殆尽。会话二的 AI 在解决核心问题后,有空间和能力去处理更高层面的代码质量问题。
对比分析
产出效率
| 对比维度 | 会话一 | 会话二 |
|---|---|---|
| 初始 prompt 模式 | ”实现这个效果" | "先理解再出方案” |
| 首轮回复前 read 调用数 | 约 6 次 | 12 次 |
| 核心方案的根因诊断 | 否 | 是 |
grid-template-columns 修改次数 | 8 | 0 |
| 引入的冗余样式规则 | :global()、双重 sticky、覆盖式 z-index | 极少 |
| 完成额外重构 | 无 | 命名统一、变量提取、类型去重、架构文档 |
| 从开始到布局稳定的 commit 数 | 30+ | 6 |
从数值上看,会话二在更短的时间内用更少的 commit 解决了问题并额外完成了重构。但两组数据不可简单归因于模型能力——会话一的 AI 如果被同样的 prompt 策略约束,表现可能大不相同。
交互模式的差异
两份会话在交互模式上存在三个显著差异。
第一个差异是 AI 首次响应前的信息收集量。会话二中 AI 在第一轮回复之前读取了 12 个文件,覆盖了布局组件、样式文件、内容配置和示例数据。会话一中 AI 在同等阶段读取了约 6 个文件,且跳过了一些关键文件——例如它没有阅读 prose.css,这导致后续对内容区宽度的计算忽略了 prose 样式对 padding 的影响。多读 6 个文件本身不是关键,关键是 AI 在分析阶段就意识到了”需要理解完整的项目结构才能设计正确的方案”。
第二个差异是 AI 是否主动对标成熟方案。会话二中的 AI 明确提及了 VitePress 和 Astro Starlight 的布局原理,并将其作为参考来诊断自己的方案:“Content area should be a fixed max-width, not 1fr”。会话一中的 AI 从未做过这件事——尽管用户在第一轮需求中已经提到了”像 VitePress 一样”。会话一的 AI 记得用户说过”像 VitePress”,但它没有去查 VitePress 是怎么做的。
第三个差异是修复尝试的维度宽度。会话一中,AI 的所有修复都集中在 grid-template-columns 这一个属性上。搜索空间是一维的。会话二中,由于 AI 在动手前已经完成了方案层面的分析,它直接从 flex 布局切入,跳过了 grid 参数调优的整个空间。
上下文锚定效应
会话一的长对话历史构成了一种锚定效应。用户在持续数小时的交互中发表了数十次反馈,这些反馈的措辞都聚焦于”宽度""比例""大小”——这自然地将 AI 的注意力锁定在了 column 宽度这一个维度上。
从 AI 的推理过程中可以看出一个清晰的模式:
- 第一轮修复:推理关键词是”用户说宽度不对,我需要调整 grid-template-columns”
- 第三轮修复:推理关键词是”用户说还是小,我尝试比例布局”
- 第五轮修复:推理关键词是”用户说更小了,我继续调比例”
AI 的推理窗口始终被前一轮的用户反馈所占据。它不会在修复的间隙主动反思,因为对话历史中没有任何一条信息提示它应该这么做。会话二的起始 prompt 提供了一个不同的框架:“先给我出设计方案,我认可后再修订”。这条指令将 AI 的执行模式从”修复”切换到了”分析”。在分析模式下,AI 的推理不再被短反馈循环驱动,而是被”理解现状 → 参考成熟方案 → 归因问题 → 设计方案”的长链条驱动。
为什么 AI 会陷入死循环
基于上述观察,AI 在长期对话中陷入低效循环的机制可以从三个层面理解。
局部搜索空间的限制。 大语言模型在生成代码修改时,其决策受到对话历史中最近交互的强烈影响。当用户的连续反馈都集中在同一个参数维度时,AI 的搜索空间会被压缩到这个维度上。它不会主动跳出说”这可能不是参数问题,而是方案问题”,因为对话历史中没有支持这种跳转的线索。这不是模型能力的缺陷,而是自回归生成机制的自然结果——下一个 token 的预测基于前文,而前文已经被”column 宽度”这个主题填满。会话一的 8 次 grid-template-columns 改动就是这一机制的直接证据:AI 始终在一个两维的搜索空间里(单位和数值)做局部搜索,从未访问过”也许应该用 flex”这个区域。
修复冲动的优先级。 AI 的 prompt 系统通常将”帮助用户解决问题”作为最高优先级目标。这意味着当用户报告问题时,AI 的默认响应是提供解决方案——通常以代码修改的形式。这种”快速响应”的倾向在简单问题上是高效的,但在复杂问题上会导致过早 commit、根因分析不足。会话一中的每一个新问题都触发了一次”回到 plan mode → 出方案 → 用户确认 → 实施”的完整循环,每次循环都产生了一个 commit,但大部分 commit 仅修改了一行 CSS。AI 在 plan mode 中展现了一定的分析能力,但当它切换到 build mode 后,这种分析能力就消失了——它变成了一个”只管执行当前方案”的工具。
对方案层面的归因缺失。 AI 擅长识别代码层面的错误——语法错误、类型不匹配、API 使用不当——但不太擅长识别方案层面的错误。当一种布局思路本身就有问题(如用 1fr 来决定内容区宽度),AI 更倾向于通过调整参数来补偿,而非质疑这个思路本身。这类似于一个程序员面对有结构缺陷的代码时反复重构局部变量,而不是重写架构。会话一中的 AI 在修复链条中展现出了对 CSS 属性的熟练操作——它知道 grid-template-columns 的语法,知道 fr 单位的含义,知道如何设置响应式断点。但它没有问”这个方向对不对”。会话二中的 AI 之所以能做出正确诊断,不是因为它的 CSS 知识比会话一的 AI 更强,而是因为它被引导去做了分析而非修复。
小结与建议
这次经历指向了几个值得注意的结论。
第一,AI 在局部调整上的表现确实可靠——每次修改 grid-template-columns 的 commit 都语法正确、注释清晰。但它不会主动跳出当前的搜索空间。当 AI 在同一个参数维度上调整了三次以上仍未解决问题,基本可以判断方向需要调整。会话一中的比例调整链(1:8:1 → 1:6:1 → 1:10:1)在第三次迭代时就应该触发这个判断。
第二,会话上下文对 AI 的思维路径有显著的锚定效应。长对话历史中的每一次失败尝试都会占据 AI 的注意力窗口。新建一个对话重置上下文后,AI 有机会从一个不包含错误尝试的起点重新分析问题。但光重置上下文不够——会话二成功的关键除了”换对话”,还包括新对话中起始 prompt 的策略调整。如果只是简单开一个新对话但继续用”帮我把这个布局修好”的 prompt,AI 仍然可能回到 grid-参数调优的老路上。
第三,“先出方案,确认后再动手”这个约束起到了关键作用。它将 AI 的执行模式从”修复”切换为”分析”,使得 AI 在产生代码变更之前完成了对项目结构、现有实现和参考方案的完整理解。这些理解步骤在直接进入 edit 的对话中很难被触发。从会话二的推理过程可以看到,AI 在分析阶段读完项目文件后,自然地将问题归因到了布局思路层面——这不是因为它的模型比会话一的聪明,而是因为它有空间去做这件事。
第四,修复链中的技术债积累值得注意。会话一中 9 个问题节点里有 6 个是修复上一问题引入的。这个比率意味着 AI 在复杂调试场景下的”修复”行为本身具有负收益倾向——每轮修复的期望净收益可能为负。当用户意识到自己在同一个对话中报告的问题类型在频繁切换时(先是宽度问题,然后是 TOC 白屏,然后是 z-index,然后是 Header 对齐),这本身就是一个信号:修复正在制造新问题,而非收敛旧问题。
AI 编程工具的效率不仅取决于模型的能力,还取决于人类如何组织指令、管理上下文和把握交互节奏。识别死循环、重置上下文、引导分析方向——这些判断目前仍然需要人来完成。