乐于分享
好东西不私藏

多子任务项目跑到后面,任务文档就是运维系统

多子任务项目跑到后面,任务文档就是运维系统

任务能跑任何人或 AI 都能接力:把流程、验收和现场沉淀进文档。

封面插画:让失败状态能够被记录、被追溯、被接力

目录

1.主文档、步骤文档、每日记录:三份东西,各管一段

2.不要只写“怎么跑”,要写“凭什么算通过”

3.复算比对里,产物清单往往比命令更重要

4.组合更新最怕的,是“到底执行了什么”说不清

5.每日记录不是流水账,要留下“结论 + 证据 + 下一步”

6. AI 的任务文档,少写形容词,多写字段

7.项目数据可以脱敏,任务结构不要脱敏

8.结尾:文档写到能接力,项目才真的能运维

做一个多子任务项目,最开始大家盯着的往往是同一件事:这条任务能不能跑通。

脚本能启动,数据能刷新,命令最后返回 0,事情看起来就算过去了。

但项目进入稳定运行后,问题会换一种样子出现。任务之间接不接得住?某一步失败后,后面到底该不该继续?第二天复盘时,能不能还原当时的现场?换一个同事,甚至换一个 AI 接手,还能不能不靠口头经验往下推进?

这次项目里,我越来越确信一件事:任务文档不是附属品。写到一定程度,它本身就是运维系统的一部分。

尤其是项目里同时有数据刷新、快照隔离、复算比对、组合更新、日志归档和 Gate 审计时,文档只写“怎么操作”远远不够。它还要定义每一步的输入、输出、通过标准、失败分支、产物路径,以及最后怎样合成整体状态。

真正需要沉淀的,不是一份无所不包的大说明,而是一组能共同运行的任务文档。

一、主文档、步骤文档、每日记录:三份东西,各管一段

这类项目里,比较有效的组织方式,是把文档拆成三层。

主执行文档管流程。

它不需要解释所有实现细节,重点是把顺序、依赖和总状态写死。例如:先做快照,再做数据刷新,再做复算比对,最后做组合更新。哪几步必须成功才能进入下一步,哪一步即使失败也要留下现场并继续,最终状态如何合成,都应由主文档负责。

这里最容易被忽略的是:后面的成功,不能覆盖前面的失败。

假设第三步复算比对失败,第四步组合更新仍按规则执行且成功了,最后不能因为第四步返回成功,就把当天写成“整体成功”。更准确的结论应该是:第三步失败,第四步已执行,整体非通过。

这不是文字上的较真。它决定了系统有没有保留真实状态,也决定了后续接手的人会不会被一个漂亮的退出码误导。

分步骤文档管细节。

每个子任务各自有一份说明:快照怎么复制,数据刷新怎样运行,复算比对必须生成什么文件,组合更新要核对哪些 manifest 和 Gate。这样做的好处,是把细节固定在离任务最近的地方。主文档不会膨胀成难以维护的长篇操作手册,执行人也不必在一份大文档里来回找规则。

每日记录管现场。

每日记录不是命令行的备份,更像当天现场的索引。目标日期、每一步状态、关键产物、失败原因、日志路径、Gate 结果和最终结论,都应该在里面。

以后定位问题,不该先去翻终端历史,而应该先打开当天记录:当时跑到了哪一步,哪个 Gate 没过,现场文件在哪里,后续任务有没有继续,下一步优先查什么。

主文档管流程,步骤文档管细节,每日记录管现场。三者合起来,才是一套能交接的系统。

二、不要只写怎么跑,要写凭什么算通过

很多任务文档写着写着,会退化成操作说明:运行某个脚本,等待完成,检查结果。

这当然是必要的,但只覆盖了第一层。复杂任务真正需要的是验收说明:退出码是否符合预期,主 Gate 是否通过,产物是否存在,文件数量和字节数是否一致,summary 是否显示 pass,manifest 里哪些字段必须满足条件。

以快照任务为例。

“把数据复制到当日目录”是一句操作说明,却不是验收标准。一个可验收的快照任务,至少要把下面几件事写清楚:快照根目录是什么,manifest 在哪里,每个数据域的 `source_file_count` 与 `dest_file_count` 是否一致,`source_bytes` 与 `dest_bytes` 是否一致,复制工具哪些退出码可接受,以及快照失败后后续步骤是否全部停止。

这些字段一旦写清,执行人或 AI 就不必猜“复制成功”到底意味着什么。

数据刷新也是同样的道理。命令跑完不等于任务通过。除了真实退出码,还要检查 recent download 的 Gate、short history 的主 Gate、关键报告文件和输出根目录。只有这些证据都满足,数据刷新才可以放行下一步。

可执行文档回答“怎么跑”;可验收文档回答“跑完以后,凭什么说它成功”。

后者才是连续任务真正的接口。

三、复算比对里,产物清单往往比命令更重要

复算比对最能说明文档的价值。

它表面上是在运行几条复算命令,实际上是在保留现场、生成差异,并把 live 端与历史端究竟差在哪里固定下来。命令只是入口;真正能支持排查和复盘的,是产物结构。

这次比较有用的一套约定,是把比对产物固定成“五件套”:`summary`、`detail`、`diff`、`live log summary` 和 `gate`。文件名固定,目录固定,字段含义也固定。

这样一来,失败时不必重新问“差异到底在哪”。`diff` 可以直接定位到节点、合约或标的,并展示 live 与 history 的对应值;复盘时也不需要为了回答一个基础问题再跑一遍,`summary` 已经记录了每个节点的 `live_count`、`history_count`、`match_count`、`diff_count` 和最大数值差异。

日志也需要有统一口径。比如不能只看最后一条 heartbeat,因为最后一条很可能已经是收盘后的状态。若记录了 `heartbeat_count`、`max_nonzero_target_count`、峰值 heartbeat 和最后 heartbeat,才能避免把“最后为零”误读成“全天没有信号”。

这里有一个很关键的取舍:第三步比对即使失败,后续任务也可能按既定规则继续。

前提不是“失败没关系”,而是失败已经被完整保留。现场、差异和 Gate 都在,失败成为一个可追溯状态,而不是一段被下一条成功日志覆盖掉的插曲。

只要产物结构稳定,后续的报告、排查和自动化才能接得上。

四、组合更新最怕的,是到底执行了什么说不清

组合更新比一般的批处理更需要写清边界。

它既涉及外部执行,也涉及资金、权重、节点状态和风控约束。如果文档只写“更新组合权重”,真正有风险的信息几乎都被省略了。

更稳妥的写法,是把验收拆成几层。

先看命令层。

任务必须前台阻塞执行,等待真实退出码。不能只看命令有没有启动;stdout 中应出现成功事件,并记录本次 `run_root`。

再看 manifest 层。

`run_root` 下应有 `command_manifest`、`offline_command_manifest`、`matlab_command_manifest`、`input_manifest`、`execution_manifest` 等文件。它们不是“存在就行”,还要核对关键字段:例如 `stage` 是否为 `all`,是否属于真实外部执行,`plan_only` 是否为 `false`,最大 worker 数和超时时间是否符合预设,以及是否明确不支持生产下单副作用。

然后是节点、输入和资金。

离线节点是否完整,状态是否为 `success` 或可接受的 `retained_success`,真实 `returncode` 是否为 0;外部模块的 `status`、`returncode`、stdout、stderr 是否留存。如果 `input_manifest` 有目标日期字段,它必须与当天目标日期一致;权重文件的 hash 也应被记录,方便事后确认当天究竟用了哪版输入。

资金层同样不能只看一个总数。`node_capital` 是否覆盖全部节点,权重和资金是否有限且非负,分配能否解释,`order_side_effects` 是否为 `false`,都需要成为明确的检查项。

最后还要写清 Gate 例外。有些 Gate 在正式外部执行时可能出现可接受的失败项,文档必须提前定义哪些例外可以接受、哪些绝不能接受。否则,执行人很容易在两个极端之间摇摆:看到一个 fail 就全部停掉,或者看到整体成功就忽略真正不可接受的风险。

组合更新的文档,本质上是在回答三个问题:这次是计划、模拟,还是真实执行?真实执行有没有越过生产边界?资金和权重有没有留下可追溯的证据?

五、每日记录不是流水账,要留下结论 证据 下一步

每日记录很容易写成屏幕输出的搬运。真正有用的记录,应该把当天的复杂现场压缩成三类信息。

先写结论。

每一步是 pass 还是 fail,整体状态是什么。如果中间失败、后续仍继续执行,总结里必须把这件事写出来。

再放证据。

关键产物、日志、manifest 和 Gate 文件的路径不需要全部展开,但必须让后来的人能一跳回到现场。

最后写下一步。

根因已经定位,就写明根因;尚未定位,就写优先排查入口:是输入未更新、数据不一致、外部模块失败,还是 live 与历史端使用了不同状态。

有一次,比对失败后,人工最终定位到原因是某个外部输入在早盘没有更新。这个信息不该用来改写“比对失败”的历史状态。失败仍然是失败,只是应在它后面补上一句:根因已定位,下一步把这个输入更新检查前置成 Gate。

这样下一次自动化或人工复盘,就不必从 `diff` 开始重新猜。每日记录的价值,不是证明当天做过什么,而是让下一次少走弯路。

六、给 AI 的任务文档,少写形容词,多写字段

如果任务文档将来还要交给 AI 执行,写法需要再硬一点。

少写“适当检查”“确认正常”“必要时继续”“重点关注异常”“记录关键结果”。这些话对人来说尚且需要上下文,对 AI 来说更像把关键判断留空。

多写:检查哪个文件,检查哪个字段,pass 的取值是什么,fail 后是否继续,继续以后整体状态如何写,哪些产物必须存在,哪些日志路径必须记录,哪些例外允许接受,哪些失败必须停止。

AI 擅长执行长链条任务,但前提是验收条件足够明确。文档越清楚,它需要临场猜测的空间就越小,越接近一个稳定的运维执行器。

人的判断不该被文档替代。人负责制定规则、解释异常、决定例外;执行者——无论是同事、脚本还是 AI——负责按顺序运行、检查 Gate、记录产物和合成状态。

这才是分工。

七、项目数据可以脱敏,任务结构不要脱敏

把这类经验沉淀成方法论时,项目名称、路径、策略节点、数据文件当然可以脱敏。

但任务结构最好保留下来。

真正可复用的东西,是主执行文档如何组织,为什么 Step 1、Step 2 必须成功才能继续,为什么 Step 3 失败后仍可能执行 Step 4,每一步如何定义 Gate,产物如何固定命名,每日记录如何合成整体状态,已定位根因如何回写到记录和长期 memory,以及怎样把人工发现的问题前置成下一次自动校验。

这些结构不涉及敏感数据,却是最值得复制的部分。

一个多子任务项目,只要把这些关系写清楚,后面无论换成人执行、AI 执行,还是脚本执行,大家都能沿着同一套判断口径往下走。

结尾:文档写到能接力,项目才真的能运维

多子任务项目做到后面,文档的目标不只是“让别人看懂”。

而是让别人能接着跑。

一个人今天执行到第三步失败,另一个人明天打开记录,应该能知道失败在哪里、现场在哪里、后续有没有执行、整体状态是什么、下一步从哪里查起。AI 在半夜接手任务,也应能据此判断哪些步骤能继续,哪些必须停止,哪些失败需要保留但不阻塞后续。

复杂项目最后能不能跑稳,靠的不是某个人记性好,也不是有人天天盯着。

靠的是任务文档把人的判断、机器的执行和系统的状态接在一起。

文档写到这个程度,它就不再是项目附件。

它就是项目的一部分。