<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DevOps on Vibe Coding 笔记</title><link>https://8-152-7-248.sslip.io/tags/devops/</link><description>Recent content in DevOps on Vibe Coding 笔记</description><generator>Hugo -- gohugo.io</generator><language>zh_CN</language><lastBuildDate>Wed, 28 Oct 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://8-152-7-248.sslip.io/tags/devops/index.xml" rel="self" type="application/rss+xml"/><item><title>Anthropic 自己的 CI 被 AI 写垮了：三次补丁，70 天、29 天、不到一天</title><link>https://8-152-7-248.sslip.io/p/agentic-ci-strain/</link><pubDate>Wed, 28 Oct 2026 00:00:00 +0800</pubDate><guid>https://8-152-7-248.sslip.io/p/agentic-ci-strain/</guid><description>&lt;img src="https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/cover.png" alt="Featured image of post Anthropic 自己的 CI 被 AI 写垮了：三次补丁，70 天、29 天、不到一天" /&gt;&lt;p&gt;你有没有经历过这种场面：让 AI 改一个功能，它很快甩给你一份 diff，你合并、提交，然后盯着 CI 慢慢转圈。&lt;/p&gt;&#10;&lt;p&gt;一开始是几分钟。&lt;/p&gt;&#10;&lt;p&gt;后来变成几十分钟。再后来，你开始在心里算：这一单要等多久才敢提交。&lt;/p&gt;&#10;&lt;p&gt;写代码这一环确实快了。慢的是别的东西。&lt;/p&gt;&#10;&lt;p&gt;2026 年 9 月 14 日，Anthropic 的工程师 Sachin Malhotra 在公司博客上发了篇文章，标题很直白——《Agentic coding is straining CI》。讲的是他们自己的持续集成服务，怎么被 AI 写代码的速度拖垮，又是怎么重写活过来的。&lt;/p&gt;&#10;&lt;h2 id="瓶颈不在写代码在-ci"&gt;瓶颈不在写代码，在 CI&#10;&lt;/h2&gt;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Anthropic engineers on average ship 8x as much code per quarter as they did from 2021-2025. Claude authors 80% of that code and it also plays a large role in reviewing and approving PRs as well.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;每个季度交付的代码量，是 2021 到 2025 年平均水平的 8 倍。Claude 写下其中 80%，同时在 PR 的评审和批准环节也扮演重要角色。&lt;/p&gt;&#10;&lt;p&gt;而测试量涨了 10 倍，工程师只「名义上」增加了一点。&lt;/p&gt;&#10;&lt;p&gt;结果就是 CI 作业量在半年里涨了 25 倍。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;On top of that, the amount of tests across our codebase grew 10x and we added a nominal amount of engineers. This all led to a 25x increase in CI jobs over a six month period&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;测试只涨了 10 倍，CI 作业却涨了 25 倍。多出来的那 2.5 倍是哪来的？&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 10 倍的测试，为什么 CI 作业涨了 25 倍？（示意拼装，非原文代码）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tests_growth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;# 原文：the amount of tests across our codebase grew 10x&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ci_jobs_growth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="c1"&gt;# 原文：a 25x increase in CI jobs over a six month period&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ci_jobs_growth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;tests_growth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2.5 —— 每个 PR 触发的测试作业，是原来的 2.5 倍&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;答案在原文另一处：Claude 偏好更小、更碎的 PR。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;This has changed the shape of PRs over time at Anthropic as Claude prefers smaller, more granular PRs&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;PR 变小、变多，每个 PR 又都要走一遍流水线，作业量自然比「测试变多」本身涨得更凶。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Writing code is no longer the constraint, and once PR review gets accelerated, CI starts feeling the pressure.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;写代码不再是瓶颈了。评审一提速，压力就传导到了 CI。&lt;/p&gt;&#10;&lt;h2 id="三次补丁一次比一次短"&gt;三次补丁，一次比一次短&#10;&lt;/h2&gt;&lt;p&gt;Anthropic 的测试影响分析服务（test impact analysis，也叫 test selection）负责判断：这次改动该跑哪些测试。跑全量是跑不动的。&lt;/p&gt;&#10;&lt;p&gt;这个服务被压垮过三次。三次都打了补丁，三次的存活时间分别是：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;70 天&lt;/li&gt;&#10;&lt;li&gt;29 天&lt;/li&gt;&#10;&lt;li&gt;不到一天&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;第一次：换更大的机器。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;2025 年 10 月，服务开始显出疲态，连续两天被半夜叫醒。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;By October of last year the service was already showing signs of strain, and we got paged two days straight.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;第一个补丁最简单：把跑这个服务的核心数翻倍。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;The first fix was easy: we doubled the cores running the service. We also knew it would be fleeting.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;他们当时就知道这招是临时的。扛了 70 天。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;第二次：按 package 分片。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;叫醒它的次数更频繁了。他们开了一个长期会话专门盯着这个服务，一旦 listener 落后超过 50,000 个作业，Claude 就会来戳一下作者。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Anytime the listener lag would get more than 50,000 jobs behind, Claude would ping me and resume our conversation on next steps.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;Claude 一直在劝他们整个重构，但每次都「我们再打一个补丁」。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Claude often argued for an overhaul, but we usually settled on another patch.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;2026 年 2 月，他们决定并行化。关键认知是：listener 不需要一个单写者给所有测试结果排序，只需要每个 package 一个单写者。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Claude generated the code for us to split each package&amp;rsquo;s state into a shard with its own worker.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;分片代码是 Claude 写的。这次撑了 29 天。他们知道是临时的，但没想到这么短。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;第三次：每天重启。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;3 月，进程在大多数工作日的下午就撞上了内存上限。&lt;/p&gt;&#10;&lt;p&gt;他们试了几条快路：找到四个 bug；换内存分配器，没用；不敢给一个已经满载的单例做内存分析。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;We only found four bugs.&amp;rdquo;&#10;&amp;ldquo;Swapping the memory allocator as a quick-hack did nothing.&amp;rdquo;&#10;&amp;ldquo;We didn&amp;rsquo;t want to risk memory profiling a singleton already under a heavy load.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;最后靠重启撑着。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Restarting bought us less than a day.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;不到一天。&lt;/p&gt;&#10;&lt;p&gt;重启还带来一个更糟的副作用：服务重启之后越来越追不上，落后超过一小时的时候（发生过好几次），大量作业结果根本没被 listener 记下来。&lt;/p&gt;&#10;&lt;p&gt;作者说得很清楚：这不代表 CI 没跑，也不代表有没测过的代码进了生产。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;To be clear, this doesn&amp;rsquo;t mean CI never ran on those PRs, or that untested code was pushed to production.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;真实后果是：测试选择组件拿着过期数据，决定哪些测试该跑、哪些不用跑。&lt;/p&gt;&#10;&lt;p&gt;70 天、29 天、不到一天。这不是巧合，是指数负载撞上线性补丁的形状。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="三次补丁的存活时间：70 天、29 天、不到一天" class="gallery-image" data-flex-basis="332px" data-flex-grow="138" height="780" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/01-three-patches.png" srcset="https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/01-three-patches_hu_34f665e1941eeb91.png 800w, https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/01-three-patches.png 1080w" width="1080"&gt;&lt;/p&gt;&#10;&lt;h2 id="根因状态长在进程里"&gt;根因：状态长在进程里&#10;&lt;/h2&gt;&lt;p&gt;三次补丁都在同一个位置打转：服务是单进程的，状态长在进程里。&lt;/p&gt;&#10;&lt;p&gt;这套服务靠两个部件配合。listener 记录每次 CI 运行产生的测试结果；selector 读这些历史，决定每个 PR 上跑哪些测试。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;A &amp;rsquo;listener&amp;rsquo; records the test results from every CI run.&amp;rdquo;&#10;&amp;ldquo;A &amp;lsquo;selector&amp;rsquo; reads the test result history and determines which tests run on which opened PRs.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;问题出在「每个测试要保留一份运行历史」这件事上。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;All of this ran as a single process because keeping a running history per test meant a single writer needed to apply the results. This v0 design prevented us from being able to horizontally shard.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;单写者保序，所以不能分片。状态在进程里，所以不能水平扩展。作业量一涨，listener 就开始追不上 PR 队列。&lt;/p&gt;&#10;&lt;p&gt;滞后的代价，原文给了具体量级。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;20 minutes of listener lag can translate into tens of thousands of test updates not being applied to the selector.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;落后 20 分钟，就是几万条测试更新没能应用到 selector 上。后果有三类：坏改动合进去，测试对所有人开始失败，引发一串不必要的排查；依赖开始飘，红的 flaky 挡住合并；测试修好了或新加了，要等 listener 追上来才跑，中间夹着回归风险。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="单进程有状态 vs 无状态 journal + 消费者" class="gallery-image" data-flex-basis="301px" data-flex-grow="125" height="860" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/02-architecture.png" srcset="https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/02-architecture_hu_5636be82ab6f173e.png 800w, https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/02-architecture.png 1080w" width="1080"&gt;&lt;/p&gt;&#10;&lt;h2 id="重写三周一个人"&gt;重写：三周，一个人&#10;&lt;/h2&gt;&lt;p&gt;最后他们把整个服务推倒了。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;We gave the test selection service a database, or an in-memory data store to be exact.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;不是磁盘数据库，是内存数据存储。具体做法：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Now, any listener worker can process any result, append it to a journal in the in-memory store, and move on without holding anything in memory - stateless and hence, horizontally scalable. A small separate consumer process rolls the journal up into per-test history every few seconds, and the selector can look up relevant result history quickly.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;拆成三步：listener 干完活就把结果追加到 journal 里，不在内存里留任何东西；一个小消费者进程每隔几秒把 journal 汇总成每个测试的历史；selector 查历史。&lt;/p&gt;&#10;&lt;p&gt;无状态，所以能水平扩。补丁换成了架构。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;This distributed architecture is more expensive to run, but it is much easier to scale and memory profile than a shaky singleton.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;比那个摇摇欲坠的单例贵，但好扩，也好做内存分析。&lt;/p&gt;&#10;&lt;p&gt;工期：一个工程师，三周。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;This project took three weeks for a single engineer. A year ago it would have been closer to a quarter.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;一年前，这活儿接近一个季度。journal 开多大、要几个 worker，这些调优基本是 Claude 自己完成的。&lt;/p&gt;&#10;&lt;p&gt;上线之后，积压曲线从「每天堆、周比周大」变成平的。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Queued, unprocessed job-result events, hourly max. Before: a backlog built up most days and grew week over week. After cutover and tuning: flat.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h2 id="如果能回到-2025-年-10-月"&gt;如果能回到 2025 年 10 月&#10;&lt;/h2&gt;&lt;p&gt;文章最后，他回答了那个假设题：如果能回去，他会怎么做。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;always plan for the exponential&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;第一，别按现在的负载设计。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;My advice to engineering teams is, whether you build or buy, assume your architecture will be at a 25x load within two quarters.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;两个季度内，你的架构要扛得住 25 倍负载。他还说了一句更大胆的：v0 设计里直接按 10 到 20 倍的感知规模来算，预算允许就行。&lt;/p&gt;&#10;&lt;p&gt;第二，让服务自己说话。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Instrument your services to act as Claude&amp;rsquo;s eyes and ears. It allows Claude to hill-climb and fix problems incrementally much better and faster than we could manually. In particular, ensure that the same number of CI jobs coming in equals the same going out.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;最要紧的一条不变量：进来的 CI 作业数，要等于出去的作业数。&lt;/p&gt;&#10;&lt;p&gt;第三，状态别放进进程。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;ldquo;Keep state out of the process from the start. I&amp;rsquo;d also avoid running any critical service as a single instance unless you can measure it and any canary changes.&amp;rdquo;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;可以落成这样一份容量契约：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# capacity.yaml —— 按 25 倍负载预留的容量契约（示意拼装，非 Anthropic 原文配置）&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;load&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;design_for_multiplier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 原文：assume your architecture will be at a 25x load within two quarters&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;v0_design_multiplier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10-20x&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 原文：account for 10-20x the perceived scale in your v0 designs&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;keep_out_of_process&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 原文：Keep state out of the process from the start&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;single_instance_allowed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 原文：avoid running any critical service as a single instance&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;health&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;jobs_in_equals_jobs_out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 原文：the same number of CI jobs coming in equals the same going out&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;listener_lag_alert_jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;50000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 原文：the listener lag would get more than 50,000 jobs behind&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="三次补丁、一次重写，与他们给的三条建议" class="gallery-image" data-flex-basis="294px" data-flex-grow="122" height="880" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/03-timeline.png" srcset="https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/03-timeline_hu_b2dcbd96856e24de.png 800w, https://8-152-7-248.sslip.io/p/agentic-ci-strain/images/03-timeline.png 1080w" width="1080"&gt;&lt;/p&gt;&#10;&lt;p&gt;Anthropic 这篇文章真正值得带走的不是「要重写」这个结论——很多团队还没到那一步。是那个衰减曲线。&lt;/p&gt;&#10;&lt;p&gt;70 天、29 天、不到一天。你打的每一个补丁，都是在给一条正在变陡的曲线续命。而补丁的有效期本身就是一个信号：&lt;strong&gt;它变短了，就该重写，不是该升级。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;你上次给自己的 CI 或者构建系统打的那个补丁，撑了多久？&lt;/strong&gt;&lt;/p&gt;&#10;</description></item></channel></rss>