一个没人分类的 issue 区,会在半年内变成一座没人敢进的仓库。
一、72 小时这个数字是怎么来的
2025 年底,syncwell 的 issue 区积压到 380 个未回复。许砚试过一个周末清空,结果周一又冒出 40 个。他意识到问题不在回复速度,在分类:没有分类,每个 issue 都要从头读一遍,读完还不知道该不该回。
以下情境为教学假设,人物、引语和数字不代表经核实的真实案例。
2026 年他定了一条公开承诺:新开 issue 在 72 小时内至少得到一次人工响应。响应不等于修复,可以是「已复现」「需要更多信息」「这是上游问题」。这条承诺的价值不在 72 小时,在于它强迫他每三天打开一次队列。
承诺还有一个副作用:它把「回不回」变成默认动作。没有承诺时,每个 issue 都要重新决定要不要回;有承诺时,默认是回,只有少数需要决定怎么回。决策次数的下降,比时间的下降更明显。
一年下来,新开 1,180 个 issue,关闭 1,046 个,净遗留 134 个。关闭的 1,046 个里,人工关闭 834 个,机器人关闭 212 个。分类总共花了 210 小时,平均每个 10.7 分钟。
首响承诺的关键不是时长,是「一定会有人来」。 用户能接受「这个问题我们暂时不修」,不能接受「我的问题消失了」。前者是判断,后者是忽视;分类的第一个动作,就是让每个 issue 至少得到一次判断。
72 小时是权衡的结果:24 小时会让维护者每天都活在工作中,一周又会让用户觉得没人在管。三天刚好覆盖一个周末,也给批处理留出空间。
72 小时还有一个隐含条件:它按自然时间算,不按工作日。这意味着周五晚上开的 issue,周一必须处理;如果按工作日算,同样的承诺会变成五天。写承诺时要把这一点写清楚,否则第一个周末就会有争议。
二、四层标签与一个模板
标签不是装饰,是路由。四层标签各回答一个问题:这是什么、在哪、多急、现在卡在哪。四层都填全,一个 issue 才进入可处理状态。
| 标签层 | 取值 | 回答的问题 | 谁填 |
|---|---|---|---|
| type | bug / feature / question / docs | 这是什么 | 维护者 |
| area | cli / sync / auth / docs | 影响哪块 | 维护者 |
| severity | P0 / P1 / P2 / P3 | 多急 | 维护者 |
| status | needs-info / confirmed / upstream / stale | 现在卡在哪 | 维护者或机器人 |
四层之外还有一个隐含字段:可复现性。有最小复现步骤的 issue,平均处理时间比没有的短一半以上。所以模板里必须有一栏「复现步骤」,并且设为必填;不填的 issue 自动打上 needs-info,七天后转 stale。
模板本身要克制。字段太多,用户会放弃提交;字段太少,维护者要来回问。一个可用的模板只有四块:你做了什么、期望什么、实际发生什么、版本与环境。四块都用短句,不用表格,因为表格会让手机端提交变得困难。
模板之外,还要有一个「最小复现仓库」的链接位。多数 bug 的沟通成本在环境差异,而不是描述不清;一个能一键复现的仓库,能把平均处理时间从 28 分钟压到 15 分钟左右。
status 这一层最容易被忽略,却最能减少重复劳动。upstream 表示问题在上游依赖,维护者只需要留一条链接;needs-info 表示等用户回复,不占用维护者的待办;stale 表示超过期限没有进展,机器人可以关闭。三种状态都不需要修复,但都需要被标出来。
needs-info 还有一个作用:它把等待责任转移给用户。标上之后,维护者的待办就清空了,issue 仍然开着;七天后没有回复,机器人提醒一次,再过七天转 stale。这条规则让「等回复」不再占用心理空间。
三、1,180 进、1,046 出、134 留
把 1,046 个关闭按处置方式拆开,会看到维护工作真正的形状。修复只占四成,其余六成是「解释」与「清理」。
| 处置 | 数量 | 占比 | 平均耗时 |
|---|---|---|---|
| 已修复 | 402 | 38.4% | 28 分钟 |
| 文档已答 | 132 | 12.6% | 9 分钟 |
| 无法复现 | 141 | 13.5% | 14 分钟 |
| 重复 | 96 | 9.2% | 6 分钟 |
| 上游问题 | 63 | 6.0% | 11 分钟 |
| 机器人关闭 | 212 | 20.3% | 0 分钟 |
| 合计 | 1,046 | 100.0% | — |
402 个修复平均 28 分钟,小计 187.6 小时;其余人工处置合计 432 个,平均约 10.5 分钟,小计 75.6 小时。两项相加 263 小时,超过分类的 210 小时——差额来自跨月:有些 issue 在 2025 年打开、2026 年关闭,工时记在 2026 年。
修复只占四成,是开源维护最反直觉的事实。 剩下六成不是浪费:文档已回答的那 132 个,每一个都是一次「产品没写清楚」的证据;无法复现的 141 个,每一个都在提示环境差异;重复的 96 个,说明搜索没找到已有答案。
遗留的 134 个按状态分布:needs-info 61 个、upstream 34 个、confirmed 27 个、stale 12 个。前两类不需要维护者动手,第三类是真待办,第四类等机器人关闭。真正压在待办里的只有 27 个,占全部遗留的 20.1%。
27 个真待办里,有 11 个是「已知但短期不修」的增强请求。这类 issue 应该单独标成 accepted,并写一句「接受但不排期」;不写的话,用户会以为你在做,三个月后再来问一次。
这个数字很重要。134 个听起来很多,会让人产生「永远清不完」的焦虑;拆开之后会发现,真正需要写代码的只有 27 个,其余都是等待或清理。焦虑来自没有分类,不来自工作量。
这个结论可以推广到所有维护工作:把「未处理」拆成「等别人」「等上游」「已接受不排期」「待修」四类,焦虑会下降一个量级。数字没有变,变的是每一类的下一步是否明确。
四、72 小时的可达性与一次复算
72 小时承诺达成得怎么样?全年 1,180 个 issue 里,首响超过 72 小时的有 99 个,占 8.4%。中位首响 26 小时,p90 是 71 小时。也就是说,九成 issue 在三天内得到了响应,剩下的一成集中在两个时间段:春节前后与三次发版周。
| 指标 | 数值 | 口径 |
|---|---|---|
| 中位首响 | 26 小时 | 从创建到第一条人工评论 |
| p90 首响 | 71 小时 | 九成 issue 不超过 |
| 超 72 小时 | 99 个 | 占 8.4% |
| 中位关闭 | 11 天 | 从创建到关闭 |
| 遗留 | 134 个 | 年末未关闭 |
超时集中在发版周,说明承诺的瓶颈不在日常分类,而在发版期间的注意力冲突。解法不是提高承诺,是把发版周的分类改成隔天一次,并提前在 README 里说明。
超时的 99 个里,有 61 个集中在三次发版周。发版周的分类频率从每天一次改成隔天一次,超时数在下半年降到 38 个;代价是当周的首响中位数从 26 小时升到 41 小时,但 72 小时的达成率反而更高。
复算:
新开 1,180;关闭 1,046;遗留 1,180 − 1,046 = 134
关闭构成:人工 834 + 机器人 212 = 1,046
人工构成:402 + 132 + 141 + 96 + 63 = 834
占比:402/1,046 = 38.4%;132/1,046 = 12.6%;141/1,046 = 13.5%
96/1,046 = 9.2%;63/1,046 = 6.0%;212/1,046 = 20.3%
分类成本:210 h ÷ 1,180 = 10.68 分钟/个 ≈ 10.7
修复成本:402 × 28 = 11,256 分钟 = 187.6 h
其余人工:432 × 10.5 = 4,536 分钟 = 75.6 h
人工合计:187.6 + 75.6 = 263.2 h(含跨年 issue)
首响:99 ÷ 1,180 = 8.4%;遗留中待办 27 ÷ 134 = 20.1%
复算里最容易被漏掉的是 263.2 小时与 210 小时的差。两个数都真实,但口径不同:前者按处置动作记,后者按分类动作记;把它们相加当成「issue 总成本」,会重复计算一次打开与一次关闭。
还有一个口径是「每关闭一个 issue 的平均成本」:263.2 小时 ÷ 1,046 个 = 15.1 分钟。这个数字可以用来估下一年的预算:如果新开数涨到 1,500,关闭数大致同比例涨,工时约 334 小时。
五、行动清单与复算验收
- 统计过去 12 个月的新开、关闭与遗留数量,三者要对得上。
- 把关闭原因分成修复、文档、无法复现、重复、上游、机器人六类。
- 建四层标签,先只启用 type 与 status 两层,稳定后再加另外两层。
- 写一个四字段的 issue 模板,把复现步骤设为必填。
- 定一个首响承诺,并统计真实的中位与 p90 首响。
- 找出超时的集中时段,调整那个时段的分类频率。
- 把遗留按 needs-info、upstream、confirmed、stale 拆开,只处理 confirmed。
- 给 stale 设一个自动关闭期限,并在关闭前留一条说明。
验收标准:任取一个 issue,都能说出它属于哪四层、卡在哪个状态、下一步由谁动作。
前四条是「把队列拆开」,后四条是「让队列自转」。如果只有一小时,先做第二条:知道关闭原因的结构,才知道该改产品、改文档还是改模板。
清单里最容易被跳过的是第七条。134 个遗留里有 107 个不需要写代码,把它们和真待办混在一起,会让维护者每天都觉得欠债。
使用边界与实操验收
10.7 分钟只覆盖分类,不覆盖修复。 修复的 187.6 小时单列;两者相加才是 issue 区的全部成本。
72 小时是承诺,不是 SLA。 它是社区约定,没有赔付;托管客户的支持档位另算,见第 8 篇。
标签不是越多越好。 四层已经够用;再加「优先级」「影响版本」「平台」会让维护成本超过收益。标签的价值在于能筛选,不在于能描述。
机器人关闭会伤感情。 自动关闭前必须留一条说明与重新打开的路径;否则用户会觉得被敷衍,下一封邮件就会发到赞助邮箱。
遗留数不是质量指标。 一个 134 个遗留但分类清楚的仓库,比一个 27 个遗留但没人知道卡在哪的仓库更健康。
关键参考与核验范围
- GitHub Docs:为项目建立健康的贡献流程 :用于核对 issue 模板、标签与贡献指南的落点。
- Open Source Guides:处理贡献 :用于核对 issue 分类与响应节奏的常见做法。
- RFC 2119 :用于核对贡献文档里「必须」「应该」这类措辞的强度。
以上链接于 2026-10-26 实测可公开访问;未核验版本、功能范围与政策更新。核验日期:2026-10-26。
范围上只讨论一个人维护项目的 issue 分类、标签与首响承诺,不讨论社区治理、贡献者激励与商业支持合同。
系列导航
- 上一篇:维护者的时间账:1,180 个 issue、148 个 PR 与 612 小时
- 下一篇:依赖与安全:214 条告警、11 条高危与三次安全公告
- 回到目录:一个人的开源产品:4,200 个 star、一百八十个付费与一年 612 小时的维护
- 相关阅读:一个人的自助支持:帮助中心、排查树与工单减少
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。