<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ai on Armstrong Yan</title><link>https://yanqian.github.io/zh/tags/ai/</link><description>Recent content in Ai on Armstrong Yan</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Thu, 13 Aug 2026 14:13:57 +0800</lastBuildDate><atom:link href="https://yanqian.github.io/zh/tags/ai/index.xml" rel="self" type="application/rss+xml"/><item><title>Hey Jarvis 的未来：当 AI 需要自己的入口</title><link>https://yanqian.github.io/zh/posts/publish/building-hey-jarvis-future/</link><pubDate>Thu, 13 Aug 2026 14:13:57 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/building-hey-jarvis-future/</guid><description>&lt;p&gt;在 &lt;a href="https://yanqian.github.io/zh/posts/publish/building-hey-jarvis/" &gt;这个系列的第一篇&lt;/a&gt; 里，我写到 Hey Jarvis 来自一个很小的需求：我和老婆晚上睡觉前聊天，遇到想知道的问题时，希望不用拿起手机，直接问一句就能得到答案。&lt;/p&gt;
&lt;p&gt;后来我做出了 Pipeline、Realtime 和 Mac App，也处理了 &lt;a href="https://yanqian.github.io/zh/posts/publish/building-hey-jarvis-voice-interaction/" &gt;语音交互&lt;/a&gt; 与 &lt;a href="https://yanqian.github.io/zh/posts/publish/building-hey-jarvis-mac-product/" &gt;Mac 产品化&lt;/a&gt; 中的一系列问题。&lt;/p&gt;
&lt;p&gt;做到这里以后，我反而越来越清楚地看到一个限制：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;AI 可以越来越聪明，但如果它没有一个自然、稳定并且值得信任的入口，它仍然只是一个需要被主动打开的应用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我最初很容易把这个问题归结为一句更情绪化的话：Siri 阻碍了 AI 助手的发展。&lt;/p&gt;
&lt;p&gt;现在我觉得，这句话只说对了一半。&lt;/p&gt;
&lt;h2 id="siri-既是助手也是系统入口"&gt;
 Siri 既是助手，也是系统入口
 &lt;a class="heading-link" href="#siri-%e6%97%a2%e6%98%af%e5%8a%a9%e6%89%8b%e4%b9%9f%e6%98%af%e7%b3%bb%e7%bb%9f%e5%85%a5%e5%8f%a3"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;从使用者的角度看，Siri 最特别的能力不一定是回答得有多聪明，而是它已经存在于系统里。&lt;/p&gt;
&lt;p&gt;它拥有唤醒词、锁屏入口、麦克风权限、系统界面和设备之间的身份。使用者不需要先找到一个应用，也不需要理解哪个后台进程正在运行。说出一句话，入口就在那里。&lt;/p&gt;
&lt;p&gt;第三方 AI 应用即使拥有更好的模型，也很难获得完全相同的位置。&lt;/p&gt;
&lt;p&gt;Apple 并非完全关闭第三方能力。通过 &lt;a href="https://developer.apple.com/documentation/appintents" class="external-link" target="_blank" rel="noopener"&gt;App Intents&lt;/a&gt;，应用可以把自己的动作和内容以结构化方式提供给 Siri、Apple Intelligence、Spotlight 和 Shortcuts。2026 年的更新还继续增加了长时间后台任务、可取消任务、跨设备实体以及敏感操作确认等能力。&lt;a href="https://www.apple.com/newsroom/2026/06/apple-unveils-next-generation-of-apple-intelligence-siri-ai-and-more/" class="external-link" target="_blank" rel="noopener"&gt;Apple 也已经公布新一代 Siri AI&lt;/a&gt;，强调个人上下文、屏幕理解、网络知识和跨应用操作。&lt;/p&gt;
&lt;p&gt;但这里有一个重要区别：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;把应用的能力提供给系统助手
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;≠
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;让应用自己成为系统助手
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;第三方可以把一个动作交给 Siri 调用，却不等于可以拥有自己的系统级唤醒词、在所有状态下持续等待，或者无摩擦地取代默认语音入口。&lt;/p&gt;
&lt;p&gt;一个很具体的例子是，Apple 目前确实允许第三方 conversational app 通过 iPhone 侧键启动，但&lt;a href="https://developer.apple.com/documentation/appintents/launching-your-voice-based-conversational-app-from-the-side-button-of-iphone" class="external-link" target="_blank" rel="noopener"&gt;官方的 assistant activation 能力&lt;/a&gt;只面向日本，需要专门的 Side Button Access entitlement，并受地区与设备条件限制。&lt;/p&gt;
&lt;p&gt;这说明 Apple 不是不知道第三方语音助手需要硬件入口。恰恰相反，这个入口重要到必须被平台单独定义、授权和限制。&lt;/p&gt;</description></item><item><title>Hey Jarvis 的困难 II：从 Demo 到 Mac 产品</title><link>https://yanqian.github.io/zh/posts/publish/building-hey-jarvis-mac-product/</link><pubDate>Thu, 13 Aug 2026 14:08:41 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/building-hey-jarvis-mac-product/</guid><description>&lt;p&gt;在 &lt;a href="https://yanqian.github.io/zh/posts/publish/building-hey-jarvis-voice-interaction/" &gt;上一篇&lt;/a&gt; 里，我写了 Hey Jarvis 怎样处理确认音、回声、打断和麦克风交接。&lt;/p&gt;
&lt;p&gt;当这些能力在终端和浏览器里跑通时，我一度觉得产品最困难的部分已经完成了。&lt;/p&gt;
&lt;p&gt;后来我才意识到，那只是证明了一条语音流程可以工作。&lt;/p&gt;
&lt;p&gt;一个 Demo 只需要在我准备好的环境里成功一次。一个产品则必须面对第一次安装、权限拒绝、窗口切换、电脑锁屏、系统睡眠、子进程崩溃和应用退出。它不但要成功，还要在无法成功时停在一个安全、诚实、可以恢复的状态。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Demo 证明一件事能发生。产品必须决定其他所有事情发生时怎么办。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="产品化不是给-python-加一个窗口"&gt;
 产品化不是给 Python 加一个窗口
 &lt;a class="heading-link" href="#%e4%ba%a7%e5%93%81%e5%8c%96%e4%b8%8d%e6%98%af%e7%bb%99-python-%e5%8a%a0%e4%b8%80%e4%b8%aa%e7%aa%97%e5%8f%a3"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;最早的 Hey Jarvis 由 Python 启动。Realtime 模式还需要打开一个 Chrome 页面，让浏览器负责 WebRTC 的麦克风和语音播放。&lt;/p&gt;
&lt;p&gt;这个结构适合开发，因为每一层都可以单独观察和调试。但如果把它直接包装成一个窗口，很多只存在于我电脑里的前提仍然没有消失：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;系统里已经安装了正确版本的 Python 和依赖；&lt;/li&gt;
&lt;li&gt;项目目录和 &lt;code&gt;.env&lt;/code&gt; 文件位于预期位置；&lt;/li&gt;
&lt;li&gt;Chrome 页面没有被重复打开；&lt;/li&gt;
&lt;li&gt;API Key 可以由开发环境读取；&lt;/li&gt;
&lt;li&gt;进程异常时，我知道应该去哪里看日志和怎样重新启动。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些都不是产品应该交给使用者理解的事情。&lt;/p&gt;
&lt;p&gt;在正式搭建 Mac App 之前，我先做了一个完全隔离的 Tauri 实验。它只回答一个问题：WKWebView 能不能在真实的 Apple Silicon Mac 上完成麦克风授权、Realtime 播放、自然打断、媒体释放，以及把麦克风还给 Python？&lt;/p&gt;
&lt;p&gt;实验成功以后，我没有继续在这份实验代码上追加功能，而是重新建立产品自己的应用外壳。&lt;/p&gt;
&lt;p&gt;这个选择看起来多走了一步，却帮我区分了两个很不一样的问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;实验：这条技术路线可不可行？
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;产品：它能否保护秘密、正确失败、恢复运行，并在另一台电脑上重现？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="三种运行环境三种责任"&gt;
 三种运行环境，三种责任
 &lt;a class="heading-link" href="#%e4%b8%89%e7%a7%8d%e8%bf%90%e8%a1%8c%e7%8e%af%e5%a2%83%e4%b8%89%e7%a7%8d%e8%b4%a3%e4%bb%bb"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;最终的 Hey Jarvis Mac App 分成三部分：&lt;/p&gt;</description></item><item><title>Hey Jarvis 的困难 I：让语音交互真正成立</title><link>https://yanqian.github.io/zh/posts/publish/building-hey-jarvis-voice-interaction/</link><pubDate>Thu, 13 Aug 2026 13:59:31 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/building-hey-jarvis-voice-interaction/</guid><description>&lt;p&gt;在 &lt;a href="https://yanqian.github.io/zh/posts/publish/building-hey-jarvis/" &gt;上一篇&lt;/a&gt; 里，我写到，Hey Jarvis 的第一个 Pipeline（串行语音处理流程）其实很快就实现了最初的需求。&lt;/p&gt;
&lt;p&gt;我说一句 “Hey Jarvis”，它录下问题，交给 AI 回答，再把答案读出来。&lt;/p&gt;
&lt;p&gt;如果只看流程图，这个语音助手已经完成了。&lt;/p&gt;
&lt;p&gt;但真正用起来以后，我发现语音交互里最困难的部分，往往不在“识别了什么”或者“回答了什么”，而在一些更基础的问题：它什么时候开始听？什么时候停止听？它能不能分清我的声音和自己的声音？一段对话结束以后，麦克风到底回到了谁手里？&lt;/p&gt;
&lt;p&gt;这些问题没有解决时，模型再聪明，使用者也会很快失去耐心。&lt;/p&gt;
&lt;h2 id="pipeline-的第一个问题它会听见自己"&gt;
 Pipeline 的第一个问题：它会听见自己
 &lt;a class="heading-link" href="#pipeline-%e7%9a%84%e7%ac%ac%e4%b8%80%e4%b8%aa%e9%97%ae%e9%a2%98%e5%ae%83%e4%bc%9a%e5%90%ac%e8%a7%81%e8%87%aa%e5%b7%b1"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;为了让我知道唤醒成功，Hey Jarvis 会先播放一句简短的确认音。&lt;/p&gt;
&lt;p&gt;最早是“在呢”，后来实时语音会话（Realtime）版本使用的是“嗯，我在，请说”。它听起来只是一个很小的体验细节，却引出了整个项目最早、也最反复的一类问题。&lt;/p&gt;
&lt;p&gt;Mac 的扬声器播放确认音时，旁边的麦克风也会收到这段声音。如果程序在确认音结束后才开始读取麦克风，那么音频缓冲区里可能还留着刚才的回声。对程序来说，这些数据和用户刚刚说出的话并没有天然区别。&lt;/p&gt;
&lt;p&gt;结果可能是这样的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;我说 “Hey Jarvis”
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ Jarvis 回答“在呢”
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ 麦克风重新收到“在呢”
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ Jarvis 以为用户已经开口
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ 录下一段错误的问题
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最直接的办法，是播放确认音时完全忽略麦克风。&lt;/p&gt;
&lt;p&gt;但这又制造了相反的问题。我听见“在呢”以后，可能会很自然地立刻开始说话，甚至在确认音的最后一个字还没有完全结束时就已经开口。如果这段时间的音频全部被丢掉，我的问题开头也会一起消失。&lt;/p&gt;
&lt;p&gt;比如我说“明天新加坡会下雨吗”，系统收到的可能只剩“新加坡会下雨吗”。这次看起来还能理解；换一个问题，少掉前几个字就可能完全改变意思。&lt;/p&gt;
&lt;p&gt;所以最终的处理不是简单地“听”或者“不听”，而是把确认音前后分成几个不同区域：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;确认音播放期间持续读取麦克风，避免旧声音堆积在缓冲区；&lt;/li&gt;
&lt;li&gt;明显属于扬声器回声、削波或溢出的片段不能成为“用户已经开口”的证据；&lt;/li&gt;
&lt;li&gt;靠近播放结束的一小段安全音频暂时保留，作为问题开头的候选；&lt;/li&gt;
&lt;li&gt;只有确认音结束后仍然观察到真实说话的迹象，候选音频才会进入正式录音；&lt;/li&gt;
&lt;li&gt;如果后面没有人继续说话，就安静地回到唤醒状态，不请求 AI。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这套逻辑还需要估计环境底噪，并在最近的一组音频片段里确认持续的人声，而不是因为某一个突然变大的声音就开始录音。开始录音时，它还会把前面大约半秒的音频一起带上，尽量不丢掉第一个字。&lt;/p&gt;
&lt;p&gt;一个原本只有两个状态的问题——“在听”或“没在听”——最后变成了对回声、底噪、连续语音和录音前缓冲的共同判断。&lt;/p&gt;
&lt;h2 id="我在应该是一句承诺"&gt;
 “我在”应该是一句承诺
 &lt;a class="heading-link" href="#%e6%88%91%e5%9c%a8%e5%ba%94%e8%af%a5%e6%98%af%e4%b8%80%e5%8f%a5%e6%89%bf%e8%af%ba"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Pipeline 里的确认音主要表示唤醒词已经被识别。&lt;/p&gt;
&lt;p&gt;到了实时语音模式，它的含义必须更加严格。&lt;/p&gt;
&lt;p&gt;唤醒之后，Hey Jarvis 需要释放本地唤醒使用的麦克风，建立网络连接，完成实时对话配置，准备好播放远端声音，再开放麦克风输入。如果确认音放得太早，我听见“我在”就开始说话，但实时对话可能还没准备好，我说出的内容会直接消失。&lt;/p&gt;
&lt;p&gt;所以我后来给这句确认音定义了一个产品层面的含义：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当“嗯，我在，请说”播放完，Hey Jarvis 才应该真正准备好听我说话。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;实现这句话，需要等待两个条件：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;实时对话已经配置完成
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ＋
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;确认音已经播放完成
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;开放麦克风输入
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这两个过程可以同时进行，但任何一个没有完成，用户输入都不能开放。&lt;/p&gt;</description></item><item><title>我做了一个 Hey Jarvis：从睡前的一个问题开始</title><link>https://yanqian.github.io/zh/posts/publish/building-hey-jarvis/</link><pubDate>Thu, 13 Aug 2026 13:55:06 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/building-hey-jarvis/</guid><description>&lt;p&gt;我和老婆晚上睡觉前经常会聊天。&lt;/p&gt;
&lt;p&gt;有时候聊的是一天里发生的事情，有时候会从一件小事跳到历史、科技、健康或者某个我们突然想到的知识点。聊着聊着，总会遇到一些我们都不知道、但又很想马上知道答案的问题。&lt;/p&gt;
&lt;p&gt;这时候，最自然的动作本来应该是直接问一句。&lt;/p&gt;
&lt;p&gt;但现实里的动作通常是：伸手去找手机，解锁，打开一个应用，点进输入框，再把刚才的问题重新组织一遍。等答案出现时，原来的聊天已经被打断了。&lt;/p&gt;
&lt;p&gt;语音助手本来应该最适合这个场景。可我真正想问的问题，Siri 经常回答不了；而更聪明的 AI，又往往住在一个需要主动打开的窗口里。&lt;/p&gt;
&lt;p&gt;我想要的其实很简单：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;躺在床上说一句 “Hey Jarvis”，它就能加入我们的对话，回答刚才的问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;于是我开始做 Hey Jarvis。&lt;/p&gt;
&lt;p&gt;功能演示：&lt;a href="https://www.youtube.com/watch?v=PDHQiYzFAXQ&amp;amp;t=9s" class="external-link" target="_blank" rel="noopener"&gt;&lt;strong&gt;中文版：让 Siri 级别的唤醒接上 ChatGPT&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;项目与下载：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/yanqian/hey-jarvis" class="external-link" target="_blank" rel="noopener"&gt;源代码：yanqian/hey-jarvis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/yanqian/hey-jarvis/releases/tag/v0.1.0-internal" class="external-link" target="_blank" rel="noopener"&gt;v0.1.0 INTERNAL-UNSIGNED 内部评估版&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="第一个版本其实很快就能工作"&gt;
 第一个版本，其实很快就能工作
 &lt;a class="heading-link" href="#%e7%ac%ac%e4%b8%80%e4%b8%aa%e7%89%88%e6%9c%ac%e5%85%b6%e5%ae%9e%e5%be%88%e5%bf%ab%e5%b0%b1%e8%83%bd%e5%b7%a5%e4%bd%9c"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Hey Jarvis 的第一版是一条很直接的 Pipeline，也就是一条串行语音处理流程：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;本地等待 “Hey Jarvis”
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ 播放一句确认音
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ 录下问题
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ 把语音转成文字
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ 让模型生成答案
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ 把答案转成语音并播放
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ 回到唤醒状态
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从功能定义上说，做到这里已经实现了最初的需求。&lt;/p&gt;
&lt;p&gt;我不需要拿起手机。只要说出唤醒词，再问一个问题，它就会把答案讲出来。为了避免所有声音一直上传，唤醒词检测在本地完成；只有被唤醒之后录下的问题，才会进入后面的 AI 流程。&lt;/p&gt;
&lt;p&gt;我还给它加了一些确定性的工具。时间和计算可以在本地完成；天气、汇率和股票价格由明确的数据提供方返回。对于这些会随时间变化的问题，我不希望模型凭记忆猜一个听起来很像真的答案。&lt;/p&gt;
&lt;p&gt;如果目标只是做一段功能演示，项目大概已经可以停在这里。&lt;/p&gt;
&lt;p&gt;但当我真的开始使用它，我发现：&lt;strong&gt;能够用语音问 AI，与拥有一个语音助手，并不是同一件事。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="pipeline-能回答问题但它还不会对话"&gt;
 Pipeline 能回答问题，但它还不会对话
 &lt;a class="heading-link" href="#pipeline-%e8%83%bd%e5%9b%9e%e7%ad%94%e9%97%ae%e9%a2%98%e4%bd%86%e5%ae%83%e8%bf%98%e4%b8%8d%e4%bc%9a%e5%af%b9%e8%af%9d"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;第一版更像一个由语音启动的命令行程序。&lt;/p&gt;
&lt;p&gt;我问完一个问题，它录音、思考、播放答案，然后整段交互结束。想继续追问，就要再说一次 “Hey Jarvis”。如果回答说得太长，我不能像人与人聊天一样插话；我只能等它讲完。&lt;/p&gt;
&lt;p&gt;人与人对话时，我们很少意识到自己在做这些事情：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;听到对方回应后，知道他已经准备好听了；&lt;/li&gt;
&lt;li&gt;在对方说话时插入一句，对方会停下来；&lt;/li&gt;
&lt;li&gt;用“那明天呢”继续追问，而不必重新交代上下文；&lt;/li&gt;
&lt;li&gt;聊完说一句“再见”，双方都知道对话结束了。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些在人类交流中近乎本能的行为，到了软件里都会变成明确的状态、事件和边界。&lt;/p&gt;</description></item><item><title>我做了一个小型 Harness，防止 AI 编程项目丢失状态</title><link>https://yanqian.github.io/zh/posts/publish/i-built-a-small-harness-to-stop-ai-coding-projects-from-forgetting-state/</link><pubDate>Tue, 21 Jul 2026 09:21:48 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/i-built-a-small-harness-to-stop-ai-coding-projects-from-forgetting-state/</guid><description>&lt;p&gt;AI 编程智能体很强大。&lt;/p&gt;
&lt;p&gt;但项目一旦拉长，往往会在一些非常具体的地方出问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;会话突然中断&lt;/li&gt;
&lt;li&gt;上下文越积越长&lt;/li&gt;
&lt;li&gt;每周额度耗尽&lt;/li&gt;
&lt;li&gt;第二天接手的智能体忘了前一天做过哪些决定&lt;/li&gt;
&lt;li&gt;智能体改动了无关文件&lt;/li&gt;
&lt;li&gt;工作明明还没完成，智能体却提前宣布结束&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;问题不在于 AI 不会写代码。&lt;/p&gt;
&lt;p&gt;真正的问题是，AI 编程项目往往没有持久的项目状态。&lt;/p&gt;
&lt;p&gt;所以，我做了一个小型开源模板：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/yanqian/ai-agent-harness-template" class="external-link" target="_blank" rel="noopener"&gt;ai-agent-harness-template&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;它的目标很简单：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;让 AI 编程项目随时都能恢复并继续推进。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="这不是提示词合集"&gt;
 这不是提示词合集
 &lt;a class="heading-link" href="#%e8%bf%99%e4%b8%8d%e6%98%af%e6%8f%90%e7%a4%ba%e8%af%8d%e5%90%88%e9%9b%86"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;现在已经有很多实用的提示词合集。&lt;/p&gt;
&lt;p&gt;但这个模板不是。&lt;/p&gt;
&lt;p&gt;它是一套仓库级 Harness，专门用于需要长期推进的 AI 编程项目。&lt;/p&gt;
&lt;p&gt;适用工具包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Codex&lt;/li&gt;
&lt;li&gt;Claude Code&lt;/li&gt;
&lt;li&gt;Cursor Agent&lt;/li&gt;
&lt;li&gt;其他类似的编程智能体&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不过，它不依赖任何一家厂商。&lt;/p&gt;
&lt;p&gt;控制边界就是仓库本身。&lt;/p&gt;
&lt;h2 id="核心思路"&gt;
 核心思路
 &lt;a class="heading-link" href="#%e6%a0%b8%e5%bf%83%e6%80%9d%e8%b7%af"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;应该把智能体当作无状态工作进程来用。&lt;/p&gt;
&lt;p&gt;它们不该依赖聊天记录。&lt;/p&gt;
&lt;p&gt;每次开始工作时，都应该根据仓库文件重新建立上下文。&lt;/p&gt;
&lt;p&gt;这个模板把持久状态保存在以下文件中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SPEC.md&lt;/code&gt;：保存需求&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feature_list.json&lt;/code&gt;：保存可执行的功能状态&lt;/li&gt;
&lt;li&gt;&lt;code&gt;progress.md&lt;/code&gt;：保存恢复工作所需的记录&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;：保存智能体规则&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QUALITY.md&lt;/code&gt;：保存评估标准&lt;/li&gt;
&lt;li&gt;&lt;code&gt;runs/&lt;/code&gt;：保存证据和交接记录&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这样一来，后来接手的智能体、人工维护者和 CI 都以同一份信息为准。&lt;/p&gt;
&lt;p&gt;仓库现在还提供了一个可安装的 AI Agent Harness skill。&lt;/p&gt;
&lt;p&gt;这个 skill 不是另一套数据库。&lt;/p&gt;
&lt;p&gt;它只是同一套仓库状态协议的便捷入口。&lt;/p&gt;
&lt;p&gt;真正持久的记忆依然留在仓库里。&lt;/p&gt;
&lt;h2 id="为什么聊天记录不适合充当数据库"&gt;
 为什么聊天记录不适合充当数据库
 &lt;a class="heading-link" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%81%8a%e5%a4%a9%e8%ae%b0%e5%bd%95%e4%b8%8d%e9%80%82%e5%90%88%e5%85%85%e5%bd%93%e6%95%b0%e6%8d%ae%e5%ba%93"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;聊天记录可以提供有用的上下文。&lt;/p&gt;</description></item><item><title>远程智能体工作流</title><link>https://yanqian.github.io/zh/posts/publish/remote-agent-workflow/</link><pubDate>Tue, 21 Jul 2026 09:03:39 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/remote-agent-workflow/</guid><description>&lt;p&gt;这个系列探讨如何从移动端 SSH 走向一套以代码仓库为依托、可以长期运行的 AI 智能体工作流。&lt;/p&gt;
&lt;p&gt;起因很简单：离开 Mac 后，我仍然想继续推进本地的 Codex 工作。&lt;/p&gt;
&lt;p&gt;但随着实践深入，问题很快变成了：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;怎样才能把远程访问转变为一套可恢复、可验证、可以长期运行的智能体工作流？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="系列文章"&gt;
 系列文章
 &lt;a class="heading-link" href="#%e7%b3%bb%e5%88%97%e6%96%87%e7%ab%a0"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://yanqian.github.io/posts/publish/remote-mac-terminal-for-codex/" &gt;远程智能体工作流（一）：用手机连接 Mac 运行 Codex&lt;/a&gt;&lt;br&gt;
借助 Tailscale、SSH、Termius、tmux 和 caffeinate，打通手机到 Mac 的终端连接。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://yanqian.github.io/posts/publish/from-remote-shell-to-agent-control-plane/" &gt;远程智能体工作流（二）：从远程 Shell 到智能体控制面&lt;/a&gt;&lt;br&gt;
解释为什么移动端 SSH 虽然是实用的基础设施，却不适合充当长期智能体任务的日常操作界面。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://yanqian.github.io/posts/publish/turning-telegram-into-a-local-codex-control-plane/" &gt;远程智能体工作流（三）：把 Telegram 变成本地 Codex 的控制面&lt;/a&gt;&lt;br&gt;
让 Telegram Bot 以轮询模式运行，把它变成一个轻量的移动端控制界面，用手机就能指挥本地 Codex 任务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://yanqian.github.io/posts/publish/in-the-repository-not-in-the-chat/" &gt;远程智能体工作流（四）：在仓库中，而非聊天中&lt;/a&gt;&lt;br&gt;
让代码仓库同时承载智能体记忆、运行约定，并成为 Agent Harness。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://yanqian.github.io/posts/publish/what-still-matters-after-codex-mobile/" &gt;远程智能体工作流（五）：Codex Mobile 之后，什么依然重要&lt;/a&gt;&lt;br&gt;
官方 Codex Mobile 推出后，重新审视这套自建工作流：它不是替代品，而是项目侧的工作流适配器。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="核心演进路径"&gt;
 核心演进路径
 &lt;a class="heading-link" href="#%e6%a0%b8%e5%bf%83%e6%bc%94%e8%bf%9b%e8%b7%af%e5%be%84"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;远程终端
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 远程运行环境
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 移动端控制面
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 仓库记忆
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 基于仓库的 Agent Harness
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 工作流适配器
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;目的并不是证明哪一种界面更好。&lt;/p&gt;</description></item><item><title>远程智能体工作流（五）：Codex Mobile 之后，什么依然重要</title><link>https://yanqian.github.io/zh/posts/publish/what-still-matters-after-codex-mobile/</link><pubDate>Mon, 20 Jul 2026 23:52:52 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/what-still-matters-after-codex-mobile/</guid><description>&lt;p&gt;这是“远程智能体工作流”系列的第五篇。&lt;/p&gt;
&lt;p&gt;最初搭建这套远程 AI 开发环境时，我想解决一个很实际的问题：&lt;/p&gt;
&lt;p&gt;离开 Mac 以后，怎样让本地 Codex 继续干活？&lt;/p&gt;
&lt;p&gt;于是有了第一层方案：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;手机 -&amp;gt; Tailscale -&amp;gt; SSH -&amp;gt; Mac -&amp;gt; tmux -&amp;gt; Codex
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;后来我发现，手机上的 SSH 不适合充当日常操作入口，于是又搭了一个 Telegram 控制面：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;手机 -&amp;gt; Telegram Bot -&amp;gt; 本地 Codex 运行时 -&amp;gt; 指定代码仓库
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再往后，我意识到背后还有一条更根本的原则：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;放在代码仓库里，不要放在聊天里。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;代码仓库必须保存持久的项目记忆。&lt;/p&gt;
&lt;p&gt;更准确地说，它应该承载项目记忆、运行约定和反馈机制。&lt;/p&gt;
&lt;p&gt;走到这一步，一个很自然的问题随之而来：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;既然官方已经推出 Codex Mobile，自定义远程智能体工作流还有必要吗？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我的答案是：有。但理由变了。&lt;/p&gt;
&lt;p&gt;它的价值不再只是让人远程接入 Codex。&lt;/p&gt;
&lt;p&gt;更重要的是让 Codex 按照项目自己的方式工作。&lt;/p&gt;
&lt;h2 id="codex-mobile-解决了什么"&gt;
 Codex Mobile 解决了什么
 &lt;a class="heading-link" href="#codex-mobile-%e8%a7%a3%e5%86%b3%e4%ba%86%e4%bb%80%e4%b9%88"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;2026 年 5 月 14 日，OpenAI 宣布在 ChatGPT 移动应用中以预览形式推出 Codex。&lt;/p&gt;
&lt;p&gt;通过官方移动端，用户可以随时在手机上接入 Codex。按照 OpenAI 的介绍，你可以跨线程处理任务、检查输出、批准命令、切换模型、发起新任务，还能实时收到终端输出、差异内容、测试结果、截图和审批请求等更新。&lt;/p&gt;</description></item><item><title>远程智能体工作流（四）：在仓库中，而非聊天中</title><link>https://yanqian.github.io/zh/posts/publish/in-the-repository-not-in-the-chat/</link><pubDate>Mon, 20 Jul 2026 23:33:28 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/in-the-repository-not-in-the-chat/</guid><description>&lt;p&gt;这是“远程智能体工作流”系列的第四篇。&lt;/p&gt;
&lt;p&gt;我的远程 AI 开发环境，第一层解决连接问题。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;手机 -&amp;gt; Tailscale -&amp;gt; SSH -&amp;gt; Mac -&amp;gt; tmux -&amp;gt; Codex
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;有了这条链路，我可以用手机访问 Mac，也能让耗时较长的本地任务持续运行。&lt;/p&gt;
&lt;p&gt;第二层解决控制问题。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;手机 -&amp;gt; Telegram Bot -&amp;gt; 本地 Codex 运行时 -&amp;gt; 选定的仓库
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样一来，手机就成了控制入口，而不再是一台屏幕很小的终端。&lt;/p&gt;
&lt;p&gt;但这两层都没有触及更深的问题。&lt;/p&gt;
&lt;p&gt;远程访问让我能连上机器。&lt;/p&gt;
&lt;p&gt;远程控制让我能启动任务、查看进展。&lt;/p&gt;
&lt;p&gt;而长时间运行的智能体开发还需要记忆。&lt;/p&gt;
&lt;p&gt;智能体可能在我离开后继续运行，也可能从中断处恢复、换一个会话接着做，或者由我通过手机操控。既然如此，整个项目就不能只存在于一条聊天线程里。&lt;/p&gt;
&lt;p&gt;于是，我给自己定了一条规则：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;聊天用来传达指令。&lt;br&gt;
仓库用来保存记忆。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;更准确地说，仓库不只是存放代码的地方。它还承载着智能体的记忆和操作约定，并为智能体提供持续的反馈机制。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://yanqian.github.io/posts/publish/in-the-repository-not-in-the-chat/assets/in-the-repository-not-in-the-chat/01-repository-agent-harness.svg" alt="作为 Agent Harness 的仓库"&gt;&lt;/p&gt;
&lt;h2 id="为什么聊天记录不能充当项目状态"&gt;
 为什么聊天记录不能充当项目状态
 &lt;a class="heading-link" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%81%8a%e5%a4%a9%e8%ae%b0%e5%bd%95%e4%b8%8d%e8%83%bd%e5%85%85%e5%bd%93%e9%a1%b9%e7%9b%ae%e7%8a%b6%e6%80%81"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;聊天很适合表达意图。&lt;/p&gt;
&lt;p&gt;我可以在聊天里说明目标、提出问题、纠正方向，或者做出产品决策。&lt;/p&gt;
&lt;p&gt;但要长期保存项目状态，聊天并不可靠。&lt;/p&gt;
&lt;p&gt;聊天内容难以比较差异，也不便验证；它依附于某一条线程，后续会话中的智能体很容易误解，甚至根本看不到。想法、日志、猜测、决定和已经过时的背景信息，往往全都混在同一条信息流里。&lt;/p&gt;
&lt;p&gt;如果只是一次性的小改动，这样做未尝不可。&lt;/p&gt;
&lt;p&gt;可一旦智能体需要长时间工作，问题就会暴露出来。&lt;/p&gt;
&lt;p&gt;项目必须能稳定回答以下问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这个系统应该做什么？&lt;/li&gt;
&lt;li&gt;哪些内容已经实现？&lt;/li&gt;
&lt;li&gt;以前在哪里失败过？&lt;/li&gt;
&lt;li&gt;什么证据能证明这些行为现在仍然正常？&lt;/li&gt;
&lt;li&gt;下一个智能体在修改文件之前，应该先读什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些答案应该和代码放在一起。&lt;/p&gt;
&lt;h2 id="让仓库同时承担记忆与-agent-harness"&gt;
 让仓库同时承担记忆与 Agent Harness
 &lt;a class="heading-link" href="#%e8%ae%a9%e4%bb%93%e5%ba%93%e5%90%8c%e6%97%b6%e6%89%bf%e6%8b%85%e8%ae%b0%e5%bf%86%e4%b8%8e-agent-harness"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;在我的项目里，智能体需要长期保留的状态通常分散在以下文件和记录中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SPEC.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feature_list.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;progress.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;test_plan.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;init.sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;orchestrator.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;git 历史&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;文件具体叫什么并不重要，重要的是分清职责。&lt;/p&gt;</description></item><item><title>远程智能体工作流（三）：把 Telegram 变成本地 Codex 的控制面</title><link>https://yanqian.github.io/zh/posts/publish/turning-telegram-into-a-local-codex-control-plane/</link><pubDate>Mon, 20 Jul 2026 23:20:13 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/turning-telegram-into-a-local-codex-control-plane/</guid><description>&lt;p&gt;这是「远程智能体工作流」系列的第三篇。&lt;/p&gt;
&lt;p&gt;前两篇文章里，我先搭出了一条实用的远程终端链路：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;手机 -&amp;gt; Tailscale -&amp;gt; SSH -&amp;gt; Mac -&amp;gt; tmux -&amp;gt; Codex
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;有了这条链路，我就能可靠地从手机连接自己的 Mac。&lt;/p&gt;
&lt;p&gt;但新的局限很快就暴露出来：手机并不好用来操作终端。&lt;/p&gt;
&lt;p&gt;移动端 SSH 适合救急，但我不想靠它处理需要长时间运行的 AI 开发任务。我不想在狭窄的手机屏幕上敲 shell 命令、连接 tmux 会话、翻找长篇日志，再一点点拼凑出当前状态。&lt;/p&gt;
&lt;p&gt;我真正想要的，是下面这样的链路：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;手机 -&amp;gt; 任务式接口 -&amp;gt; 本地智能体运行时 -&amp;gt; 仓库状态
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;于是，我做了一个小型 Telegram Bot，把它用作本地 Codex 的控制面。&lt;/p&gt;
&lt;p&gt;关键不在于 Telegram 有多特别。&lt;/p&gt;
&lt;p&gt;真正重要的是：手机成为控制界面，而 Mac 仍然负责执行工作。&lt;/p&gt;
&lt;h2 id="为什么选-telegram"&gt;
 为什么选 Telegram
 &lt;a class="heading-link" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e9%80%89-telegram"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Telegram 很适合用来做这个实验，因为它已经具备：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;移动端通知&lt;/li&gt;
&lt;li&gt;简短的命令消息&lt;/li&gt;
&lt;li&gt;回复串&lt;/li&gt;
&lt;li&gt;内联按钮&lt;/li&gt;
&lt;li&gt;跨设备历史记录&lt;/li&gt;
&lt;li&gt;成熟的 Bot API&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更重要的是，Telegram 支持两种截然不同的部署模式。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://yanqian.github.io/posts/publish/turning-telegram-into-a-local-codex-control-plane/assets/turning-telegram-into-a-local-codex-control-plane/01-webhook-vs-polling.svg" alt="Telegram 的 webhook 与 polling 模式"&gt;&lt;/p&gt;
&lt;p&gt;第一种是 webhook 模式：&lt;/p&gt;</description></item><item><title>远程智能体工作流（二）：从远程 Shell 到智能体控制面</title><link>https://yanqian.github.io/zh/posts/publish/from-remote-shell-to-agent-control-plane/</link><pubDate>Mon, 20 Jul 2026 22:33:24 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/from-remote-shell-to-agent-control-plane/</guid><description>&lt;p&gt;这是“远程智能体工作流”系列的第二篇。&lt;/p&gt;
&lt;p&gt;上一篇文章里，我搭建了一套实用的远程终端工作流：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;手机 -&amp;gt; Tailscale -&amp;gt; SSH -&amp;gt; Mac -&amp;gt; tmux -&amp;gt; Codex
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这套方案解决了第一个问题：离开书桌后，怎样连回自己的 Mac；手机断开后，怎样让本地智能体继续执行耗时较长的任务。&lt;/p&gt;
&lt;p&gt;它很快就派上了用场。&lt;/p&gt;
&lt;p&gt;但在实际使用后，我又发现了第二个问题。&lt;/p&gt;
&lt;p&gt;SSH 解决了连通性，却不会自动带来一套好用的远程开发工作流。&lt;/p&gt;
&lt;p&gt;移动端 SSH 用得越多，它的边界就越清楚：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;手机不该被当成一台微型终端。&lt;br&gt;
手机应该成为本地智能体工作流的控制面。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="第一层解决的是基础设施"&gt;
 第一层解决的是基础设施
 &lt;a class="heading-link" href="#%e7%ac%ac%e4%b8%80%e5%b1%82%e8%a7%a3%e5%86%b3%e7%9a%84%e6%98%af%e5%9f%ba%e7%a1%80%e8%ae%be%e6%96%bd"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;远程终端这套配置仍然不可或缺。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://yanqian.github.io/posts/publish/from-remote-shell-to-agent-control-plane/assets/remote-mac-terminal-for-codex/01-remote-architecture.svg" alt="远程终端架构"&gt;&lt;/p&gt;
&lt;p&gt;我需要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 Tailscale 连接手机与 Mac，又不把 SSH 暴露在公网上。&lt;/li&gt;
&lt;li&gt;用 SSH 安全登录。&lt;/li&gt;
&lt;li&gt;用 tmux 保证耗时较长的任务不会因连接断开而终止。&lt;/li&gt;
&lt;li&gt;用 caffeinate 防止 Mac 在智能体工作期间休眠。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这样，我就有了一套可靠的基础能力：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;我可以连上机器。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;我可以启动工作。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;我可以断开连接。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;我可以稍后再连回来。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这是很实在的一步。&lt;/p&gt;
&lt;p&gt;但它只回答了基础设施层面的问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;我能连到这台机器吗？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;它没有回答工作流层面的问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;我能顺畅地用手机推动耗时较长的 AI 开发工作吗？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对我来说，答案是否定的。&lt;/p&gt;
&lt;h2 id="手机并不是一台好终端"&gt;
 手机并不是一台好终端
 &lt;a class="heading-link" href="#%e6%89%8b%e6%9c%ba%e5%b9%b6%e4%b8%8d%e6%98%af%e4%b8%80%e5%8f%b0%e5%a5%bd%e7%bb%88%e7%ab%af"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;移动端 SSH 很适合应急访问。&lt;/p&gt;</description></item><item><title>远程智能体工作流（一）：用手机连接 Mac 运行 Codex</title><link>https://yanqian.github.io/zh/posts/publish/remote-mac-terminal-for-codex/</link><pubDate>Mon, 20 Jul 2026 22:15:53 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/remote-mac-terminal-for-codex/</guid><description>&lt;p&gt;本文是“远程代理工作流”系列的第一篇。&lt;/p&gt;
&lt;p&gt;这篇指南将介绍如何用手机操作 Mac 终端，并让 Codex、自动化脚本、本地开发代理等长时间任务持续运行。&lt;/p&gt;
&lt;p&gt;我们要搭建的不是远程桌面，而是一套可靠的远程终端工作流：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;手机 -&amp;gt; SSH -&amp;gt; Mac -&amp;gt; tmux -&amp;gt; Codex / 代理任务
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;配置完成后，Mac 就会成为一个轻量的远程执行节点。无论身在何处，你都可以用手机接入。&lt;/p&gt;
&lt;h2 id="各个工具分别做什么"&gt;
 各个工具分别做什么
 &lt;a class="heading-link" href="#%e5%90%84%e4%b8%aa%e5%b7%a5%e5%85%b7%e5%88%86%e5%88%ab%e5%81%9a%e4%bb%80%e4%b9%88"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="ssh"&gt;
 SSH
 &lt;a class="heading-link" href="#ssh"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;SSH 是一种安全的远程登录协议，可以让你从手机进入 Mac 的终端。&lt;/p&gt;
&lt;p&gt;在这套工作流中，SSH 负责：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安全访问 Mac 的命令行。&lt;/li&gt;
&lt;li&gt;使用密码或 SSH 密钥验证身份。&lt;/li&gt;
&lt;li&gt;从手机远程执行命令。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不过，SSH 一旦断开，并不能保证任务继续运行。这正是我们还需要 tmux 的原因。&lt;/p&gt;
&lt;h3 id="tailscale"&gt;
 Tailscale
 &lt;a class="heading-link" href="#tailscale"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Tailscale 会在你的设备之间建立私有网络。即使 Mac 和手机接入不同的网络，两台设备也能通过稳定的私有 IP 地址互相访问。&lt;/p&gt;
&lt;p&gt;在这套工作流中，Tailscale 负责：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;让你通过 4G、5G、酒店 Wi-Fi、公司 Wi-Fi 或家庭 Wi-Fi 远程访问 Mac。&lt;/li&gt;
&lt;li&gt;为 Mac 提供稳定的 &lt;code&gt;100.x.x.x&lt;/code&gt; 地址。&lt;/li&gt;
&lt;li&gt;加密设备之间的网络通信。&lt;/li&gt;
&lt;li&gt;避免将 SSH 直接暴露在公网上。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本文默认使用官方 Tailscale macOS 客户端。在这种配置下，后台服务、登录状态和菜单栏状态都由该应用管理。&lt;/p&gt;</description></item><item><title>AI 原生软件工程（四）：氛围编程无法取代人的判断</title><link>https://yanqian.github.io/zh/posts/publish/against-vibe-coding-why-human-judgment-still-matters/</link><pubDate>Sat, 18 Jul 2026 23:53:44 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/against-vibe-coding-why-human-judgment-still-matters/</guid><description>&lt;p&gt;实现可以自动化，评估也可以自动化。但判断，始终只能由人来做。&lt;/p&gt;
&lt;p&gt;这是“AI 原生软件工程”系列的第四篇。&lt;/p&gt;
&lt;p&gt;本文接续上一篇：&lt;a href="https://yanqian.github.io/zh/posts/publish/software-is-becoming-search-why-engineers-are-turning-into-constraint-designers/" &gt;AI 原生软件工程（三）：软件即搜索&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;第一篇追问，我们如何形成理解。&lt;/p&gt;
&lt;p&gt;第二篇追问，我们如何获得正确性。&lt;/p&gt;
&lt;p&gt;第三篇提出，软件正在变成一种搜索过程。&lt;/p&gt;
&lt;p&gt;但有一个危险的误解，必须说清楚：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;只要有智能体、验证框架和约束，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;软件就能自行生产出来。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;事实并非如此。&lt;/p&gt;
&lt;p&gt;在第二篇里，约束帮助我们获得正确性。&lt;/p&gt;
&lt;p&gt;在第三篇里，约束塑造了实现方案的搜索过程。&lt;/p&gt;
&lt;p&gt;这一篇要继续追问：谁来为约束本身负责？&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;谁来决定该优化什么，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;该拒绝什么，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;又有哪些东西从一开始就值得做？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;开始采用 AI 辅助的软件开发流程后，我注意到一个出乎意料的现象。&lt;/p&gt;
&lt;p&gt;实现能力越强，判断反而越有价值。&lt;/p&gt;
&lt;p&gt;起初，我觉得这有些反常。&lt;/p&gt;
&lt;p&gt;AI 越强，人的决策不应该越不重要吗？&lt;/p&gt;
&lt;p&gt;结果恰恰相反。&lt;/p&gt;
&lt;p&gt;实现不再是瓶颈。&lt;/p&gt;
&lt;p&gt;方向才是。&lt;/p&gt;
&lt;h2 id="氛围编程好用直到失控"&gt;
 氛围编程：好用，直到失控
 &lt;a class="heading-link" href="#%e6%b0%9b%e5%9b%b4%e7%bc%96%e7%a8%8b%e5%a5%bd%e7%94%a8%e7%9b%b4%e5%88%b0%e5%a4%b1%e6%8e%a7"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;大多数开发者都经历过这样的过程。&lt;/p&gt;
&lt;p&gt;一开始，你只有一个简单的想法：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;把 X 做出来。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;AI 生成代码。&lt;/p&gt;
&lt;p&gt;你稍作调整。&lt;/p&gt;
&lt;p&gt;跑通了。&lt;/p&gt;
&lt;p&gt;于是继续往下做。&lt;/p&gt;
&lt;p&gt;一个个小胜利不断累积。&lt;/p&gt;
&lt;p&gt;项目也渐渐变大。&lt;/p&gt;
&lt;p&gt;直到某个时刻，问题突然一股脑冒了出来：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;架构渐渐偏离原来的方向&lt;/li&gt;
&lt;li&gt;抽象层越堆越多&lt;/li&gt;
&lt;li&gt;调试越来越慢&lt;/li&gt;
&lt;li&gt;对系统的信心彻底崩塌&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;系统依然能运行。&lt;/p&gt;
&lt;p&gt;但已经没人说得清，它为什么能运行。&lt;/p&gt;
&lt;p&gt;项目陷入一种奇怪的状态：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;好像一切都能推倒重来。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;却没有任何东西真正处于掌控之中。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我把这叫作氛围编程。&lt;/p&gt;
&lt;p&gt;并不是因为 AI 不好。&lt;/p&gt;
&lt;p&gt;而是因为，每一步进展都不再对应一个经过认真权衡的决定。&lt;/p&gt;
&lt;h2 id="测试通过带来的错觉"&gt;
 测试通过带来的错觉
 &lt;a class="heading-link" href="#%e6%b5%8b%e8%af%95%e9%80%9a%e8%bf%87%e5%b8%a6%e6%9d%a5%e7%9a%84%e9%94%99%e8%a7%89"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;面对这种问题，一个常见的回答是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;多加一些测试就好了。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我也这样做过。&lt;/p&gt;</description></item><item><title>AI 原生软件工程（三）：软件即搜索</title><link>https://yanqian.github.io/zh/posts/publish/software-is-becoming-search-why-engineers-are-turning-into-constraint-designers/</link><pubDate>Sat, 18 Jul 2026 23:37:09 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/software-is-becoming-search-why-engineers-are-turning-into-constraint-designers/</guid><description>&lt;p&gt;当实现变得唾手可得，工程就不再那么像建造，而更像导航。&lt;/p&gt;
&lt;p&gt;这是“AI 原生软件工程”系列的第三篇。&lt;/p&gt;
&lt;p&gt;本文承接上一篇：&lt;a href="https://yanqian.github.io/zh/posts/publish/harness-engineering-is-about-limiting-ai-not-empowering-it/" &gt;AI 原生软件工程（二）：验证框架工程与正确性&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;第一篇追问：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;当实现工作交给 AI 后，理解从何而来？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;第二篇追问：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;当生成的成本变得低廉，如何保证正确性？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这一篇要问：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;如果实现越来越便宜，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;工程师究竟在做什么？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这里，约束的含义发生了变化。&lt;/p&gt;
&lt;p&gt;第二篇谈约束，是为了保证正确性。&lt;/p&gt;
&lt;p&gt;这一篇谈约束，是为了界定搜索范围：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;如何划定可接受实现的范围？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;纵观软件发展史的大部分时期，开发软件就意味着把它建造出来。&lt;/p&gt;
&lt;p&gt;先有一个想法。&lt;/p&gt;
&lt;p&gt;然后设计架构。&lt;/p&gt;
&lt;p&gt;接着编写实现。&lt;/p&gt;
&lt;p&gt;最后测试结果。&lt;/p&gt;
&lt;p&gt;瓶颈显而易见：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;写代码。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我们对工程能力的理解，也一直建立在这个前提之上。&lt;/p&gt;
&lt;p&gt;人们眼中的优秀工程师，往往能够：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;更快写出实现&lt;/li&gt;
&lt;li&gt;更快完成调试&lt;/li&gt;
&lt;li&gt;熟记更多 API&lt;/li&gt;
&lt;li&gt;精通更多框架&lt;/li&gt;
&lt;li&gt;交付更多可以运行的代码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI 正在动摇这个前提。&lt;/p&gt;
&lt;p&gt;不是因为它会取代工程师。&lt;/p&gt;
&lt;p&gt;而是因为它让实现成本骤降。&lt;/p&gt;
&lt;p&gt;一旦实现变得便宜，软件开发的方式也会随之改变。&lt;/p&gt;
&lt;p&gt;它开始变得像一场搜索。&lt;/p&gt;
&lt;h2 id="传统工程在实现稀缺时做建造"&gt;
 传统工程：在实现稀缺时做建造
 &lt;a class="heading-link" href="#%e4%bc%a0%e7%bb%9f%e5%b7%a5%e7%a8%8b%e5%9c%a8%e5%ae%9e%e7%8e%b0%e7%a8%80%e7%bc%ba%e6%97%b6%e5%81%9a%e5%bb%ba%e9%80%a0"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;传统的软件开发大致遵循这条路径：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;想法
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 架构
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 实现
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 验证
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;实现的代价很高。&lt;/p&gt;
&lt;p&gt;每个决定都要付出成本。&lt;/p&gt;
&lt;p&gt;每一层抽象都至关重要。&lt;/p&gt;
&lt;p&gt;改变方向非常痛苦，因此人们会在动手之前优化方案。&lt;/p&gt;
&lt;p&gt;工程就是建造。&lt;/p&gt;
&lt;h2 id="ai-让建造变成探索"&gt;
 AI 让建造变成探索
 &lt;a class="heading-link" href="#ai-%e8%ae%a9%e5%bb%ba%e9%80%a0%e5%8f%98%e6%88%90%e6%8e%a2%e7%b4%a2"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;有了现代编程智能体，实现不再稀缺。&lt;/p&gt;
&lt;p&gt;短短几分钟，你就可以得到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;五种架构&lt;/li&gt;
&lt;li&gt;三套重构方案&lt;/li&gt;
&lt;li&gt;两种数据库模型&lt;/li&gt;
&lt;li&gt;多套 API 设计&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;于是，工作流程变成了：&lt;/p&gt;</description></item><item><title>AI 原生软件工程（二）：验证框架工程与正确性</title><link>https://yanqian.github.io/zh/posts/publish/harness-engineering-is-about-limiting-ai-not-empowering-it/</link><pubDate>Sat, 18 Jul 2026 23:29:59 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/harness-engineering-is-about-limiting-ai-not-empowering-it/</guid><description>&lt;p&gt;在 AI 原生软件工程中，最重要的也许不是生成，而是约束。&lt;/p&gt;
&lt;p&gt;这是「AI 原生软件工程」系列的第二篇。&lt;/p&gt;
&lt;p&gt;本文承接上一篇：&lt;a href="https://yanqian.github.io/zh/posts/publish/agentic-coding-mental-models-and-the-new-depth-of-software-engineering/" &gt;AI 原生软件工程（一）：智能体编程中的心智模型&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;上一篇讨论的问题是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;如果理解系统不再主要依靠亲手写代码，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;人类要如何在智能体工作流中建立心智模型？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;接下来的问题是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;如果实现工作交给了 AI，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;正确性从何而来？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;谈到 AI 辅助软件开发，人们往往只关心一件事：&lt;/p&gt;
&lt;p&gt;我们能将软件产出提高多少？&lt;/p&gt;
&lt;p&gt;编码更快。&lt;/p&gt;
&lt;p&gt;上下文更长。&lt;/p&gt;
&lt;p&gt;智能体可以自主运行。&lt;/p&gt;
&lt;p&gt;一次改动多个文件。&lt;/p&gt;
&lt;p&gt;工作流能够自我修复。&lt;/p&gt;
&lt;p&gt;但用 AI 智能体做了一段时间项目后，我却得出了相反的结论：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;最重要的工程问题，不是如何让 AI 更自主。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;而是如何更严格地约束 AI。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;因为毫无限制地生成代码，几乎从来不是瓶颈。&lt;/p&gt;
&lt;p&gt;正确性才是。&lt;/p&gt;
&lt;p&gt;这里暂且不谈约束对创造力或搜索空间的影响，只谈正确性。&lt;/p&gt;
&lt;p&gt;真正要回答的是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;怎样才能让 AI 生成的实现可以被放心信任？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="传统软件开发的基本假设"&gt;
 传统软件开发的基本假设
 &lt;a class="heading-link" href="#%e4%bc%a0%e7%bb%9f%e8%bd%af%e4%bb%b6%e5%bc%80%e5%8f%91%e7%9a%84%e5%9f%ba%e6%9c%ac%e5%81%87%e8%ae%be"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;传统软件开发建立在一个简单的假设上：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;人
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 实现
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 验证
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;写系统的人，也会在动手实现的过程中逐渐理解系统。&lt;/p&gt;
&lt;p&gt;很多时候，验证并不会被单独提出来。&lt;/p&gt;
&lt;p&gt;因为实现出自自己之手，你自然更愿意相信它。&lt;/p&gt;
&lt;p&gt;在小团队中，这套做法出人意料地管用。&lt;/p&gt;
&lt;p&gt;直到复杂度不断攀升。&lt;/p&gt;
&lt;h2 id="ai-打破了这个假设"&gt;
 AI 打破了这个假设
 &lt;a class="heading-link" href="#ai-%e6%89%93%e7%a0%b4%e4%ba%86%e8%bf%99%e4%b8%aa%e5%81%87%e8%ae%be"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;智能体编程改变了原有结构。&lt;/p&gt;
&lt;p&gt;现在，整个循环变成了：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;人
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 意图
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;AI
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 实现
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;人
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 审查
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;乍看之下，效率很高。&lt;/p&gt;</description></item><item><title>AI 原生软件工程（一）：智能体编程中的心智模型</title><link>https://yanqian.github.io/zh/posts/publish/agentic-coding-mental-models-and-the-new-depth-of-software-engineering/</link><pubDate>Sat, 18 Jul 2026 22:57:49 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/agentic-coding-mental-models-and-the-new-depth-of-software-engineering/</guid><description>&lt;p&gt;AI 能生成代码。验证框架能检验行为。但理解由谁来建立？&lt;/p&gt;
&lt;p&gt;这是“AI 原生软件工程”系列的第一篇。&lt;/p&gt;
&lt;p&gt;这个系列想追问一个更大的问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;当 AI 降低了实现成本，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;软件工程中还有什么是稀缺的？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;本文先从第一种稀缺资源谈起：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;理解。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;过去几个月，我一直在密集尝试 AI 辅助的软件开发方式。&lt;/p&gt;
&lt;p&gt;不是自动补全。&lt;/p&gt;
&lt;p&gt;也不只是把 AI 当作编程副驾驶。&lt;/p&gt;
&lt;p&gt;而是一套由智能体主导执行的工作流：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SPEC
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 约束
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 验证框架
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 智能体执行
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 评估
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 迭代
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这段经历非常有意思。&lt;/p&gt;
&lt;p&gt;借助它，我用自己并不十分熟悉的语言和框架交付了项目，开发速度也大幅提升。&lt;/p&gt;
&lt;p&gt;做小项目时，简直像魔法。&lt;/p&gt;
&lt;p&gt;可一到更大的项目，意想不到的情况发生了。&lt;/p&gt;
&lt;p&gt;我发现，实现速度和系统理解并不是一回事。&lt;/p&gt;
&lt;p&gt;最后，我不得不面对一个让人不太舒服的事实：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;如果 AI 明天消失，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;我可能很难继续开发自己系统里的某些部分。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个认识改变了我看待软件工程的方式。&lt;/p&gt;
&lt;h2 id="传统模式在实现过程中形成理解"&gt;
 传统模式：在实现过程中形成理解
 &lt;a class="heading-link" href="#%e4%bc%a0%e7%bb%9f%e6%a8%a1%e5%bc%8f%e5%9c%a8%e5%ae%9e%e7%8e%b0%e8%bf%87%e7%a8%8b%e4%b8%ad%e5%bd%a2%e6%88%90%e7%90%86%e8%a7%a3"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;过去的软件工程，大致是这样的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;人
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 编写代码
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 建立心智模型
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; 运行和维护系统
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;写代码不只是为了实现功能。&lt;/p&gt;
&lt;p&gt;它也是学习系统的过程。&lt;/p&gt;
&lt;p&gt;我们在这些事情中逐渐弄懂系统：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;调试&lt;/li&gt;
&lt;li&gt;重构&lt;/li&gt;
&lt;li&gt;追踪执行过程&lt;/li&gt;
&lt;li&gt;与各种约束周旋&lt;/li&gt;
&lt;li&gt;犯错&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;亲手实现，自然会带来理解。&lt;/p&gt;
&lt;p&gt;只是过去，我们未必意识到这一点。&lt;/p&gt;
&lt;h2 id="智能体编程改变了路径"&gt;
 智能体编程改变了路径
 &lt;a class="heading-link" href="#%e6%99%ba%e8%83%bd%e4%bd%93%e7%bc%96%e7%a8%8b%e6%94%b9%e5%8f%98%e4%ba%86%e8%b7%af%e5%be%84"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;有了 AI 编程，整个循环变了。&lt;/p&gt;</description></item><item><title>播客摘要工具让我明白：摘要不等于理解</title><link>https://yanqian.github.io/zh/posts/publish/a-podcast-summarizer-taught-me-that-summaries-are-not-understanding/</link><pubDate>Sat, 18 Jul 2026 12:13:29 +0800</pubDate><guid>https://yanqian.github.io/zh/posts/publish/a-podcast-summarizer-taught-me-that-summaries-are-not-understanding/</guid><description>&lt;p&gt;有人看到我简历上的一个项目，问了我一个很简单的问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;这个软件真的解决了你的问题吗？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个问题问得很好。&lt;/p&gt;
&lt;p&gt;那个项目是一款播客摘要工具。&lt;/p&gt;
&lt;p&gt;源代码公开在这里：&lt;a href="https://github.com/yanqian/podcast-summarizer" class="external-link" target="_blank" rel="noopener"&gt;yanqian/podcast-summarizer&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;最初的想法很直接。&lt;/p&gt;
&lt;p&gt;听完一段长音频，要花不少时间。&lt;/p&gt;
&lt;p&gt;如果能先把一期节目转成文字，再生成摘要，我也许只需读一遍摘要，不必花一个小时收听，就能理解整期内容。&lt;/p&gt;
&lt;p&gt;当时的产品假设是这样的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;长内容
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 转写文本
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 摘要
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 理解
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;真正做完以后，我才意识到，这个假设并不成立。&lt;/p&gt;
&lt;p&gt;倒也不是全错。&lt;/p&gt;
&lt;p&gt;但它偏偏错在最关键的地方。&lt;/p&gt;
&lt;p&gt;这个软件确实能生成摘要。&lt;/p&gt;
&lt;p&gt;它也完整展示了一套 AI 工作流。&lt;/p&gt;
&lt;p&gt;它能导入播客、处理音频、生成转写片段和摘要片段，还能显示两者之间的对应关系。&lt;/p&gt;
&lt;p&gt;作为工程演示，它是成功的。&lt;/p&gt;
&lt;p&gt;但作为帮助人理解内容的工具，它没有解决真正的问题。&lt;/p&gt;
&lt;h2 id="最初的问题并不是内容太长"&gt;
 最初的问题并不是内容太长
 &lt;a class="heading-link" href="#%e6%9c%80%e5%88%9d%e7%9a%84%e9%97%ae%e9%a2%98%e5%b9%b6%e4%b8%8d%e6%98%af%e5%86%85%e5%ae%b9%e5%a4%aa%e9%95%bf"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;一开始，我以为问题就在于内容太长。&lt;/p&gt;
&lt;p&gt;一期播客很长。&lt;/p&gt;
&lt;p&gt;一篇博客文章也可能很长。&lt;/p&gt;
&lt;p&gt;会议转写同样可能很长。&lt;/p&gt;
&lt;p&gt;于是，最自然的产品思路就是压缩：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;把内容变短
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;摘要承诺的正是这件事。&lt;/p&gt;
&lt;p&gt;它减少篇幅。&lt;/p&gt;
&lt;p&gt;删去重复。&lt;/p&gt;
&lt;p&gt;把散漫的对话梳理出结构。&lt;/p&gt;
&lt;p&gt;看起来很高效。&lt;/p&gt;
&lt;p&gt;但真正读过生成的摘要后，我发现了一件不太对劲的事。&lt;/p&gt;
&lt;p&gt;摘要读完了，我还是不知道那场谈话究竟是怎样展开的。&lt;/p&gt;
&lt;p&gt;我知道他们谈了什么。&lt;/p&gt;
&lt;p&gt;知道大致结论。&lt;/p&gt;
&lt;p&gt;也记住了几个要点。&lt;/p&gt;
&lt;p&gt;但我并没有真正理解整段对话。&lt;/p&gt;
&lt;p&gt;摘要丢掉了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个观点是怎样被引出来的&lt;/li&gt;
&lt;li&gt;是什么问题触发了这个观点&lt;/li&gt;
&lt;li&gt;哪些地方仍有疑问&lt;/li&gt;
&lt;li&gt;有哪些例子支撑它&lt;/li&gt;
&lt;li&gt;讨论过哪些取舍&lt;/li&gt;
&lt;li&gt;哪些情绪或现实背景很重要&lt;/li&gt;
&lt;li&gt;说话者在哪里改变了思路&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;摘要并没有说错。&lt;/p&gt;
&lt;p&gt;它只是不够。&lt;/p&gt;
&lt;h2 id="摘要会抹掉通往结论的过程"&gt;
 摘要会抹掉通往结论的过程
 &lt;a class="heading-link" href="#%e6%91%98%e8%a6%81%e4%bc%9a%e6%8a%b9%e6%8e%89%e9%80%9a%e5%be%80%e7%bb%93%e8%ae%ba%e7%9a%84%e8%bf%87%e7%a8%8b"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="链接到标题"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;链接到标题&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;好的摘要保留了终点。&lt;/p&gt;
&lt;p&gt;却留不住抵达终点的那条路。&lt;/p&gt;
&lt;p&gt;这正是问题的核心。&lt;/p&gt;
&lt;p&gt;很多时候，我们恰恰要沿着这条路走一遍，才能真正理解一个观点。&lt;/p&gt;</description></item></channel></rss>