项目周会上,第一个里程碑报"已完成 90%"。三周后它还是 90%,又过了两周变成 85%——因为发现了漏项。项目最终延期一个月,而在这一个月里,所有人一直相信"就差一点"。
问题不在执行,而在**"完成"这个词从来没有被定义过**。里程碑如果不写清"到哪一步算到了",它就不是一个检查点,而是一个心理安慰。
1. 里程碑该定义什么
一个可用的里程碑包含四件事,缺一件它就无法判定。
| 要素 | 说明 | 缺失后果 |
|---|---|---|
| 产出的东西 | 具体到可指认的物件(文档、接口、可运行的环境) | "做完了"变成主观判断 |
| 验收方式 | 谁、用什么方式确认 | 无人签字,状态靠自报 |
| 完成的判据 | 可观测的条件,二值 | 百分比出现,进度不可信 |
| 不包含什么 | 明确排除项 | 后期不断"补漏",百分比倒退 |
这四项还有个使用上的次序:先定"不包含什么",再定"完成的判据"。反过来的话,判据会不自觉地包含所有能想到的东西,因为它总想显得完整;而排除项一旦写下,判据自然收窄。
第三项最关键:完成的判据必须是二值的。"完成 90%"这种表述之所以有害,是因为它不可验证,也不可否认。它把"还剩多少"这个问题从可观测变成了可协商。
2. 百分比为什么必然出现
它不是员工的表达习惯问题,而是三个结构性原因。
| 原因 | 机制 | 替代做法 |
|---|---|---|
| 里程碑本身不可二值判定 | 没有判据,只能估 | 先把判据写死 |
| 阶段过长 | 一个里程碑跨两个月,中间无反馈 | 拆成 1–2 周可判定的子节点 |
| 汇报要求连续进度 | 周报必须填一个数 | 改为"未开始 / 进行中 / 已达成 / 已阻塞"四态 |
两种汇报形态的差别可以直接看出来:
// 坏的样子:连续四周的同一句话
M2 下单链路灰度可切 90% 预计下周完成
M2 下单链路灰度可切 95% 预计下周完成
M2 下单链路灰度可切 85% 发现漏项,需一周
M2 下单链路灰度可切 95% 预计下周完成
// 好的样子:状态 + 阻塞点,四周内两升一降
M2 未开始 —
M3 已阻塞 等待测试环境,已提资源单,预计 2 天
M3 进行中 三个渠道中两个已通,第三个卡在回调验签
M3 已达成(验证:张三、李四,11-08) 记录见 #412
第三条常被忽略:如果汇报模板要求填百分比,人就一定会填百分比。模板设计决定了信息质量,这比要求大家"如实汇报"有效得多。
四态里最有价值的是"已阻塞"——它强制说出卡在哪里。而"完成 90%"永远不会暴露阻塞,因为 90% 可以包含任何东西。
3. 判据怎么写
好的判据有共同形状:一个动作 + 一个可观测结果。
| 里程碑类型 | 模糊写法 | 可判定写法 |
|---|---|---|
| 设计完成 | 方案设计完成 | 评审会通过,记录中无未决项 |
| 接口就绪 | 接口开发完成 | 三个调用方在测试环境调通,返回样例归档 |
| 数据迁移 | 数据迁移完成 | 全量比对差异为 0,且连续两天复跑一致 |
| 上线 | 功能上线 | 灰度 100%,观察 24 小时无 P1/P2 |
| 性能达标 | 性能优化完成 | 目标接口 p99 ≤ 目标值,压测报告归档 |
注意每一行都包含"谁/在哪/什么结果",而不只是"做完了"。
判据里最容易写坏的是时间相关的条件。"观察 24 小时"这类判据看起来可判定,实际上缺了起止定义,就变成了可协商。完整的写法要补三样:观察起点、观察窗口内的失败判据、失败后的处置。
// 时间类判据的三件套
起点:灰度到 100% 的时刻(记录在变更单里)
窗口:24 小时
失败判据:出现任一 P1/P2,或错误率高于基线 2 倍
处置:立即回滚,里程碑状态回到"进行中",不以"已完成只是有缺陷"记录
第二行的"三个调用方在测试环境调通"比"接口开发完成"多出的信息量,恰好是后期返工的主要来源。
// 里程碑定义的最小模板:每个字段都要能被第三方核对
milestone:
id: M2
name: "下单链路灰度可切"
deliverable: // 可指认的物件
- "灰度开关配置(已合入主干)"
- "回滚脚本(已在测试环境执行过一次)"
done_when: // 二值判据,不允许出现百分比
- "测试环境三个渠道各完成 50 单,成功率 100%"
- "回滚演练耗时 < 10 分钟,记录归档"
verified_by: "张三(QA)+ 李四(后端)" // 签字的人,不是"团队"
not_included: // 明确排除,防止后期补漏
- "历史订单迁移"
- "移动端适配"
还有一条实践上的建议:一个里程碑的判据条目数不要超过五条。条目越多,越难全部满足,也越容易在临近时被"合并同类项"模糊掉。超过五条通常意味着它应该被拆成两个节点。
not_included 是四个字段里最容易被省掉、也最能减少争议的一个。
4. 里程碑之间的依赖
单独看每个里程碑都合理,串起来就会出问题。
| 依赖形态 | 风险 | 缓解 |
|---|---|---|
| 串行(A 完成后 B 才能开始) | 任一延期全链延期 | 尽量把可并行的部分拆出来 |
| 前置资源冲突(同一批人做 A 和 B) | 隐性串行,排期表看不出来 | 排期时按人核算,不按阶段核算 |
| 验收依赖外部方 | 自己无法控制完成判定 | 把"外部确认"单独设为一个里程碑 |
| 环境依赖 | 环境不到位则无法验证 | 环境就绪单独成节点 |
第三种常被漏掉:当里程碑的验收需要客户或第三方确认时,这个确认动作本身应该是一个独立节点,否则它会被算进"我们这边完成了"。
依赖关系还有一层:每个里程碑都应当写明它阻塞了谁。只写"我依赖什么"是单向的,某个节点延期时,没人知道影响面。双向依赖表在排期评审时就该出现。
// 双向依赖:谁依赖我,比 我依赖谁 更能暴露风险
M2:
depends_on: [M1]
blocks: [M4, M5] // 这两项在 M2 延期时要同步重排
M3:
depends_on: [M1.5] // 环境就绪
blocks: []
// blocks 为空的节点延期,影响面小;blocks 长的节点应该优先保障资源
第三种常被漏掉:当里程碑的验收需要客户或第三方确认时,这个确认动作本身应该是一个独立节点,否则它会被算进"我们这边完成了"。
// 排期自检:按人核算,暴露隐性串行
bin/plan-check --plan milestones.yaml \
--resource owners.yaml \
--report conflicts
// 输出示例
// M2 与 M3 均需 张三 (0.6 + 0.8 = 1.4 FTE) → 隐性串行,实际完成时间后移
// M4 verified_by 李四,但李四在 M3 期间无可用工时 → 验收节点应独立排期
// M5 依赖 测试环境,环境就绪未列为里程碑 → 建议新增 M1.5
5. 判定与签字
谁来说"到了",比判据本身更容易出问题。
| 判定方式 | 可靠性 | 问题 |
|---|---|---|
| 执行人自报 | 低 | 利益相关,倾向报喜 |
| 项目经理判定 | 中 | 可能不了解技术细节 |
| 约定的验收人判定 | 高 | 需要提前指定,且要有时间 |
| 自动化判定(脚本/报表) | 最高 | 只适用于可完全自动化的判据 |
第四种最理想但适用范围窄。多数里程碑只能靠第三种,而它的前提是验收人在里程碑定义时就确定——不能等到要验收时再找。
签字环节还有一个具体安排:验收人需要在里程碑定义时就确认自己有时间,而不是到期时再被通知。这一步在排期表里通常没有体现,于是验收环节经常成为实际延期点。
签字这件事也必须落到名字。写到"团队确认"的里程碑,等于没有人确认。
6. 排错:五种"里程碑到了但没到"
| 现象 | 成因 | 处理方向 |
|---|---|---|
| 长期停在 90% | 判据不可二值,只能估 | 重写判据为可观测条件 |
| 达成后又倒退 | 无 not_included,后期补漏 |
补排除项,或把补漏单列为新节点 |
| 每个里程碑都"基本完成" | 判定人 = 执行人 | 指定独立验收人 |
| 依赖引发的延期无人预警 | 资源冲突未按人核算 | 排期时按 FTE 核算 |
| 上线节点反复推迟 | 判据含"观察 24 小时"但无起始条件 | 写明观察起点与失败后的处置 |
这些现象的共性可以归成一句:它们都不是执行不力,而是定义缺失。定义缺失的里程碑在前期表现为"进展顺利",在后期表现为"反复推迟",而它从来不产生一条可归因的故障记录——所以它是项目里最难复盘的一类问题。
第五条是很实际的一类:判据里写了"观察 24 小时",但没写从什么时候开始算、观察到异常怎么办。于是每次临近就重新定义一次,节点自然反复推迟。
7. 边界:什么情况不需要正式里程碑
| 场景 | 为什么 | 做法 |
|---|---|---|
| 周期短于两周 | 中间设点成本高于收益 | 一个终点判据即可 |
| 单人项目 | 判定与执行天然重合 | 保留判据,不必签字流程 |
| 探索性工作 | 产出形态未定 | 以"投入上限 + 检查点"代替里程碑 |
| 持续运维类工作 | 无终态 | 用 SLO 与周期检查代替 |
判断口径一句话:里程碑是用来说"到了"的,不是用来说"还差一点"的。如果一个节点无法在某一刻被明确判定为"到了",它更可能是任务而不是里程碑。
8. 自测
- 一个可用的里程碑必须包含哪四件事?缺了"不包含什么"会导致什么具体后果?
- 为什么"完成 90%"这种表述不可验证也不可否认?它与"还剩多少"这个问题的关系是什么?
- 汇报模板要求填百分比,为什么必然导致百分比失真?四态汇报里最有价值的是哪一态?
- 可判定判据的共同形状是什么?"接口开发完成"应改写成什么?
- 当验收依赖外部方时,为什么要把"外部确认"单独设为一个里程碑?
- 为什么说"里程碑是用来说到了的,不是用来说还差一点的"?