# 当软件的时间开始松动

AI 让一部分实现可以等到上下文出现以后再确定，也让使用反馈在原来的事情结束前返回。软件的时间线正在松动，责任却不能跟着松动。

## Metadata

- HTML: https://glenzli.com/notes/software-time-loosens/
- Markdown: https://glenzli.com/notes/software-time-loosens.md
- Collection: Notes
- Language: zh-CN
- Published: 2026-07-18
- Updated: 2026-08-17
- Tags: ai, software-engineering, runtime, delivery, feedback

## Content

这次旅行中，我临时写了一个行程应用。

出发前，我准备了比旅行天数更多的候选安排。真正到了当地，每天还要根据天气、闭馆、预约、体力和各种临时变化，重新决定第二天去哪里。这个应用最初只是把候选行程放在一起，方便随时切换。

它没有在出发前完成，也没有在第一次部署后完成。

我一边使用，一边发现缺少的能力和原先没有想到的问题。有些修改当天完成，检查、部署，随后就在同一段行程里继续使用。

需求、开发、交付和使用仍然是不同的事情，却不再必须依次发生。

软件交付后继续维护当然不新鲜。敏捷开发、持续交付和 DevOps，早已让使用反馈进入后续版本。真正变化的是，这条反馈闭环第一次短到可以追上软件正在服务的现实活动。

过去，旅行中发现的问题会被记下来，等事后整理，留到下一版，甚至下一次旅行。现在，修改后的版本可以在这次旅行结束前回到手里。反馈不必等到情境已经变成回忆，才开始产生作用。

一个只存在两周的应用，也可以在两周里连续变化；一个需要维护十年的系统，反而可能因为风险和迁移成本，很久才更新一次。

软件活多久，和它会经历多少次交付，并不是一回事。

沿着这条时间线再往前，还有一个问题：

> 如果一段实现只服务当前上下文，结果又可以独立验证，它还必须在交付前成为确定的源码吗？

## 实现何时确定

现在让 AI 写一段一次性的数据清洗脚本，并不困难。通常的做法是先生成代码，运行测试，再放进沙箱或本地环境执行。

代码便宜了，软件的形态却没变。需求先成为源码，源码经过构建和交付，运行时再执行已经确定的实现。即使大部分代码来自 Agent，源码仍是需求进入运行环境前必须经过的中间产物。

但如果一段过程只处理这一次输入，真实数据和环境又要到运行时才出现，具体实现也许可以晚一点。

晚一点，不等于不检查。

运行时仍然要生成或选择候选实现，候选必须经过验证，真实动作需要单独授权。变化只是：不再要求所有具体过程都在部署前写完。

运行时决定过程并不新鲜。JIT 会生成机器码，查询优化器会根据数据分布选择执行计划。它们从已有的形式表示出发，在预先定义的语义里展开。

AI 更开放。系统可以依据已经批准的目的、当下的数据和执行反馈，生成事先没有完整列出的查询、控制流或工具组合。选择更多，不确定性也更多。

税务计算需要稳定、复现和持续审计，适合提前写成确定性程序。季度数据整理则不同：字段、缺失值和异常分布每次都在变化。长期保存的可以是指标定义、数据边界和验收规则，具体查询和清洗过程，等看到当期数据以后再生成。

边界也很实际：只有结果能够被可靠观察和验证的部分，才适合延迟实现。数据是否符合规则可以由程序检查；一份分析究竟有没有决策价值，仍然要由真正使用它的人判断。

## 抽象的账变了

传统软件复用的不只是代码，也是一套统一抽象。

为了让实现覆盖更多场景，我们提取领域模型，设计通用接口，引入框架和配置，再把后来出现的特殊情况收进同一套结构。后来的人先学习这套系统怎样划分世界，才能把自己的问题翻译成它接受的形式。

软件活得够久、复用得够广，这笔学习和维护成本就能被摊销。

运行时生成改了其中一部分账。

一段过程如果只服务当前任务，就未必值得为了想象中的复用，提前建一套覆盖所有情况的抽象。系统可以保留稳定的数据结构、访问边界和验收规则，再按照当前意图生成局部过程。

过去常常是人适应软件预先定义的工作方式。以后，更多具体实现可以在边界不变的前提下，适应眼前的问题。

抽象不会消失。Schema、协议、能力接口、不可变量和验证器，反而要更清楚，因为运行时生成必须被它们约束。

可能消失的，是应用层为了复用短命过程而不断膨胀的通用框架。复杂性也没有蒸发。它只是从代码库和使用者的学习成本，转移到意图表达、生成、验证和追溯。若这些环节无法检查，动态生成不过是把看得见的复杂结构，换成看不见的复杂行为。

只有值得长期共享的概念，才值得让所有人共同学习。

## 过程可以临时

运行时生成不能简化成：给模型一句话，让它自己想办法。

“给我一份有用的季度报告”只给了方向。怎样算有用，哪些数据不能碰，成本上限是多少，谁有权改变条件，都没有说。

如果执行者遇到困难就能修改目标、放宽验收或扩大权限，最后完成的已经不是原来的任务。

所以，过程可以留到运行时，目标和边界必须提前说清。系统至少要知道允许使用哪些数据和能力，可以承受多少成本，需要留下什么证据，以及谁能改变这些条件。

它可以换计划、换工具、重新生成实现，却不能静默改写自己要完成的事情。目标变化，应当形成新的提案，再交给有权决定的人。

一段代码通过测试，不会自动获得生产数据的访问权；一次 API 调用返回成功，也不表示真实目标已经完成。

所谓自主，不是模型拥有一切能力，而是它能在已经批准的目标和有限能力之间寻找过程。

实现可以临时，边界不能。

## 交付成为检查点

旅行应用仍然使用普通源码、测试和重新部署。它没有在运行时替自己生成产品代码。改变的只是使用反馈和下一次交付之间的距离。

这个距离也不只是小时数。需求要经过几次转述，开发者是否还记得问题发生时的情境，修改要在多少人和系统之间流转，都决定反馈能否真正回来。

项目可以每天发布，却始终没有解决真实使用中的问题。模型也可以几秒生成代码，但在修改经过确认、验证和迁移以前，反馈闭环仍然没有完成。

交付没有消失。它仍要确认一个版本在当前范围内可以使用，也要提供恢复和回退的边界。只是，交付不再天然意味着产品形成过程已经结束。

它更像一个经过验证的可用检查点：当前版本可以从这里投入使用，真实使用也会从这里推动下一轮变化。

这对个人化、短周期、强依赖情境的软件尤其明显。一个应用只存在几天，也可以在这几天里到达多个可用状态。活动结束后，它仍然可以被冻结、归档或删除。多次交付，不会自动把它变成长期资产。

## 两条循环

使用中的变化和运行时生成，很容易被说成同一件事。

它们不是。

系统为了处理当前数据，临时生成一条查询或一段清洗代码，属于一次任务内部的执行。只要目标、权限和验收没有变化，它仍在同一个执行边界里。

如果真实使用暴露出应用无法表达某类计划，原来的数据结构、验收方式或能力边界已经不够用，就要修改产品本身，形成新的可用版本。

前者以结果、失败或中止结束。后者要回到产品层，重新处理代码、契约、状态迁移和交付。

两条循环可以连接。某段运行时实现被反复使用，可能成为下一次产品修改的候选；一次使用暴露的问题，也可能让系统重新判断哪些过程应该提前实现。

但它们不能混成一条。当前任务重新规划，不等于产品已经有了新版本；产品进入下一次交付，也不表示它必须采用运行时生成。

更快的反馈不会自动导向更动态的软件，运行时生成也不代表软件会自己进化。它们只是松开了时间线上的不同位置。

## 代码何时成为资产

运行时生成的代码，不必只有“提交进仓库”和“彻底消失”两种结局。

只服务本次执行的实现，可以在结果通过验证、必要证据被保存后丢弃。可能有限复用的实现，可以连同适用目标、输入和环境一起缓存；再次使用前，重新检查这些条件。

当一段实现被频繁使用，开始产生外部依赖，需要人工维护，或者失败代价明显上升，才值得判断它是否应该成为长期代码。

确认以后，它应当被整理或重写，进入设计、审查、测试和发布流程。不能把一次运行中偶然生成的代码，原样倒回仓库。

过去，我们在开发前猜测什么值得复用。以后，一部分代码可以先在真实运行中证明自己的适用范围和责任，再决定是否进入代码库。

代码库因此更像长期责任的集合，而不是系统曾经找到过的所有解法。

## 不止一种时间

回头看，软件里至少有三种不同的时间。

一项责任值得维持多久，是寿命；具体实现必须在什么时候确定，是实现绑定；真实使用距离下一个可用版本有多远，是反馈。

它们彼此有关，却不能互相推出。

短寿命软件可以在几天里多次发布；长期系统可能因为风险很高而缓慢变化。一段实现只运行一次，不代表适合在运行时生成；采用运行时生成，也不代表产品本身变化得更快。

过去，我们习惯把它们压进同一条时间线：定义需求，设计编码，交付使用，最后收集反馈。软件开发从来没有真的这么整齐，只是理解、修改、验证和交付的成本，让它不得不表现得像这样。

AI 降低一部分成本以后，绑在一起的时间开始松动。具体过程可以晚一点确定，使用反馈可以早一点回来，一段代码也可以在证明值得维护以后再成为资产。

责任仍然要有明确落点，只是不必要求所有东西同时固定下来。

权限检查、状态机、关键规则、协议、验证器和恢复机制，仍然适合由长期维护的确定性程序承担。路径难以穷举、强依赖当前上下文、寿命很短而结果可以验证的过程，才适合留给运行时生成。

两种区域会长期共存。一条规则可能维护多年，一段临时实现只存在几分钟，执行证据却因为追溯需要保存更久。Git commit 仍然重要，但一次执行的版本边界已经开始延伸到代码之外：当时批准了什么，系统拥有什么能力，又凭什么接受结果。

硬实时控制、安全关键系统、结果难以验证或副作用无法恢复的任务，仍然更适合提前写成确定性程序。反馈回来得快，也不意味着可以把生产环境当测试场。变化越靠近真实使用，验证、状态迁移和回退越不能省。

AI 对软件工程更深的影响，也许不是把代码写得更快，而是重新安排软件里的时间：哪些责任必须提前固定，哪些实现可以等上下文出现以后再生成，哪些反馈还能赶在原来的事情结束前回来。

需求、开发、交付和使用仍然承担不同责任，只是不再必须按顺序发生。

实现可以晚一点。

责任不能。

## 相关材料

- [AI Software Engineering Notes](https://github.com/glenzli/ai-software-engineering-notes)：本文所依据的软件寿命、Agentic 工程与意图导向执行笔记。
- [In-Use Evolution](https://github.com/glenzli/ai-software-engineering-notes/blob/main/foundations/IN_USE_EVOLUTION.md)：真实使用如何在原始情境仍然有效时形成下一可用检查点。
- [Milestone II: Intent-Oriented Execution](https://github.com/glenzli/ai-software-engineering-notes/blob/main/milestone-2-intent-oriented-execution/README.md)：关于实现绑定时机、意图契约、运行时生成与产物晋升的研究假设。
- [行程扭蛋 / Plan Gacha](https://github.com/glenzli/plan-gacha)：旅行途中持续使用和修改的行程计划工具。
