本文定义 backlog、版本计划、技术提案和 CHANGELOG 的权责边界。目标不是增加文档层级,而是让每个 事实只有一个维护位置,并让 CI 阻止编号、范围和状态漂移。
| 文档 | 唯一负责 | 不得维护 |
|---|---|---|
| backlog 碎片 | 条目编号、标题、动机、目标版本、实施状态、Proposal 指针 | 版本优先级、实施顺序、验收条件、技术方案正文 |
| backlog 入口 | 台账阅读入口、编号前缀与维护规则 | 条目行本身——它们住在 backlog.d/ 碎片里 |
| 当前版本计划 | 版本目标、P0/P1/P2、依赖与实施顺序、版本验收和退出条件 | 条目实施状态、重复的条目标题、方案裁决正文 |
| Proposal | API / wire、状态机、边界、兼容策略、资源预算、验证方案和设计裁决 | 排期优先级、实施进度、发布结果 |
| design.md | 已接受且跨版本长期有效的设计立场 | 尚未裁决的方案和单版本排期 |
| 根 README、guide、全部包与 example README | 当前稳定版的安装、入口、能力与限制 | 已淘汰安装方式、旧版状态和实施过程 |
skills/*/SKILL.md / INSTALL.md |
Agent 发现与任务路由、安全边界、Skill 安装及渐进式披露入口 | 手写复制 live catalog、descriptor、完整命令表或 guide 正文 |
docs/assets/*.svg |
当前架构与首页能力摘要 | 已删除组件、接入方业务词和旧版命令示例 |
changelog.d/<version>/ / CHANGELOG.md |
已实现的用户可见变化 | 待办、设计备选和实施过程 |
releases/、proposals/、CHANGELOG、版本化兼容语料 |
对应版本的计划、裁决与发布证据 | 当前版安装入口 |
同一字段不得在两个文档中维护。为了可读性,版本计划可以多次引用 PB 编号,但范围表只写编号和 验收,不复制 backlog 标题;Proposal 的“状态”只表示设计是否被接受,不代表条目实施进度。
对外当前文档与历史证据严格分区:README、guide、包 README、design 和 SVG 只能描述当前稳定事实;
旧版本号、旧安装源和当时状态只留在版本计划、Proposal、CHANGELOG 与版本化兼容语料。正式版必须在
打 tag 前完成当前文档,不能以“发布后再改 README”制造一个文档已过期的 tag。release_prep 对受管
版本锚点执行精确替换,并对旧安装口径、非中性命令示例和架构 SVG 能力执行 fail-closed 检查。
发现问题
-> backlog 建号(待排期)
-> 版本范围 MR(目标版本 + P0/P1/P2 + 验收)
-> 必要时 Proposal(提案中)
-> design-gate 裁决(Proposal 已接受 / 已否决)
-> 实现 MR(实现中)
-> 验证完成(已验证)
-> 发布 MR 聚合到 CHANGELOG
-> 发布完成后 finalize 删除该条目的 backlog 碎片
范围、方案和实现允许在同一个 MR 中推进的前提是变更仍可独立评审且没有绕过裁决。存在未决 design-gate 时,实现代码不得先行合入。
台账是 docs/backlog.d/ 下一条目一个碎片文件,不是一张入库的大表。理由与 changelog.d/
相同:写入按条目独占,存储也必须按条目独占,否则并行 MR 改各自的状态行却落在同一文件的相邻行,
三方合并稳定撞成 hunk 冲突。
- 实现 MR 只改自己条目的碎片。 不顺手整理别人的碎片,不把多个条目的状态合进一次编辑。
- 不要以任何形式重新引入入库的总表(包括「由工具生成、随 MR 提交」的版本):生成物同样会被每个
实现 MR 重写,冲突原样回来。要看全表用
dart run tool/backlog_render.dart按需现渲,看完即弃。 - 编号前缀决定种类(
PB/BUG/DOC/DG),文件名必须与 frontmatter 的id一致。 - 字段、状态词表、单行小节约束和链接前缀规则以
backlog.d/README.md为准, 由check_planning机检。
满足任一条件的条目,在进入实现 MR 前必须有 docs/proposals/<version>/ 下的 Proposal:
- 新增或修改公共 API、wire 字段、命令 descriptor 或稳定 JSON 输出;
- 引入状态机、异步 job、超时、重试、取消、租约或资源上限;
- 横跨
patchbay、patchbay_cli、patchbay_flutter或接入方适配层; - 改变默认行为、安全边界、脱敏规则、兼容或降级语义;
- backlog 标记了
design-gate; - 同一能力需要 VM Service、direct 或两个接入方共同验证。
纯文案、测试补强、明确的生成物修复和不改变外部行为的重构,可以在 MR 中直接写清契约和验收, 无需为了形式新增 Proposal。
Proposal 必须使用模板,并至少冻结:目标/非目标、公共契约、状态与失败语义、
兼容策略、资源预算、测试矩阵、待裁决问题。Proposal 处于“提案中”时只能做原型验证;合入实现前
必须改为“已接受”,并把长期设计结论同步到 design.md。
- 范围 MR 同时更新条目碎片和对应版本计划;不改变运行时行为,无需 CHANGELOG 碎片。
- Proposal MR 写
Plan: PB-...和关联的DG-...,不把“默认建议”当成已裁决事实。 - 实现 MR 必须引用已接受 Proposal;实现若偏离,先更新 Proposal 并重新评审。
- 范围延期先改版本计划,再把条目碎片的
target清成—;禁止只改其中一份。 - 发布 MR 聚合 CHANGELOG 并定版版本号,不动 backlog 碎片和版本计划状态,也不回写 Proposal 的 实施状态。
- 发布收尾由
tool/release_finalize.dart在四包实际发布之后执行:删除已完成条目的碎片、 把版本计划标为已发布。它的产物走一个小 MR 合回main(main受保护,不接受直接推送)。 顺序不能颠倒——finalize 会写下「已发布」,在包还没上 pub.dev 时执行等于替未发生的事实背书; 而四包是按依赖顺序逐个推、可能中途被拒的,先删碎片再发布会留下台账已清空、版本却没发出去 且无处回滚的悬空状态。
MR 的边界按“能否独立评审、验收和回退”决定,不按 PB 数量或文件数量机械切分。以下情况应放进同一个 MR:共同改变一项公共契约、重写同一热点调用链、必须联合验收,或拆开后任一部分不能形成可用结果。 以下情况才适合拆分:依赖方向单一,验收可以独立判定,任一 MR 回退都不会让另一项语义失真。
- 堆叠 MR 默认不超过三层;共同底座先合入,再让上层 rebase。
- 三个及以上并行分支会修改同一热点时,改为共同交付分支或串行推进,不能继续扩大兄弟分支数量。
- 集成候选只用于固定输入 SHA 后的联合验收,不作为功能 MR。候选里发现的语义冲突回到来源 MR 修复。
- 单个 PB 可以跨多个 MR,但每个 MR 都要给出自己的结果、验收和回退边界;多个 PB 也可在边界不可拆时 合成一个 MR,并在描述中解释原因。
MR 模板必须声明目标分支、依赖链和交付单元类型。评审时先判断边界是否成立,再看代码规模;行数只是 风险信号,不是拆分指标。
main 只接定版合并:它的每个提交都对应一个已发布版本或 hotfix,因此始终可构建、可测试、可发布,
git log main 就是发布史。版本开发使用临时 dev/<SemVer> 分支:
- 从稳定
main创建dev/<SemVer>,该版本的功能 MR 默认以它为目标; - 堆叠 MR 在父 MR 合入前以父分支为目标,合入后及时 rebase 到版本分支;
- 冻结用状态表达而不是再切一条分支:把版本计划的
> 状态:推进到RC即冻结范围,此后只接发布 阻断修复,并在版本分支完成 CI、兼容和接入方真机验收; - 通过退出条件后,用一个发布 MR 把版本分支合回
main,再同步 GitHub、打 tag 和发布。版本号 bump 与 CHANGELOG 聚合属于这个发布 MR,不散落在功能分支里; - 发布完成后回收版本分支。只有明确承担维护线时才长期保留。
分支叫 dev/ 而不是 release/:它从版本周期第一天就在接功能 MR,一生中绝大部分时间并不处于发布
状态;沿用 release/ 会让评审误以为目标分支已经冻结。同理,这里不引入常驻 develop——版本作用域的
分支随版本回收,不会长期分叉,也省掉每次发布和 hotfix 后的回合成本。代价是下一版的工作在当前版本
活跃期间只能留在 backlog 等待,这与 P2「不用低优先级新功能填充补丁版」的口径一致。
紧急修复从 main 创建 hotfix/<SemVer>,验证后先合回 main,再前向合入仍活跃的版本分支。任何
分支都不得绕过 Proposal、CHANGELOG 或测试门禁;版本分支用于稳定化,不是降低质量门槛。
当前活跃版本分支见版本计划目录。各版本发布时的历史做法只记在该版本自己的计划里, 本文只描述当前规则。
仓根运行:
$ dart run tool/check_planning.dart # 结构 + 跨文档一致性,CI 门禁
$ dart run tool/backlog_render.dart # 按需渲染只读台账总表,不提交CI 会检查:
AGENTS.md存在,CLAUDE.md只包含@AGENTS.md,防止 Agent 指令双真源;- 每个 backlog 碎片的文件名与 frontmatter
id一致(编号唯一由此保证),字段与正文小节都在封闭集 内、必填项齐全、小节单行且可渲染成表格单元格、仓内链接带../前缀; - 实施状态与目标版本属于封闭枚举(design-gate 另有自己的状态词表);
- 目标为当前版本的 PB 条目,在对应版本计划 P0/P1/P2 范围表中恰好出现一次;
- 版本范围表不引用不存在的 PB,也不复制 backlog 的标题列;
- 碎片中引用的 Proposal 和 design-gate 文件/编号存在,且 Proposal 声明了该编号;
- 标记
待裁决的条目必须同时引用 Proposal 和 design-gate; docs/backlog.md没有重新长出条目行——入库总表一旦回潮,碎片化消除的冲突会原样回来。release_prep另行检查当前文档的版本锚点、hosted 安装口径、中性示例与架构 SVG;历史区不参与 当前版本漂移判定。
packages/patchbay_cli/tool/command_docs.dart --check 另行验证 Skill frontmatter、配套 INSTALL.md 与
只读起步命令生成块;Skill 只路由到 live catalog / describe / help,不维护第二份可变命令事实。
检查脚本只验证结构关系,不替代对方案内容和验收质量的评审。