<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>软件验证 on Lingming 灵明</title><link>https://lingming.blog/tags/%E8%BD%AF%E4%BB%B6%E9%AA%8C%E8%AF%81/</link><description>Recent content in 软件验证 on Lingming 灵明</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Tue, 21 Jul 2026 18:50:13 -0400</lastBuildDate><atom:link href="https://lingming.blog/tags/%E8%BD%AF%E4%BB%B6%E9%AA%8C%E8%AF%81/index.xml" rel="self" type="application/rss+xml"/><item><title>黑箱转向（八）：三种黑箱，三种控制</title><link>https://lingming.blog/posts/2026/redefining-control-in-the-age-of-generative-systems/</link><pubDate>Sat, 07 Mar 2026 17:44:27 -0500</pubDate><author>Lingming</author><guid>https://lingming.blog/posts/2026/redefining-control-in-the-age-of-generative-systems/</guid><description>黑箱不是一种东西，控制也不是单一方法。本系列终章以来源、系统和行为三种黑箱，对照认识、行为和运行三层控制，给出按风险选择透明性、验证与恢复机制的矩阵，并说明 AI 时代为何需要重新分配理解，而不是宣布透明性的终结。</description><content:encoded>&lt;p>这个系列从一句有冲击力的判断开始：当代码生产超过人类理解，控制必须从实现转向约束。&lt;/p>
&lt;p>经过八篇讨论，这句话需要被改得更精确。软件从来没有完全透明，约束也从来没有脱离实现。AI 真正加剧的是生成、验证与组织理解之间的不对称。应对它的办法不是宣布“透明性终结”，而是判断：面对哪一种未知，我们还需要理解什么，又需要哪些独立证据和恢复能力？&lt;/p>
&lt;p>本篇不再重复一次未来宣言，而把全系列压缩成一个可操作的矩阵。&lt;/p>
&lt;h2 id="三种黑箱">三种黑箱&lt;/h2>
&lt;h3 id="来源黑箱不知道为什么这样生成">来源黑箱：不知道为什么这样生成&lt;/h3>
&lt;p>最终代码可能清晰可读，团队却不知道它依赖了哪些上下文、为何选择这种结构、哪些假设没有进入仓库。来源黑箱影响的是意图、追溯和审查质量。&lt;/p>
&lt;p>它主要出现在开发阶段，但不是 AI 独有。复制旧代码、使用外包制品或继承缺少记录的遗留系统也会产生相同问题。AI 让这类变化更容易快速、大批量出现。&lt;/p>
&lt;h3 id="系统黑箱局部清楚组合行为不清楚">系统黑箱：局部清楚，组合行为不清楚&lt;/h3>
&lt;p>源码、模块和配置都能访问，系统行为却由依赖、网络、数据、并发、部署环境和第三方服务共同形成。大型分布式系统长期处在这种状态。&lt;/p>
&lt;p>系统黑箱的难点不是找不到任何代码，而是没有一个视角能穷尽所有交互。理解必须借助接口、架构图、实验、遥测和事故经验分布在组织中。&lt;/p>
&lt;h3 id="行为黑箱运行结果具有统计性或适应性">行为黑箱：运行结果具有统计性或适应性&lt;/h3>
&lt;p>当大模型直接参与生成、分类、规划或工具调用，同一输入可能因上下文、采样、模型版本和外部数据产生不同结果。此时静态源码无法完全规定产品输出。&lt;/p>
&lt;p>行为黑箱需要评测分布、置信与失败类别、权限边界和持续监控。它不应被倒推到所有 AI 生成代码：模型写出的普通排序函数，仍然可以是一个确定性程序。&lt;/p>
&lt;p>运行时代码代理可能同时具备三种黑箱：生成理由难追溯，工具与依赖形成复杂系统，决策又具有统计性。组合风险更高，但分析仍要逐层进行。&lt;/p>
&lt;h2 id="三层控制">三层控制&lt;/h2>
&lt;h3 id="认识控制知道知识和未知在哪里">认识控制：知道知识和未知在哪里&lt;/h3>
&lt;p>认识控制不要求一个人理解全部系统，而要求关键知识有明确归属，重要决定可以追溯，团队知道哪些组件只依赖契约、哪些区域必须深入审查。&lt;/p>
&lt;p>常见资产包括设计说明、架构决策记录、代码审查、来源证明、依赖清单和责任地图。它们提供解释与调查基础，却不能单独保证系统行为正确。&lt;/p>
&lt;h3 id="行为控制用证据限制允许发生的事">行为控制：用证据限制允许发生的事&lt;/h3>
&lt;p>行为控制把目标和禁区转成接口、类型、不变量、权限政策、测试、静态分析和形式证明。对运行时模型，还包括离线评测、对抗测试、工具策略和输出验证。&lt;/p>
&lt;p>它的边界是规格问题：没有写出的风险不会自动被证明，错误约束也可能被完美执行。因此证据必须标明主张、适用条件和残余不确定性。&lt;/p>
&lt;h3 id="运行控制发现限制和纠正真实失败">运行控制：发现、限制和纠正真实失败&lt;/h3>
&lt;p>运行控制假定生产环境会出现模型外事实。它通过监控、审计、限流、隔离、灰度、熔断、降级、补偿和事故响应缩短影响。&lt;/p>
&lt;p>运行控制也不能替代前两层。无限权限的系统即使监控完善，也可能在告警抵达前造成不可逆损害；没有设计理由的系统即使成功回滚，也可能反复制造同类事故。&lt;/p>
&lt;h2 id="把三种黑箱与三层控制放在一起">把三种黑箱与三层控制放在一起&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>对象&lt;/th>
 &lt;th>认识控制&lt;/th>
 &lt;th>行为控制&lt;/th>
 &lt;th>运行控制&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>来源黑箱&lt;/td>
 &lt;td>记录模型、输入版本、设计取舍与批准者&lt;/td>
 &lt;td>小批生成、独立审查、构建与测试门槛&lt;/td>
 &lt;td>将具体部署绑定到可核验制品和审批&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>系统黑箱&lt;/td>
 &lt;td>接口所有权、依赖图、关键数据流、责任地图&lt;/td>
 &lt;td>契约、不变量、隔离、兼容性与故障测试&lt;/td>
 &lt;td>可观测性、容量保护、灰度、降级与恢复&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>行为黑箱&lt;/td>
 &lt;td>说明模型能力、数据、已知限制与适用范围&lt;/td>
 &lt;td>代表性评测、对抗测试、权限与工具约束&lt;/td>
 &lt;td>漂移监测、抽样审计、停止条件与人类升级&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>矩阵中的九格不是必须全部堆满的合规清单。它的作用是暴露空白：若团队只说“我们有测试”，可以继续追问测试针对哪种黑箱、支持哪一层控制，以及真实运行失败时谁行动。&lt;/p>
&lt;h2 id="控制强度应当跟随后果而不是跟随潮流">控制强度应当跟随后果，而不是跟随潮流&lt;/h2>
&lt;p>一个生成内部报表脚本的助手，与一个可以批准贷款、调整药物剂量或修改生产防火墙的代理，不应使用同一控制标准。&lt;/p>
&lt;p>可以沿四个问题确定强度：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>后果是否可逆？&lt;/strong> 错误文案可以编辑，资金转出和隐私泄漏难以撤回。&lt;/li>
&lt;li>&lt;strong>影响范围多大？&lt;/strong> 单个开发环境与全体生产租户不同。&lt;/li>
&lt;li>&lt;strong>系统自主性多高？&lt;/strong> 提出建议、创建草稿、执行操作和自我扩展权限是不同等级。&lt;/li>
&lt;li>&lt;strong>失败能否及时观察？&lt;/strong> 明确报错比悄悄改变排序、歧视某类用户或积累财务偏差更容易控制。&lt;/li>
&lt;/ol>
&lt;p>低风险任务可以依赖抽样审查和普通测试。高风险、广影响、难逆转又难观察的系统，则需要更强规格、独立验证、细粒度权限、人类批准和事故演练。&lt;/p>
&lt;h2 id="三个案例">三个案例&lt;/h2>
&lt;h3 id="ai-生成一个纯函数">AI 生成一个纯函数&lt;/h3>
&lt;p>主要风险是来源和实现质量。保留小 diff，检查算法与边界，用性质测试和静态分析验证即可。研究基础模型内部特征通常不是必要控制。&lt;/p>
&lt;h3 id="ai-修改一个分布式结算服务">AI 修改一个分布式结算服务&lt;/h3>
&lt;p>来源、系统两种黑箱同时重要。除了代码证据，还要检查数据迁移、幂等、依赖失败、权限、灰度范围和补偿路径。控制重点是跨模块不变量与故障半径。&lt;/p>
&lt;h3 id="代理在生产中自动处理退款">代理在生产中自动处理退款&lt;/h3>
&lt;p>三种黑箱同时存在。模型判断具有统计性，工具调用具有外部副作用，还可能读取敏感数据。除了离线评测和制品审计，还要设置金额上限、身份验证、速率限制、异常升级、人类复核和即时停用能力。&lt;/p>
&lt;p>案例说明，“AI 系统需要概率控制”只对行为本身具有概率性的场景成立。开发阶段用了生成工具，不足以把整个软件从确定性工程改写为统计工程。&lt;/p>
&lt;h2 id="透明性不是越多越好而要分配到关键位置">透明性不是越多越好，而要分配到关键位置&lt;/h2>
&lt;p>完全开放所有内部细节会制造信息过载，也可能泄漏安全和隐私信息。完全依赖外部行为又会让调试、审计和知识积累困难。&lt;/p>
&lt;p>成熟设计应当分配透明性：&lt;/p>
&lt;ul>
&lt;li>高后果规则和权限策略要清楚、可检查；&lt;/li>
&lt;li>复杂组件可以隐藏实现，但必须给出稳定契约和失败方式；&lt;/li>
&lt;li>生成过程保存足够来源证据，不必永久保存全部敏感上下文；&lt;/li>
&lt;li>运行模型说明适用范围和已知限制，不用虚假的自然语言解释掩盖不确定性；&lt;/li>
&lt;li>事故调查能够从用户影响追到版本、配置、制品和责任角色。&lt;/li>
&lt;/ul>
&lt;p>真正要反对的不是黑箱，而是没有选择依据的黑箱：团队不知道自己隐藏了什么，也不知道用什么证据弥补。&lt;/p>
&lt;h2 id="控制的有限定义">控制的有限定义&lt;/h2>
&lt;p>本系列最终采用的定义是：&lt;/p>
&lt;blockquote>
&lt;p>工程控制，是在明确适用条件和残余不确定性的前提下，拥有与风险相称的理由相信系统会保持在可接受边界内，并能在越界时及时发现、限制和纠正。&lt;/p>&lt;/blockquote>
&lt;p>这个定义不承诺绝对安全，也不把一切降为概率。确定性协议可以保留确定性性质，统计模型则需要分布性证据；两者都必须面对规格遗漏、环境变化和组织执行问题。&lt;/p>
&lt;p>它也没有把理解排除在控制之外。理解帮助我们提出正确性质、解释反例和修复未知故障；约束帮助我们在无法理解全部细节时限制风险；运行反馈帮助我们发现此前理解和规格都没有覆盖的现实。&lt;/p>
&lt;h2 id="八篇文章留下的八个判断">八篇文章留下的八个判断&lt;/h2>
&lt;ol>
&lt;li>软件工程从来依靠分层理解，而不是单个心智掌握一切。&lt;/li>
&lt;li>AI 的关键压力是生成—验证落差，不是代码行数本身。&lt;/li>
&lt;li>认知债是安全修改所需知识与团队可调用知识之间的缺口。&lt;/li>
&lt;li>控制需要多层独立证据，没有单一指标可以取代其余方法。&lt;/li>
&lt;li>架构通过故障半径、权限、时间和相关性塑造风险。&lt;/li>
&lt;li>约束设计是一种增强的工程能力，不是脱离实现的职业特权。&lt;/li>
&lt;li>来源可以分布，责任仍必须落在能够行动的人与组织上。&lt;/li>
&lt;li>不同黑箱需要不同控制；“AI”不是统一风险类别。&lt;/li>
&lt;/ol>
&lt;h2 id="结语从全面理解走向有边界的可信">结语：从全面理解，走向有边界的可信&lt;/h2>
&lt;p>AI 不会让工程从理性走向神秘，也不会自动把复杂性提升为更高级秩序。它只让我们更难继续假装：实现出现了，理解、验证和责任就会自然跟上。&lt;/p>
&lt;p>黑箱转向最值得保留的，不是“透明性已经死亡”这句宣言，而是一条更朴素的纪律：实现越容易生成，越要说明什么不能交给生成；系统越难穷尽，越要给关键主张配置证据；行为越难预测，越要限制权限并准备恢复。&lt;/p>
&lt;p>未来的软件可能包含更多机器生成的内部细节，但它是否值得信任，仍取决于人类怎样设计边界、检查证据、分配责任并从失败中更新。&lt;/p>
&lt;h2 id="延伸阅读与参考资料">延伸阅读与参考资料&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://csrc.nist.gov/pubs/sp/800/218/final">NIST：Secure Software Development Framework&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.nist.gov/publications/artificial-intelligence-risk-management-framework-generative-artificial-intelligence">NIST：Generative AI Profile for the AI Risk Management Framework&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.nist.gov/publications/zero-trust-architecture">NIST SP 800-207：Zero Trust Architecture&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://dora.dev/research/2025/dora-report/">DORA：State of AI-assisted Software Development 2025&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://slsa.dev/spec/v1.1/terminology">SLSA：Provenance and Build Terminology&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;em>上一篇：&lt;a href="https://lingming.blog/posts/2026/the-ethics-of-the-black-box/">《黑箱转向（七）：AI 生成代码出错，谁负责》&lt;/a>。&lt;/em>&lt;/p></content:encoded></item><item><title>黑箱转向（四）：控制不可读之物，需要哪些证据</title><link>https://lingming.blog/posts/2026/controlling-the-unreadable/</link><pubDate>Tue, 03 Mar 2026 14:53:41 -0500</pubDate><author>Lingming</author><guid>https://lingming.blog/posts/2026/controlling-the-unreadable/</guid><description>控制复杂或生成式软件不能只靠逐行阅读，也不能只看测试是否通过。本文以转账系统为例，建立需求、契约、性质测试、实现分析、形式验证与运行监控组成的六层证据体系，说明每种方法各自能证明什么。</description><content:encoded>&lt;p>假设 AI 生成了一个转账函数，单元测试全部通过。我们能否据此放心上线？&lt;/p>
&lt;p>还不能。测试可能只覆盖余额充足的正常路径，没有检查重复请求、并发扣款、货币精度、审计记录或下游超时。即使每一行代码都由人写，问题也一样存在。阅读能够发现某些错误，却无法穷尽输入、状态和环境；测试能够提供行为证据，也无法证明需求本身完整。&lt;/p>
&lt;p>&lt;a href="https://lingming.blog/posts/2026/the-collapse-of-linearity/">上一篇&lt;/a>讨论团队理解与系统之间的认知债。本篇转向工程保证：当完整理解不可得时，怎样建立足够但不虚假的信心？&lt;/p>
&lt;h2 id="不是从实现控制切换到约束控制">不是从“实现控制”切换到“约束控制”&lt;/h2>
&lt;p>接口契约、不变量、测试先行和形式验证都早于生成式 AI。它们不是黑箱时代突然出现的新方法，也没有取代实现检查。AI 改变的是相对成本：候选实现更容易产生，明确性质和核验证据便显得更稀缺。&lt;/p>
&lt;p>因此，更准确的方向不是二选一，而是从单一证据转向&lt;strong>分层保证&lt;/strong>：&lt;/p>
&lt;blockquote>
&lt;p>说明我们主张系统满足什么，用相互独立的方法支持这项主张，并诚实记录仍未覆盖的条件。&lt;/p>&lt;/blockquote>
&lt;p>这与安全关键领域中的 assurance case 思路相近。控制不是“测试绿了”的感觉，而是一条可以被质疑的主张—证据链。&lt;/p>
&lt;h2 id="第一层先证明问题被定义">第一层：先证明问题被定义&lt;/h2>
&lt;p>转账功能的第一层不是代码，而是业务和风险要求：&lt;/p>
&lt;ul>
&lt;li>金额必须为正，并使用明确的货币与精度规则；&lt;/li>
&lt;li>同一幂等键不能造成重复扣款；&lt;/li>
&lt;li>未授权主体不能发起转账；&lt;/li>
&lt;li>余额与账本必须保持一致；&lt;/li>
&lt;li>下游超时不能留下无法判定的中间状态；&lt;/li>
&lt;li>每次变更必须留下可审计记录。&lt;/li>
&lt;/ul>
&lt;p>这些要求包含功能、禁止行为和失败处理。若团队只给模型一句“实现转账 API”，生成器会用训练数据中的常见模式填补空白。实现可以整洁，却不一定符合这个组织的真实制度。&lt;/p>
&lt;p>需求层的证据来自领域专家确认、威胁建模、历史事故、法规和用户场景。它的盲点是自然语言可能歧义，利益相关者也可能遗漏风险。&lt;/p>
&lt;h2 id="第二层把关键性质写成契约和不变量">第二层：把关键性质写成契约和不变量&lt;/h2>
&lt;p>契约把部分要求变成更精确的边界：&lt;/p>
&lt;ul>
&lt;li>前置条件：调用者已授权，金额与货币合法；&lt;/li>
&lt;li>后置条件：成功时借贷双方账本变化守恒；&lt;/li>
&lt;li>不变量：任何时刻总账不能因内部转账凭空增加或减少；&lt;/li>
&lt;li>接口保证：重复幂等键返回同一业务结果。&lt;/li>
&lt;/ul>
&lt;p>类型系统、数据库约束、状态机和权限策略都可以承担这种工作。它们让一部分错误变得不可表达，或者在边界处立即失败。&lt;/p>
&lt;p>但契约不会自动正确。若把“每天限额”写错，机器可以完美验证一个错误规则；若性质没有包含隐私泄漏，形式上的资金守恒也不能证明系统安全。约束减少行为空间，不替我们决定哪一个空间值得允许。&lt;/p>
&lt;h2 id="第三层用多种测试探索性质">第三层：用多种测试探索性质&lt;/h2>
&lt;p>示例测试适合固定已知场景；性质测试从更广输入中寻找反例；状态机或模型测试适合检查操作序列；模糊测试可以探索解析器和协议边界；故障注入则检查依赖失败时的系统反应。&lt;/p>
&lt;p>对于转账系统，可以让生成器产生不同金额、账户状态、重复请求和并发顺序，持续检验余额守恒与幂等性。QuickCheck 在 2000 年已经展示了用随机数据检验程序性质的方法，这并不是 AI 时代的新发明。&lt;/p>
&lt;p>测试的力量在于找到具体反例，而不是证明“所有可能情况都没问题”。测试数据分布、模拟环境和断言质量都会限制结论。AI 可以帮助提出边界案例，也可能生成与实现共享同一误解的测试，因此高风险性质需要独立来源。&lt;/p>
&lt;h2 id="第四层检查实现而不是宣布实现无关">第四层：检查实现，而不是宣布实现无关&lt;/h2>
&lt;p>代码审查、静态分析、依赖扫描、动态分析和渗透测试仍然重要。行为测试可能发现“发生了错误”，实现分析更容易解释错误怎样发生，以及是否存在同类模式。&lt;/p>
&lt;p>代码覆盖率在这里仍有用途：它能指出测试从未执行的语句或分支。它不能证明需求已经覆盖，也不能衡量断言质量。所谓“行为覆盖”如果不定义行为模型、输入分区和性质集合，就只是一个好听的新标签。&lt;/p>
&lt;p>更合理的关系是：&lt;/p>
&lt;ul>
&lt;li>需求覆盖问：重要主张是否有证据；&lt;/li>
&lt;li>代码覆盖问：实现结构哪些区域从未执行；&lt;/li>
&lt;li>性质测试问：给定生成分布是否找到反例；&lt;/li>
&lt;li>变异测试问：测试是否能识别人为注入的错误；&lt;/li>
&lt;li>静态分析问：是否存在某类结构性缺陷。&lt;/li>
&lt;/ul>
&lt;p>这些维度互补，没有一个可以单独取代其余部分。&lt;/p>
&lt;h2 id="第五层用形式验证承担适合它的高风险主张">第五层：用形式验证承担适合它的高风险主张&lt;/h2>
&lt;p>形式验证可以证明实现相对于形式化规格满足某些性质。seL4 微内核展示了机器检查的功能正确性证明能够达到很深层级，同时也明确列出编译器、硬件和规格等可信假设。&lt;/p>
&lt;p>这正说明形式证明的边界：它证明的是模型中写出的性质，不是现实世界的一切正确性。完整验证成本高，也不必施加在每段低风险业务代码上。&lt;/p>
&lt;p>更现实的做法是风险分配：&lt;/p>
&lt;ul>
&lt;li>用类型和约束处理大量局部错误；&lt;/li>
&lt;li>用模型检测检查有限状态协议；&lt;/li>
&lt;li>用求解器验证关键权限与资源性质；&lt;/li>
&lt;li>对安全内核、加密协议或高后果控制器投入更强证明；&lt;/li>
&lt;li>对其余系统保留测试、审查和运行防护。&lt;/li>
&lt;/ul>
&lt;p>AI 可能帮助生成规格或证明，但规格与证明脚本仍需独立检查。由同一个模型同时提出实现、测试和“证明”，容易产生相关性失败。&lt;/p>
&lt;h2 id="第六层上线以后仍需验证">第六层：上线以后仍需验证&lt;/h2>
&lt;p>前五层都无法完整复制生产环境。真实流量、数据分布、依赖故障和运维操作会暴露新的条件，因此保证必须延伸到运行期：&lt;/p>
&lt;ul>
&lt;li>灰度或金丝雀发布限制初始影响；&lt;/li>
&lt;li>指标、日志和追踪帮助识别越界；&lt;/li>
&lt;li>对账和审计任务检查业务不变量；&lt;/li>
&lt;li>限流、熔断与权限边界限制传播；&lt;/li>
&lt;li>降级、前滚修复或回滚缩短影响时间；&lt;/li>
&lt;li>事故复盘把新事实反馈到需求和测试。&lt;/li>
&lt;/ul>
&lt;p>运行监控不是承认前面的工程失败，而是承认开放系统总会遇到模型外事实。&lt;/p>
&lt;h2 id="把证据放进同一张表">把证据放进同一张表&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>层级&lt;/th>
 &lt;th>转账案例中的主张&lt;/th>
 &lt;th>主要证据&lt;/th>
 &lt;th>不能单独证明&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>需求&lt;/td>
 &lt;td>这是正确的业务与风险目标&lt;/td>
 &lt;td>领域评审、威胁模型&lt;/td>
 &lt;td>要求无遗漏&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>契约&lt;/td>
 &lt;td>关键状态必须守恒&lt;/td>
 &lt;td>类型、约束、不变量&lt;/td>
 &lt;td>契约符合现实意图&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>测试&lt;/td>
 &lt;td>代表性场景满足性质&lt;/td>
 &lt;td>示例、性质、故障注入&lt;/td>
 &lt;td>输入空间已经穷尽&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>实现&lt;/td>
 &lt;td>没有已知结构性缺陷&lt;/td>
 &lt;td>审查、静态与动态分析&lt;/td>
 &lt;td>所有行为正确&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>形式验证&lt;/td>
 &lt;td>指定模型满足指定性质&lt;/td>
 &lt;td>机器检查证明&lt;/td>
 &lt;td>模型外环境安全&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>运行验证&lt;/td>
 &lt;td>真实系统保持在边界内&lt;/td>
 &lt;td>监控、对账、灰度&lt;/td>
 &lt;td>未来不会出现新风险&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>这张表的价值不在于让流程变长，而在于防止证据越权。测试通过只能支持它实际检查的主张，代码可读也只能提高发现某些错误的机会。&lt;/p>
&lt;h2 id="结语控制是可审查的信心">结语：控制是可审查的信心&lt;/h2>
&lt;p>黑箱系统最危险的不是我们没有读过全部实现，而是我们无法说清自己凭什么相信它。&lt;/p>
&lt;p>分层保证保留了理解的价值，也承认理解的边界。工程师可以阅读关键实现，同时用契约限制状态、用测试搜索反例、用形式方法证明高风险性质，并在运行期准备发现和恢复。&lt;/p>
&lt;p>控制不可读之物，不是把内部过程忘掉，而是让每项重要主张拥有与其风险相称的证据。&lt;/p>
&lt;h2 id="延伸阅读与参考资料">延伸阅读与参考资料&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://doi.org/10.1109/2.161279">Bertrand Meyer：Applying “Design by Contract”&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://doi.org/10.1145/351240.351266">Koen Claessen、John Hughes：QuickCheck&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://doi.org/10.1145/1743546.1743574">Gerwin Klein 等：seL4 — Formal Verification of an Operating-System Kernel&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.nist.gov/itl/executive-order-14028-improving-nations-cybersecurity/software-supply-chain-security-guidance-0">NIST：Recommended Minimum Standards for Vendor or Developer Verification of Software&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://csrc.nist.gov/pubs/sp/800/218/final">NIST：Secure Software Development Framework&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;em>上一篇：&lt;a href="https://lingming.blog/posts/2026/the-collapse-of-linearity/">《黑箱转向（三）：认知债——团队知道得越来越少吗》&lt;/a>；下一篇：&lt;a href="https://lingming.blog/posts/2026/architecture-as-risk-geometry/">《黑箱转向（五）：架构即风险几何》&lt;/a>。&lt;/em>&lt;/p></content:encoded></item><item><title>黑箱转向（二）：生成—验证落差，真正的拐点</title><link>https://lingming.blog/posts/2026/the-generative-inflection-point/</link><pubDate>Mon, 02 Mar 2026 11:38:38 -0500</pubDate><author>Lingming</author><guid>https://lingming.blog/posts/2026/the-generative-inflection-point/</guid><description>AI 可以在短时间内生成大量实现，但代码产量不等于交付能力。本文结合开发者调查和生产率研究，把“生成拐点”重新定义为团队的生成能力持续超过澄清、审查、整合和运行验证能力，并给出识别这一落差的指标。</description><content:encoded>&lt;p>一个代码代理十分钟生成五个文件，并不意味着团队获得了十分钟的交付。有人仍要确认需求没有误解、依赖没有引入风险、边界条件得到处理、测试没有只证明理想路径，上线后也不会破坏既有数据。&lt;/p>
&lt;p>代码生成把“得到一个可运行候选方案”变得很便宜，却没有同比例压缩其余工作。&lt;a href="https://lingming.blog/posts/2026/the-white-box-assumption/">上一篇&lt;/a>说明，大型软件早已依靠局部理解运行。本篇要定位 AI 带来的新增压力：不是软件第一次超出个体认知，而是实现吞吐量可能开始持续超过保证吞吐量。&lt;/p>
&lt;h2 id="代码产量不是软件生产率">代码产量不是软件生产率&lt;/h2>
&lt;p>软件工作的产出不是代码文本，而是被用户使用、能够维护并承担后果的系统变化。新增行数甚至未必是正向指标：更短的实现可能更好，删除不必要代码也可能比增加功能更有价值。&lt;/p>
&lt;p>因此，“模型每秒生成多少行”无法直接与“工程师每小时写多少行”比较。模型可以快速制造候选实现，工程师则还在完成问题建模、取舍、集成和验证。两者不是同一种计量单位。&lt;/p>
&lt;p>更合适的链条是：&lt;/p>
&lt;blockquote>
&lt;p>需求澄清 → 候选生成 → 人工审查 → 自动验证 → 系统整合 → 渐进发布 → 运行反馈&lt;/p>&lt;/blockquote>
&lt;p>AI 主要压缩其中一部分，有时也能帮助测试和解释，但任何未被压缩的环节都可能成为新瓶颈。候选代码越便宜，团队越容易把瓶颈从“写不出来”转移到“看不完、接不上、无法放心上线”。&lt;/p>
&lt;h2 id="现有证据不支持一个整齐的全球拐点">现有证据不支持一个整齐的全球拐点&lt;/h2>
&lt;p>截至 2026 年，AI 编程的使用率和效果都在快速变化，但研究结果仍取决于任务与人群。&lt;/p>
&lt;p>2025 年 Stack Overflow 开发者调查显示，很多开发者已经使用 AI 工具，但 72% 的相关受访者表示 vibe coding 不是其专业工作方式；对 AI 准确性持不信任态度的人多于信任者。高责任的部署与监控任务也最少被计划交给 AI。这说明“广泛辅助”不能直接改写成“AI 已是主要代码生产者”。&lt;/p>
&lt;p>METR 在 2025 年对熟悉自己大型开源仓库的资深开发者进行随机实验，观察到允许使用当时 AI 工具的任务平均耗时反而增加。2026 年的后续说明认为较新的工具可能已经带来加速，却也指出不愿在无 AI 条件下工作的参与者造成了样本选择问题，无法给出稳定总体估计。&lt;/p>
&lt;p>DORA 2025 的结论更适合这组复杂证据：AI 像一个放大器。它可以提高个人效率和交付吞吐，也可能同时增加交付不稳定性；平台质量、内部开发体验、小批量变更和清晰的组织政策会显著影响结果。&lt;/p>
&lt;p>所以，本系列不把 2026 年某一天宣布为统一的“生成拐点”。拐点发生在具体团队内，而且需要用实际交付数据识别。&lt;/p>
&lt;h2 id="真正的落差发生在哪里">真正的落差发生在哪里&lt;/h2>
&lt;p>生成—验证落差至少有四种来源。&lt;/p>
&lt;h3 id="需求落差">需求落差&lt;/h3>
&lt;p>模型可以忠实实现一条错误或不完整的需求。代码越快出现，团队越可能把“已有实现”误当作“问题已经被定义”。需求中的权限、失败处理、兼容性和非功能约束若没有先说清，后续审查只能在成品中反向猜测。&lt;/p>
&lt;h3 id="意图落差">意图落差&lt;/h3>
&lt;p>人手编写也可能缺少设计理由，但 AI 会让这种情况更容易规模化。一个实现可能来自几轮对话、临时上下文和模型默认选择；仓库只保存最终 diff，没有保存哪些方案被排除、哪些假设仍不确定。&lt;/p>
&lt;h3 id="审查落差">审查落差&lt;/h3>
&lt;p>生成工具可以一次交付大批变化，而审查者的注意力仍有限。大批量 diff 会降低逐项质疑的概率，“测试是绿的”很容易成为替代性判断。此时问题不一定是代码不可读，而是组织没有为阅读支付足够时间。&lt;/p>
&lt;h3 id="整合落差">整合落差&lt;/h3>
&lt;p>模型擅长局部任务，不代表它掌握组织特有的部署约束、历史兼容负担和隐性业务规则。一段局部合理的实现，可能扩大依赖、破坏性能预算或绕过已有治理流程。真正昂贵的工作常发生在模块边界。&lt;/p>
&lt;h2 id="怎样判断团队是否越过了自己的拐点">怎样判断团队是否越过了自己的拐点&lt;/h2>
&lt;p>不要只统计生成代码占比。更有用的是同时观察流量、质量和理解。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>维度&lt;/th>
 &lt;th>可观察指标&lt;/th>
 &lt;th>危险信号&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>变更流量&lt;/td>
 &lt;td>PR 大小、并行变更数、审查等待时间&lt;/td>
 &lt;td>生成量上升，审查队列持续增长&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>返工质量&lt;/td>
 &lt;td>首次通过率、回退率、缺陷逃逸率&lt;/td>
 &lt;td>合并更快，返工与事故同步增加&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>系统整合&lt;/td>
 &lt;td>构建失败、兼容问题、依赖增长&lt;/td>
 &lt;td>局部测试通过，集成频繁失败&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>团队理解&lt;/td>
 &lt;td>设计理由覆盖、模块接手时间、事故定位时间&lt;/td>
 &lt;td>只有生成者会操作，没人能解释边界&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>运行结果&lt;/td>
 &lt;td>变更失败率、恢复时间、用户影响&lt;/td>
 &lt;td>吞吐增加，稳定性下降&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>当候选实现增长快于审查与运行保证，并且返工、恢复和接手成本持续上升，团队才真正越过了自己的生成拐点。&lt;/p>
&lt;h2 id="缩小落差而不是限制一切生成">缩小落差，而不是限制一切生成&lt;/h2>
&lt;p>解决办法不是给 AI 设置一个统一代码配额，而是让生成批量与保证能力匹配。&lt;/p>
&lt;ol>
&lt;li>先写成功条件、禁止行为和非功能约束，再请求实现。&lt;/li>
&lt;li>把任务拆成能被独立审查的小变化，限制一次跨越的模块和权限。&lt;/li>
&lt;li>要求每次生成同时提供测试主张、未覆盖边界和关键设计取舍。&lt;/li>
&lt;li>对高风险代码保留更强人工审查、静态分析和独立验证。&lt;/li>
&lt;li>用团队交付结果评估工具，而不是只看补全接受率或生成行数。&lt;/li>
&lt;li>发现审查队列和认知债上升时，优先删除、合并和澄清，而非继续堆积实现。&lt;/li>
&lt;/ol>
&lt;p>AI 有时也能缩小验证成本，例如生成性质测试、解释陌生模块或帮助定位依赖。但这些输出同样需要核验。工具能够参与保证流程，不等于它可以为自己的结果签发可信证明。&lt;/p>
&lt;h2 id="结语拐点是一条反馈曲线">结语：拐点是一条反馈曲线&lt;/h2>
&lt;p>生成式 AI 最重要的变化，不是把源代码变成神秘物体，而是解除实现产量原有的人力摩擦。这个变化可能释放创造力，也可能让组织更快地积累未经充分验证的系统。&lt;/p>
&lt;p>真正的分水岭，不在于模型一次写了多少行，而在于团队能否让问题定义、审查证据、运行反馈和责任容量跟上。生成快于验证只是风险条件；是否滑向黑箱，要看组织怎样响应这条落差。&lt;/p>
&lt;h2 id="延伸阅读与参考资料">延伸阅读与参考资料&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://survey.stackoverflow.co/2025/ai/">Stack Overflow：2025 Developer Survey — AI&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/">METR：Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://metr.org/blog/2026-02-24-uplift-update/">METR：We Are Changing Our Developer Productivity Experiment Design&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://dora.dev/research/2025/dora-report/">DORA：State of AI-assisted Software Development 2025&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;em>上一篇：&lt;a href="https://lingming.blog/posts/2026/the-white-box-assumption/">《黑箱转向（一）：软件工程从来不是完全的白箱》&lt;/a>；下一篇：&lt;a href="https://lingming.blog/posts/2026/the-collapse-of-linearity/">《黑箱转向（三）：认知债——团队知道得越来越少吗》&lt;/a>。&lt;/em>&lt;/p></content:encoded></item><item><title>黑箱转向（总序）：当生成速度超过验证速度</title><link>https://lingming.blog/posts/2026/the-manifesto-for-software-engineering-after-human-comprehension/</link><pubDate>Sun, 01 Mar 2026 21:22:10 -0500</pubDate><author>Lingming</author><guid>https://lingming.blog/posts/2026/the-manifesto-for-software-engineering-after-human-comprehension/</guid><description>AI 没有第一次把软件变成黑箱，却显著扩大了生成速度与验证能力之间的落差。本篇区分来源、系统与行为三种黑箱，提出以可解释范围、行为证据和运行时恢复共同定义控制，并交代全系列的八个问题。</description><content:encoded>&lt;p>设想两个团队都在一天内新增五千行代码。第一个团队由工程师逐步编写，第二个团队主要让代码代理生成。第二天发生故障时，两边都不能仅靠“把五千行重新读一遍”解决问题：他们还要理解依赖、配置、数据状态、部署环境和外部服务。区别在于，第二个团队可能还缺少一层东西——为什么生成器选择了这些结构，哪些默认假设从未被写进需求，以及审查能力是否跟得上生成速度。&lt;/p>
&lt;p>这正是本系列所谓的“黑箱转向”。它不是一个关于“人写的代码透明、机器写的代码神秘”的简单故事，也不是宣告阅读代码已经无用。更有限、也更可检验的判断是：&lt;/p>
&lt;blockquote>
&lt;p>生成式 AI 降低了制造实现的成本，却没有按同样比例降低澄清需求、检查行为、整合系统和承担后果的成本。真正扩大的，是生成与验证之间的落差。&lt;/p>&lt;/blockquote>
&lt;h2 id="软件从来不是完整的白箱">软件从来不是完整的白箱&lt;/h2>
&lt;p>大型软件早已超出单个人的完整理解。操作系统、数据库、浏览器、云平台和开源依赖都通过分工与抽象运行；模块化本来就是让人无需了解全部内部细节，也能依赖一个稳定接口继续工作。AI 没有发明这种局部黑箱。&lt;/p>
&lt;p>因此，“白箱时代”最多是一种工程理想：源代码原则上可检查，关键决定可以追溯，局部实现能够被解释。它从来不意味着某个人真的能把整个系统放进头脑，也不意味着可见源码自动带来正确性。&lt;/p>
&lt;p>生成式 AI 改变的，是这套理想的成本结构。一个团队可以比过去更快地产生超出其审查容量的改动，也可以在没有形成充分心智模型之前获得一个看似完整的系统。反过来，AI 也可能帮助解释旧代码、补测试、整理文档和缩小理解成本。结果不是单向的技术宿命，而取决于团队怎样使用它。&lt;/p>
&lt;h2 id="先区分三种黑箱">先区分三种黑箱&lt;/h2>
&lt;p>“黑箱”如果只表示“不完全理解”，范围会大到失去分析价值。本系列把它拆成三种可以分别治理的问题。&lt;/p>
&lt;p>第一种是&lt;strong>来源黑箱&lt;/strong>。代码本身可能清晰，但团队不知道某个实现为什么被生成、依赖了哪些上下文、经过哪些人工判断。这是意图、来源和审查证据的问题。&lt;/p>
&lt;p>第二种是&lt;strong>系统黑箱&lt;/strong>。每个组件可能都能阅读，组合后的行为却受依赖版本、网络、配置、并发、数据和外部服务共同影响。这不是 AI 独有的问题，而是复杂软件长期面对的问题。&lt;/p>
&lt;p>第三种是&lt;strong>行为黑箱&lt;/strong>。当大模型在运行时参与分类、生成、规划或工具调用，系统行为具有统计性和情境敏感性。此时，仅检查一份静态源代码无法穷尽可能输出，需要专门的评测、权限边界与运行监控。&lt;/p>
&lt;p>代码代理在运行时自行修改并执行程序时，三种黑箱可能同时出现。但它们仍不能被混成一个问题：生成普通代码，不会自动让普通程序变成概率程序；模型内部难以解释，也不等于生成出来的源代码无法分析。&lt;/p>
&lt;h2 id="控制不等于全知也不等于只看结果">控制不等于全知，也不等于只看结果&lt;/h2>
&lt;p>本系列把工程控制定义为：&lt;strong>在说明适用条件和残余不确定性的前提下，拥有足够证据相信系统会保持在可接受边界内，并能在越界时发现、限制和纠正。&lt;/strong>&lt;/p>
&lt;p>这个定义包含三层能力：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>控制层&lt;/th>
 &lt;th>要回答的问题&lt;/th>
 &lt;th>常见手段&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>认识控制&lt;/td>
 &lt;td>我们知道哪些，哪些仍不知道？&lt;/td>
 &lt;td>设计说明、代码审查、来源记录、依赖清单&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>行为控制&lt;/td>
 &lt;td>哪些性质必须成立，证据是什么？&lt;/td>
 &lt;td>类型、契约、不变量、测试、静态分析、形式验证&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>运行控制&lt;/td>
 &lt;td>失败如何被发现、隔离和恢复？&lt;/td>
 &lt;td>指标、日志、追踪、限权、灰度、降级、回滚&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>三层不能相互替代。接口契约不能证明需求本身正确；测试通过不能证明输入空间已经穷尽；可观测性也不能弥补无限权限。黑箱工程不是放弃理解，而是把“需要理解到什么程度”和“还需要哪些独立证据”说得更清楚。&lt;/p>
&lt;h2 id="八篇文章各自解决什么">八篇文章各自解决什么&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>篇章&lt;/th>
 &lt;th>核心问题&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://lingming.blog/posts/2026/the-white-box-assumption/">第一篇：软件工程从来不是完全的白箱&lt;/a>&lt;/td>
 &lt;td>传统软件如何通过结构化、信息隐藏和协作管理不完全理解？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://lingming.blog/posts/2026/the-generative-inflection-point/">第二篇：生成—验证落差，真正的拐点&lt;/a>&lt;/td>
 &lt;td>AI 在什么条件下提高产出，又怎样制造审查与整合瓶颈？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://lingming.blog/posts/2026/the-collapse-of-linearity/">第三篇：认知债——团队知道得越来越少吗&lt;/a>&lt;/td>
 &lt;td>怎样区分代码复杂、知识流失和缺少设计理由？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://lingming.blog/posts/2026/controlling-the-unreadable/">第四篇：控制不可读之物，需要哪些证据&lt;/a>&lt;/td>
 &lt;td>代码审查、测试、契约和形式验证如何形成分层保证？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://lingming.blog/posts/2026/architecture-as-risk-geometry/">第五篇：架构即风险几何&lt;/a>&lt;/td>
 &lt;td>架构怎样限制故障半径、权限范围和风险持续时间？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://lingming.blog/posts/2026/the-new-engineer-from-coder-to-constraint-designer/">第六篇：从编码者到约束设计者？&lt;/a>&lt;/td>
 &lt;td>工程师的任务组合如何变化，哪些编码能力仍不可替代？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://lingming.blog/posts/2026/the-ethics-of-the-black-box/">第七篇：AI 生成代码出错，谁负责&lt;/a>&lt;/td>
 &lt;td>作者身份、来源证据、组织问责和法律责任如何区分？&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://lingming.blog/posts/2026/redefining-control-in-the-age-of-generative-systems/">第八篇：三种黑箱，三种控制&lt;/a>&lt;/td>
 &lt;td>面对不同黑箱，怎样选择透明性、约束与恢复机制？&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="本系列不主张什么">本系列不主张什么&lt;/h2>
&lt;p>它不主张 AI 已经成为所有团队的主要代码生产者，也不主张软件工程存在一个全球同步的历史拐点。2025 至 2026 年的调查和实验仍呈现混合结果：AI 能提高某些任务的速度，也可能增加返工、评审批量和交付不稳定性；资深开发者、陌生代码库和高责任任务的结果尤其不能从简单基准推断。&lt;/p>
&lt;p>它也不主张约束将“取代”实现、观测将“取代”阅读，或者架构师将“取代”程序员。更合理的变化是重心重新分配：当实现更便宜，问题定义、边界设计、验证证据和运行责任会变得相对更稀缺。&lt;/p>
&lt;p>黑箱转向真正要求的，不是对不可理解的浪漫化，而是一种更严格的谦逊：知道自己没有验证什么，知道系统可能怎样失败，也知道失败之后由谁采取行动。&lt;/p>
&lt;h2 id="延伸阅读与参考资料">延伸阅读与参考资料&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://doi.org/10.1145/361598.361623">D. L. Parnas：On the Criteria To Be Used in Decomposing Systems into Modules&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://dora.dev/research/2025/dora-report/">DORA：State of AI-assisted Software Development 2025&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/">METR：Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://survey.stackoverflow.co/2025/ai/">Stack Overflow：2025 Developer Survey — AI&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://csrc.nist.gov/pubs/sp/800/218/final">NIST：Secure Software Development Framework&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;em>下一篇：&lt;a href="https://lingming.blog/posts/2026/the-white-box-assumption/">《黑箱转向（一）：软件工程从来不是完全的白箱》&lt;/a>。&lt;/em>&lt;/p></content:encoded></item></channel></rss>