From d271983ab498f38bbf6c9288ea3b7ea1041a7a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E9=94=90?= Date: Mon, 17 Aug 2026 12:36:30 +0800 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20=E8=A7=84=E5=88=92=20Patchbay=200.4?= =?UTF-8?q?.0=20=E7=89=88=E6=9C=AC=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/backlog.md | 64 +++++++++-------- docs/releases/0.4.0.md | 155 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 29 deletions(-) create mode 100644 docs/releases/0.4.0.md diff --git a/docs/backlog.md b/docs/backlog.md index 9855b79..15b97ec 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -4,6 +4,9 @@ > 完成后随发版移入 CHANGELOG 对应版本段并从此处删行。`design-gate` 条目未经仓主裁决 > 不得进入实现 MR。只记结论与指针,不写过程叙事;裁决理由在对应 MR / note。 > 已裁决不做的方向见 [design.md 的非目标台账](design.md),此处不重复、不重提。 +> +> 当前排期见 [Patchbay 0.4.0 版本计划](releases/0.4.0.md)。进入版本计划不等于越过设计闸门; +> `待裁决` 条目必须先完成对应裁决,才能进入实现 MR。 ## 缺陷 @@ -11,30 +14,30 @@ |---|---|---| | (暂无已知未修缺陷) | | | -## 特性(待排期) - -| 条目 | 动机 / 出处 | 备注 | -|---|---|---| -| 锚定式手势 `ui.gesture.*`:press-hold / drag 路径 / fling,identifier 锚定 + 相对比例坐标 + 代际围栏 | 接入方真机验证分工:方向盘按压态、小窗拖动只能 adb 坐标打 | **design-gate** | -| 定时 capture + golden diff:第 N 帧截取、两帧差异率 | 接入方:首帧变形取证只能 screencap 关键帧对比(Flutter 自绘部分可收编;OS 合成层不做,见非目标) | | -| 屏幕唤醒:会话活跃期间 app 自动 keep-screen-on(Android `FLAG_KEEP_SCREEN_ON` + iOS `isIdleTimerDisabled`,会话静默自动释放,debug-only) | 真机调试息屏即 UI 面全拒(实测),iOS 无系统级 stay-awake;默认自动还是手动为 **design-gate**(自动会使息屏行为本身的测试失真,需留关闭出口)。同批的 lifecycle 提示与 `patchbay doctor` 已实现 | design-gate | -| host 侧声明 `snapshotSelectors` capability,CLI 据此判定而非猜测失败形态 | 现状是 CLI 捕获 `invalidParams` / `protocolError` 反推「老 host」,能给出类型化拒绝但属推断;正路是 host 声明能力 | 前置已解除:协议演进套件(feature capabilities)已合入(849043a),当前 CLI 侧类型化降级只是临时兜法 | -| 统一 CommandRegistry:descriptor+decoder+gate+handler+validator 过同一 dispatcher | 第二 consumer 手写 adapter 的元键坑已实证核心不机检 descriptor 语义的风险 | | -| CLI 注册 / 帮助表改由命令 descriptor 生成 | `packages/patchbay_cli/lib/src/cli.dart` 的手写 switch 臂是 0.3.0 并行开发中最大的一类冲突源——每支加命令都改同一处 | 与上一行的统一 CommandRegistry 捆做 | -| README / 文档命令参考表由 descriptor / help 输出生成 | 双语 README 与包 README 的命令表靠人肉逐字节核对保持一致 | 依赖上一行的 descriptor 生成落地 | -| 幂等 retryPolicy(external 命令按 requestId 去重);审计 sink(可注入、记脱敏参数形状);CLI `describe` | dogfood(`doctor` 已实现) | | -| DevTools 借用剩余两批:perf VM RPC → net 画像 | 规划稿已交仓主;第一批 inspect 开关已合入 main | net 画像 **design-gate**(脱敏评审) | -| snapshot revision / diff | dogfood(低优先级) | | -| launcher 监督循环收编:把首个接入方项目级的重连监督(退避策略 + machine-frame 生命周期 + 断连判读)抽为 patchbay_cli 通用 `launch` 能力;会话记录 schema 增显式 pending 状态位(现依赖 consumer 侧以自身 PID 通过探活的巧劲,跨仓契约应显式化) | 首个接入方已落项目级实现并真机验证;第二接入方已集成 session store,其启动器必复踩「断连即退」 | 等首个实现合入烤几天 + 第二试点确认形态 | -| `ui verify-manifest` 按 destination 逐屏巡检:驱动导航依次落到每个被声明的屏,覆盖非常驻控件 | v1 只对账当前挂载态、`destination` 仅作过滤(已落,见 CHANGELOG Unreleased);巡检要驱动导航,改变「只读对账」的性质 | | -| `ui verify-manifest` 接受 YAML manifest | v1 只认 JSON;大清单人手维护 YAML 更省事,但要引入解析依赖 | | -| `ui verify-manifest` 覆盖 Semantics identifier(`ui tap` 的目标面) | catalog `uiTargets` 只登记 `PatchbayKey` 注册的 text / capture 目标,可点控件的 identifier 不在其中;要取 `ui.semantics.tree`,那是另一个命名空间和另一套挂载语义 | | -| `ui targets --emit-manifest`:从活体 catalog 生成 expected-targets manifest 初稿 | 真机验收现在要照着 catalog 手抄 `ui verify-manifest` 清单 | | -| `wire_codegen --write` 顺手刷新协议面 surface golden | golden 重生成是与 codegen 分离的手工步骤(`PATCHBAY_UPDATE_GOLDENS=1 dart test`),哨兵只在聚合 / rebase 期才触发:0.3.0 四支各自绿、合成才红,一次性补进 12 个 wire 类型(7eb6236) | | -| `release_prep --apply` 覆盖 `patchbayPackageVersion` 与两份 README 的版本引用 | apply 代改四包 version 却不动这两处,只有 `release_version_parity_test` 事后兜住(0.3.0 定版实撞:apply 后测试红);该常量被 host 当 `serverVersion` 报给客户端,漂移即全网 App 谎报构建 | | -| `release_prep --apply` 时自动冻结本版协议面进兼容语料库 | `packages/patchbay_cli/test/golden/legacy_host_v0_2_0/` 一类的旧版语料是手工冻结的,版本过去后不可再生成 | | -| command_codegen check 的样例 contract 瘦身 | `packages/patchbay/contracts/example_commands.g.dart` 208 行生成物只为喂 drift 门禁而长期入仓,应改由真实命令声明推导 | | -| CHANGELOG 碎片化:`changelog.d/` 每 MR 一文件 + `release_prep` 聚合 | 0.3.0 每对并行分支都在根 CHANGELOG 同一处相撞,是结构性冲突源 | | +## 特性 + +| 编号 | 条目 | 动机 / 出处 | 目标版本 | 状态 / 备注 | +|---|---|---|---|---| +| PB-040-01 | 锚定式手势 `ui.gesture.*`:press-hold / drag 路径 / fling,identifier 锚定 + 相对比例坐标 + 代际围栏 | 接入方真机验证分工:方向盘按压态、小窗拖动只能 adb 坐标打 | 0.4.0 | **待裁决**:DG-040-01 | +| PB-040-02 | 定时 capture + golden diff:第 N 帧截取、两帧差异率 | 接入方:首帧变形取证只能 screencap 关键帧对比(Flutter 自绘部分可收编;OS 合成层不做,见非目标) | 0.4.0 | 已排期(P1) | +| PB-040-03 | 屏幕唤醒:会话活跃期间 app 自动 keep-screen-on(Android `FLAG_KEEP_SCREEN_ON` + iOS `isIdleTimerDisabled`,会话静默自动释放,debug-only) | 真机调试息屏即 UI 面全拒(实测),iOS 无系统级 stay-awake;自动会使息屏行为本身的测试失真,需留关闭出口。同批的 lifecycle 提示与 `patchbay doctor` 已实现 | 0.4.0 | **待裁决**:DG-040-02 | +| PB-040-04 | host 侧声明 `snapshotSelectors` capability,CLI 据此判定而非猜测失败形态 | 现状是 CLI 捕获 `invalidParams` / `protocolError` 反推「老 host」,能给出类型化拒绝但属推断;正路是 host 声明能力 | 0.4.0 | 已排期(P0);前置已解除:feature capabilities 已合入(849043a) | +| PB-040-05 | 统一 CommandRegistry:descriptor+decoder+gate+handler+validator 过同一 dispatcher | 第二 consumer 手写 adapter 的元键坑已实证核心不机检 descriptor 语义的风险 | 0.4.0 | 已排期(P0) | +| PB-040-06 | CLI 注册 / 帮助表改由命令 descriptor 生成 | `packages/patchbay_cli/lib/src/cli.dart` 的手写 switch 臂是 0.3.0 并行开发中最大的一类冲突源——每支加命令都改同一处 | 0.4.0 | 已排期(P0);依赖 PB-040-05 | +| PB-040-07 | README / 文档命令参考表由 descriptor / help 输出生成 | 双语 README 与包 README 的命令表靠人肉逐字节核对保持一致 | 0.4.0 | 已排期(P0);依赖 PB-040-06 | +| PB-040-08 | 幂等 retryPolicy(external 命令按 requestId 去重);审计 sink(可注入、记脱敏参数形状);CLI `describe` | dogfood(`doctor` 已实现) | 0.4.0 | 已排期(P1);依赖 PB-040-05 | +| PB-040-09 | DevTools 借用剩余两批:perf VM RPC → net 画像 | 规划稿已交仓主;第一批 inspect 开关已合入 main | 0.4.0 | perf 已排期(P1);net **待裁决**:DG-040-03 | +| PB-040-10 | snapshot revision / diff | dogfood(低优先级) | 0.4.0 | 已排期(P2) | +| PB-040-11 | launcher 监督循环收编:把首个接入方项目级的重连监督(退避策略 + machine-frame 生命周期 + 断连判读)抽为 patchbay_cli 通用 `launch` 能力;会话记录 schema 增显式 pending 状态位(现依赖 consumer 侧以自身 PID 通过探活的巧劲,跨仓契约应显式化) | 首个接入方已落项目级实现并真机验证;第二接入方已集成 session store,其启动器必复踩「断连即退」 | 0.4.0 | 已排期(P0);待首个实现烤稳与第二试点确认形态 | +| PB-040-12 | `ui verify-manifest` 按 destination 逐屏巡检:驱动导航依次落到每个被声明的屏,覆盖非常驻控件 | v1 只对账当前挂载态、`destination` 仅作过滤(已落,见 CHANGELOG);巡检要驱动导航,改变「只读对账」的性质 | 0.4.0 | 已排期(P1);依赖 PB-040-14、PB-040-15 | +| PB-040-13 | `ui verify-manifest` 接受 YAML manifest | v1 只认 JSON;大清单人手维护 YAML 更省事,但要引入解析依赖 | 0.4.0 | 已排期(P2) | +| PB-040-14 | `ui verify-manifest` 覆盖 Semantics identifier(`ui tap` 的目标面) | catalog `uiTargets` 只登记 `PatchbayKey` 注册的 text / capture 目标,可点控件的 identifier 不在其中;要取 `ui.semantics.tree`,那是另一个命名空间和另一套挂载语义 | 0.4.0 | 已排期(P1) | +| PB-040-15 | `ui targets --emit-manifest`:从活体 catalog 生成 expected-targets manifest 初稿 | 真机验收现在要照着 catalog 手抄 `ui verify-manifest` 清单 | 0.4.0 | 已排期(P0) | +| PB-040-16 | `wire_codegen --write` 顺手刷新协议面 surface golden | golden 重生成是与 codegen 分离的手工步骤(`PATCHBAY_UPDATE_GOLDENS=1 dart test`),哨兵只在聚合 / rebase 期才触发:0.3.0 四支各自绿、合成才红,一次性补进 12 个 wire 类型(7eb6236) | 0.4.0 | 已排期(P0) | +| PB-040-17 | `release_prep --apply` 覆盖 `patchbayPackageVersion` 与两份 README 的版本引用 | apply 代改四包 version 却不动这两处,只有 `release_version_parity_test` 事后兜住(0.3.0 定版实撞:apply 后测试红);该常量被 host 当 `serverVersion` 报给客户端,漂移即全网 App 谎报构建 | 0.4.0 | 已排期(P0) | +| PB-040-18 | `release_prep --apply` 时自动冻结本版协议面进兼容语料库 | `packages/patchbay_cli/test/golden/legacy_host_v0_2_0/` 一类的旧版语料是手工冻结的,版本过去后不可再生成 | 0.4.0 | 已排期(P0) | +| PB-040-19 | command_codegen check 的样例 contract 瘦身 | `packages/patchbay/contracts/example_commands.g.dart` 208 行生成物只为喂 drift 门禁而长期入仓,应改由真实命令声明推导 | 0.4.0 | 已排期(P2);依赖 PB-040-05 | +| PB-040-20 | CHANGELOG 碎片化:`changelog.d/` 每 MR 一文件 + `release_prep` 聚合 | 0.3.0 每对并行分支都在根 CHANGELOG 同一处相撞,是结构性冲突源 | 0.4.0 | 已排期(P0) | ## 文档债(快赢,可随任意批次走) @@ -44,14 +47,17 @@ ## design-gate(需仓主裁决后动工) -| 条目 | 裁决点 | -|---|---| -| macOS 桌面 lifecycle 闸判定 | 「失焦但在渲」是否放行:桌面端改帧活性判定、移动端维持 `resumed`(方案 A);第二 consumer 有复现环境可验证 | -| 锚定式手势 | 相对比例坐标手势与「不做坐标定位」立场的边界划法 | -| DevTools net 画像 | 请求画像的脱敏口径 | +| 编号 | 裁决点 | 目标版本 | 状态 | +|---|---|---|---| +| DG-040-04 | macOS 桌面 lifecycle 闸判定:「失焦但在渲」是否放行;桌面端改帧活性判定、移动端维持 `resumed`(方案 A),第二 consumer 有复现环境可验证 | 0.4.0 | 待裁决 | +| DG-040-01 | 锚定式手势:相对比例坐标手势与「不做坐标定位」立场的边界划法 | 0.4.0 | 待裁决 | +| DG-040-02 | 自动 keep-screen-on:默认自动还是手动,以及关闭出口与静默释放语义 | 0.4.0 | 待裁决 | +| DG-040-03 | DevTools net 画像:请求画像的脱敏口径 | 0.4.0 | 待裁决 | ## 维护规则 - 一条一行,动机一句话,证据给指针;不粘贴过程。 +- 状态只用:`待排期`、`待裁决`、`已排期`、`实现中`、`已验证`;版本计划负责定义优先级与退出条件。 - 完成 = 移入 CHANGELOG 对应版本段并删行;放弃 = 移入 design.md 非目标台账并写理由。 +- 延期 = 通过范围变更 MR 清除目标版本、标回 `待排期`,并保留未满足的证据指针。 - 每次发版前过一遍本表,与 CHANGELOG、兼容矩阵同批核对。 diff --git a/docs/releases/0.4.0.md b/docs/releases/0.4.0.md new file mode 100644 index 0000000..cd22210 --- /dev/null +++ b/docs/releases/0.4.0.md @@ -0,0 +1,155 @@ +# Patchbay 0.4.0 版本计划 + +> 状态:规划中 +> +> 范围真源:本文件定义 0.4.0 的目标与退出条件;[backlog](../backlog.md) 保存尚未完成的条目与证据。 +> +> 发布方式:功能分支逐项合入 `main`,候选版用 `patchbay-v0.4.0-rc.N` 固定,正式版用 +> `patchbay-v0.4.0` 定版。 + +## 版本目标 + +把 0.3.0 已有的“可观察、可调用”能力补成一条可靠的自动化闭环: + +1. CLI 能稳定启动、选择并监督一个会话; +2. 操作者能按稳定 identifier 定位目标,执行长按、拖拽和 fling; +3. 操作继续服从声明门、生命周期门和 generation 围栏,不退化成任意坐标点击; +4. 操作前后能用 manifest、snapshot、capture 与 DevTools 证据验证结果; +5. 新命令从同一份 descriptor 生成注册、校验、帮助和文档,降低继续扩展的冲突成本。 + +0.4.0 以“尽量清空当前 backlog”为目标。所有现有特性均进入目标范围,但不是每项都能无条件阻塞 +发布:安全边界未裁决、外部验证未完成或收益不足以覆盖风险的条目,必须通过范围变更 MR 明确退回 +backlog,不能静默消失或带着未验证实现发布。 + +## 范围分级 + +### P0:发布阻断 + +以下条目缺失时,0.4.0 的核心闭环不成立: + +| 编号 | 条目 | 关键验收 | +|---|---|---| +| PB-040-01 | 锚定式手势:press-hold、drag 路径、fling | identifier 锚定、相对比例坐标、generation 围栏;VM/direct 同语义;普通与嵌套滚动真机通过 | +| PB-040-04 | host 声明 `snapshotSelectors` capability | 新 host 不再靠错误形态推断;老 host 类型化降级保持兼容 | +| PB-040-05 | 统一 CommandRegistry | descriptor、decoder、gate、handler、validator 由同一 dispatcher 驱动,目录与执行不可漂移 | +| PB-040-06 | descriptor 生成 CLI 注册与帮助 | 删除对应手写注册分支;生成物漂移由 CI 拦截 | +| PB-040-07 | descriptor/help 生成命令参考文档 | 中英文 README 与包 README 不再人工维护命令表 | +| PB-040-11 | Launcher 监督与显式 pending session | 退避重连、machine-frame 生命周期、断连诊断;两个接入方确认 schema | +| PB-040-15 | `ui targets --emit-manifest` | 活体 catalog 可生成稳定、可直接校验的 manifest 初稿 | +| PB-040-16 | `wire_codegen --write` 刷新协议面 golden | 写入与检查使用同一协议面,聚合阶段不再补漏 | +| PB-040-17 | `release_prep` 覆盖版本引用 | 包版本、`patchbayPackageVersion`、README 引用一次更新并机检 | +| PB-040-18 | `release_prep` 冻结兼容语料 | RC/正式版本的协议 fixture 可重复生成并被兼容测试读取 | +| PB-040-20 | CHANGELOG 碎片化 | 每个行为 MR 独占碎片;定版时稳定聚合,避免根文件热点冲突 | + +### P1:本版目标 + +以下能力全部按 0.4.0 排期;完成 P0 后按依赖顺序推进: + +| 编号 | 条目 | 关键验收 | +|---|---|---| +| PB-040-02 | 定时 capture 与 golden diff | 支持第 N 帧和两帧差异率;明确只覆盖 Flutter 渲染层 | +| PB-040-03 | 会话活跃时自动 keep-screen-on | debug-only、静默释放、显式关闭出口;不会让息屏测试误判 | +| PB-040-08 | retryPolicy、审计 sink、CLI `describe` | 仅幂等 external 命令按 requestId 去重;审计只记录脱敏参数形状 | +| PB-040-09 | DevTools perf 与 net 画像 | perf 先交付;net 经脱敏裁决后才可启用 | +| PB-040-12 | `ui verify-manifest` 按 destination 巡检 | 明示其会改变 App 状态;导航失败和部分完成均有类型化证据 | +| PB-040-14 | manifest 校验 Semantics identifier | 与 catalog `uiTargets` 命名空间分离,歧义与未挂载 fail-closed | + +### P2:力争清空 + +这些条目价值较低或可独立延期,但仍进入 0.4.0 实现队列: + +| 编号 | 条目 | 关键验收 | +|---|---|---| +| PB-040-10 | snapshot revision/diff | revision 单调、diff 有明确基线和资源上限 | +| PB-040-13 | YAML manifest | 与 JSON 解析为同一内部模型,错误位置可诊断 | +| PB-040-19 | command_codegen 样例 contract 瘦身 | 门禁由真实声明推导,不再长期维护大段样例生成物 | + +P2 不应抢占 P0/P1 的修复和真机验证预算。若 RC 阶段仍未完成,可通过范围变更 MR 退回 backlog, +不因此延迟一个已经满足核心目标的版本。 + +## 设计闸门 + +M0 完成前不进入相关实现 MR。裁决写入 [design.md](../design.md),版本计划只记录结论链接。 + +| 编号 | 裁决 | 默认建议 | 影响条目 | +|---|---|---|---| +| DG-040-01 | 锚定手势与“不做坐标定位”的边界 | 允许 identifier 锚定后的控件内相对比例坐标;继续禁止任意屏幕绝对坐标 | PB-040-01 | +| DG-040-02 | 自动 keep-screen-on 默认行为 | 默认仍关闭;仅由显式 launcher/session 策略开启,租约到期或会话静默后释放 | PB-040-03 | +| DG-040-03 | DevTools net 脱敏口径 | 默认不采集 body、认证头和完整 query;只暴露封闭字段与大小/耗时画像 | PB-040-09 | +| DG-040-04 | macOS 失焦但仍渲染时的 lifecycle 门 | 桌面端以帧活性补充判断,移动端继续要求 `resumed`;必须由接入方复现验证 | 横切 UI 能力 | + +## 依赖与实施批次 + +批次表示合入顺序,不是新的版本号;一批可以拆成多个独立 MR。 + +### M0:规划和裁决 + +- 冻结本计划;完成 DG-040-01 至 DG-040-04;为每项指定验收负责人和接入方验证窗口。 +- 建立 `changelog.d/` 与范围变更模板,之后的行为 MR 不直接争写根 CHANGELOG 的 Unreleased 段。 + +### M1:注册、生成与发布底座 + +- PB-040-05 → PB-040-06 → PB-040-07;先建立统一 registry,再生成 CLI/help/docs。 +- 并行完成 PB-040-04、PB-040-16 至 PB-040-20。 +- 退出条件:新增命令无需再同时修改 host 分发、CLI switch 和多份手写命令表。 + +### M2:会话可靠性与安全执行 + +- PB-040-11 先吸收首个接入方已验证的监督循环,再由第二接入方确认 pending schema。 +- 在统一 registry 上实现 PB-040-08;完成 DG-040-02 后实现 PB-040-03。 +- 退出条件:断连、重连、重复请求、审计和会话释放都有稳定机读结果。 + +### M3:UI 操作闭环 + +- PB-040-15 先提供 manifest 初稿;PB-040-14 补齐 Semantics identifier。 +- DG-040-01 通过后实现 PB-040-01;覆盖 press-hold、分段 drag 与 fling。 +- PB-040-12 在 manifest/identifier 稳定后驱动逐屏巡检;PB-040-13 最后补输入格式。 +- 退出条件:至少两个接入方完成一条“启动 → 定位 → 滑动 → 验证”的真机路径。 + +### M4:观测与差异证据 + +- PB-040-02、PB-040-10 和 PB-040-09;perf 可先于 net 合入,net 必须等待 DG-040-03。 +- 退出条件:输出明确事实来源、资源上限和隐私边界,不把 Flutter 层证据表述成 OS 合成层事实。 + +### M5:RC 与正式发布 + +- 从 `main` 打 `patchbay-v0.4.0-rc.1`,由两个接入方按固定 SHA 验证;修复后递增 RC,不移动旧 tag。 +- 运行 `release_prep --apply` 和完整 CI/真机门禁;范围变化先改本文件,再定版。 +- GitHub 合并、回推内网主仓并核对 SHA 后,打 annotated tag `patchbay-v0.4.0`。 + +## MR 契约 + +每个实现 MR 必须: + +1. 在中文描述中写明 `Plan: PB-040-XX`、用户结果、协议/安全影响和验收命令; +2. 一个 MR 只承担一个可独立回退的计划条目,跨条目时解释不可拆原因; +3. 新行为带能验证“先红后绿”的测试,并覆盖 VM/direct 或明确说明为何只适用一条传输; +4. 公共 API、协议、默认上限或安全边界变化同步更新专题文档和 CHANGELOG 碎片; +5. design-gate 条目在裁决 MR 合入前不得进入实现 MR。 + +推荐分支名使用 `feature/040-`;自动化代理创建的分支继续使用其约定前缀。 + +## 范围变更规则 + +- **新增**:必须说明为何属于版本目标、依赖哪一项,以及替换或消耗哪部分验证预算。 +- **延期**:必须提交范围变更 MR,记录未满足的证据、风险和回到 backlog 后的状态。 +- **禁止静默降级**:不得为了按期发布而删除测试、放宽 fail-closed、隐藏 capability 或绕过设计闸门。 +- **缺陷优先**:0.4 开发期间发现的回归先修复,再继续新增能力;涉及已发布版本时独立评估补丁版。 + +## 发布退出条件 + +- P0 全部完成;P1 未完成项均有已合入的范围变更记录;P2 完成或明确退回 backlog。 +- 四包 analyze/test、Flutter/example 测试、格式和两个 codegen drift 门禁全绿。 +- 兼容语料覆盖 0.3.0 host ↔ 0.4.0 CLI、0.4.0 host ↔ 0.3.0 CLI 的支持边界。 +- Android 与 iOS 至少各完成一次真机会话;锚定手势在至少两个接入方完成端到端验证。 +- direct 与 VM Service 对共享能力返回一致的 admission、稳定 code、requestId 和预算语义。 +- README、guide、命令参考、兼容矩阵、根/包 CHANGELOG 与发布版本一致。 +- `release_prep --check`、pub dry-run、双远端 tag SHA 核对全部通过。 + +## 完成后的归档 + +正式 tag 发布后: + +- 将完成条目从 backlog 移入 0.4.0 CHANGELOG; +- 将延期条目标回“待排期”,清除 0.4.0 目标版本并保留范围变更链接; +- 本文件状态改为“已发布”,补正式 tag 与 peeled commit SHA,之后不再改写范围历史。 From 5249881b6d24b3009cdaf6252163bed4b50e607d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E9=94=90?= Date: Mon, 17 Aug 2026 12:40:48 +0800 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=E8=90=BD=E5=9C=B0=20CHANGELOG=20?= =?UTF-8?q?=E7=A2=8E=E7=89=87=E6=B5=81=E7=A8=8B=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/pull_request_template.md | 28 +++++++ CONTRIBUTING.md | 15 +++- changelog.d/README.md | 122 +++++++++++++++++++++++++++++++ docs/backlog.md | 2 +- docs/release-checklist.md | 15 ++++ docs/releases/0.4.0.md | 2 +- 6 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 .github/pull_request_template.md create mode 100644 changelog.d/README.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..e31fa20 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,28 @@ +## 变更结果 + + + +## 计划与边界 + +- Plan: +- Design gate: +- 协议、安全或兼容影响: + +## 验证 + +- [ ] 新行为测试验证过先红后绿,或本 MR 不改变行为 +- [ ] 已运行与改动范围相称的 analyze/test/codegen 检查 +- [ ] 涉及 VM/direct 共享能力时,两条传输语义一致 +- [ ] 需要接入方或真机验证时,已附证据或明确后续责任 + +## CHANGELOG + +- [ ] 已按 [`changelog.d/README.md`](https://github.com/cr1992/patchbay/blob/main/changelog.d/README.md) 添加碎片 +- [ ] 本 MR 无需碎片,理由: + + + +## 文档与发布面 + +- [ ] 公共 API、协议、默认上限或安全行为变化已同步文档 +- [ ] 未直接修改包内派生的 `CHANGELOG.md`,或本 MR 是正式发布聚合 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 791c578..f3e6186 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,11 +15,22 @@ header 记录的是相对生成物自身的路径);完整两条命令见 [发版清单](docs/release-checklist.md); 4. 新增行为必须带测试,且测试要验证过「能红」(打个定向 mutation 确认断言真的红)。 -5. 公共 API、协议字段、默认资源上限或安全行为有变化时,同步更新 README / 对应专题文档和 - [CHANGELOG.md](CHANGELOG.md);文档、测试与实现必须描述同一契约。 +5. 公共 API、协议字段、默认资源上限或安全行为有变化时,同步更新 README / 对应专题文档,并按 + [CHANGELOG 碎片规范](changelog.d/README.md)新增碎片;日常 PR 不直接修改根或包内 CHANGELOG, + 文档、测试与实现必须描述同一契约。 6. 本仓公开:文档与注释不记录内网域名、内部项目与业务线名。需要指代时写「内网主仓」 「接入方」;内网地址走 CI 变量或 remote 名,不写字面值。 +## CHANGELOG 碎片 + +会影响使用者的 PR 必须在 `changelog.d/` 新增一个独占碎片,文件名绑定版本计划/backlog 编号和 +`added|changed|deprecated|removed|fixed|security` 类型。纯测试、注释、排版或无外部行为变化的 +内部重构可以不写,但要在 PR 模板说明理由。 + +碎片在功能 PR 合入后继续保留,正式发布时才聚合进根 [CHANGELOG.md](CHANGELOG.md) 并删除;四个包的 +CHANGELOG 仍由根表统一派生,不是独立真源。完整命名、内容、评审和发布规则见 +[changelog.d/README.md](changelog.d/README.md)。 + ## 设计红线 改协议或 UI 桥之前先读 [docs/design.md](docs/design.md)——六条设计立场(受理≠执行、 diff --git a/changelog.d/README.md b/changelog.d/README.md new file mode 100644 index 0000000..92edeb4 --- /dev/null +++ b/changelog.d/README.md @@ -0,0 +1,122 @@ +# CHANGELOG 碎片规范 + +本目录保存尚未发布、会影响使用者的变更说明。日常行为 MR 各写自己的碎片;定版时统一聚合进仓根 +`CHANGELOG.md`,再由 `release_prep` 从根表派生四个包的 `CHANGELOG.md`。 + +仓根 `CHANGELOG.md` 是已发布历史的唯一真源;本目录只保存待发布输入。四个包当前共享同一份发布 +正文,因此碎片不声明 package scope。 + +## 何时必须写 + +以下变化必须随 MR 添加碎片: + +- 新功能、用户可见行为变化或缺陷修复; +- 公共 API、协议字段、稳定错误码、默认值或资源上限变化; +- 安全边界、兼容范围、安装方式或发布行为变化; +- 已弃用或移除的能力。 + +以下变化通常不写: + +- 只改测试、注释、排版或内部重构,且外部行为不变; +- 版本规划、设计讨论和未落地提案; +- 发布聚合 MR 本身——它消费已有碎片,不为聚合动作再造一条碎片。 + +无法判断时按“使用者升级后是否需要知道”裁决。选择“不需要碎片”的 MR 必须在 PR 模板中写明理由。 + +## 文件名 + +格式: + +```text +[.]..md +``` + +`change-id` 使用两种封闭格式: + +- 已排期工作:版本计划或 backlog 编号,例如 `PB-040-01`; +- 未排期缺陷:先在 backlog 缺陷表登记,再分配 `BUG-YYYYMMDD-NN`,例如 `BUG-20260817-01`。 + +同一条目拆成多个独立行为时,用可选的 `part` 区分;`part` 只能使用小写 ASCII 字母、数字和连字符。 + +```text +PB-040-01.added.md +PB-040-01.cli.added.md +PB-040-05.registry.changed.md +BUG-20260817-01.fixed.md +``` + +完整文件名必须匹配: + +```regex +^(PB-[0-9]{3}-[0-9]{2}|BUG-[0-9]{8}-[0-9]{2})(\.[a-z0-9][a-z0-9-]*)?\.(added|changed|deprecated|removed|fixed|security)\.md$ +``` + +禁止使用 MR 编号作为唯一 ID:创建碎片时 MR 可能尚不存在,同一个计划项也可能跨多个 MR。 + +## 类型 + +类型与根 CHANGELOG 的栏目一一对应: + +| 后缀 | 聚合栏目 | 使用场景 | +|---|---|---| +| `added` | `Added` | 新增能力 | +| `changed` | `Changed` | 既有行为、API、默认值或兼容范围变化 | +| `deprecated` | `Deprecated` | 仍可使用、但计划移除的能力 | +| `removed` | `Removed` | 已移除能力 | +| `fixed` | `Fixed` | 缺陷修复 | +| `security` | `Security` | 安全修复或安全边界收紧 | + +一个文件只属于一个类型。一个 MR 同时包含新增和兼容变化时,写两个碎片,不把两类行为塞进同一条。 + +## 内容 + +每个碎片使用 UTF-8,正文只包含一条顶层 Markdown 列表项: + +```markdown +- 新增 identifier 锚定的 drag 与 fling,并在目标代际变化时拒绝执行。 +``` + +要求: + +- 默认使用中文,公共类型、命令、字段和稳定 code 使用反引号保留原名; +- 从使用者结果写起,说明“新增/改变/修复了什么”,不记录实现过程、提交 SHA 或评审过程; +- 不写标题、版本号、日期、front matter 或空占位; +- 需要补充迁移方法时,可在同一列表项下使用缩进续段; +- 仓内链接以根 `CHANGELOG.md` 为基准,包内绝对链接继续由 `release_prep` 改写; +- 破坏性变化必须以 `**Breaking:**` 开头,并给出迁移路径; +- `security` 不记录可直接复现利用的敏感细节。 + +例如: + +```markdown +- **Breaking:** `PatchbaySessionRecord` 改用显式 `pending` 状态;构造记录时不再用空 URI 表示启动中。 + 旧接入方应先升级读取逻辑,再写入新字段。 +``` + +## MR 流程 + +1. 从版本计划或 backlog 取得 `change-id`;未排期缺陷先登记,design-gate 先裁决。 +2. 实现 MR 同时新增碎片,日常 MR 不直接编辑根或四个包的 `CHANGELOG.md`。 +3. 作者在 PR 模板填写计划编号、验证证据和碎片文件;无需碎片时填写理由。 +4. 评审者核对文件名、类型、用户视角、Breaking 标记,以及文档/测试是否描述同一契约。 +5. MR 合入后碎片继续留在本目录,直到对应版本定版;不得在功能合入后提前删除。 + +一个碎片只由创建它的 MR 修改。后续修正另开碎片,避免多个分支重新争写同一个文件。 + +## 发布聚合 + +定版时按以下顺序处理: + +1. 校验全部文件名、change-id、类型、非空正文和单一顶层列表项; +2. 按 `Added → Changed → Deprecated → Removed → Fixed → Security` 建立栏目; +3. 同一栏目内按文件名升序聚合,保证重复执行得到相同结果; +4. 将内容写入仓根 `CHANGELOG.md` 的 `## Unreleased` 段; +5. 删除本次已聚合的碎片,保留本 `README.md`; +6. 运行 `release_prep --apply`,把 Unreleased 落款成正式版本并派生四个包的 CHANGELOG; +7. 聚合、删除碎片、版本落款和包内派生必须进入同一个发布提交。 + +PB-040-20 的自动聚合尚未实现之前,由 maintainer 在发布 MR 中按上述规则手工完成;实现后, +`release_prep --check` 必须负责校验,`--apply` 必须负责稳定聚合和删除碎片。自动化实现 MR 应同步移除 +这段过渡说明。 + +已经推送的 release tag 不回写。遗漏的变更用下一个补丁版本的新碎片补记,不移动 tag,也不修改旧版本段。 diff --git a/docs/backlog.md b/docs/backlog.md index 15b97ec..b00e8e5 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -37,7 +37,7 @@ | PB-040-17 | `release_prep --apply` 覆盖 `patchbayPackageVersion` 与两份 README 的版本引用 | apply 代改四包 version 却不动这两处,只有 `release_version_parity_test` 事后兜住(0.3.0 定版实撞:apply 后测试红);该常量被 host 当 `serverVersion` 报给客户端,漂移即全网 App 谎报构建 | 0.4.0 | 已排期(P0) | | PB-040-18 | `release_prep --apply` 时自动冻结本版协议面进兼容语料库 | `packages/patchbay_cli/test/golden/legacy_host_v0_2_0/` 一类的旧版语料是手工冻结的,版本过去后不可再生成 | 0.4.0 | 已排期(P0) | | PB-040-19 | command_codegen check 的样例 contract 瘦身 | `packages/patchbay/contracts/example_commands.g.dart` 208 行生成物只为喂 drift 门禁而长期入仓,应改由真实命令声明推导 | 0.4.0 | 已排期(P2);依赖 PB-040-05 | -| PB-040-20 | CHANGELOG 碎片化:`changelog.d/` 每 MR 一文件 + `release_prep` 聚合 | 0.3.0 每对并行分支都在根 CHANGELOG 同一处相撞,是结构性冲突源 | 0.4.0 | 已排期(P0) | +| PB-040-20 | CHANGELOG 碎片化:`changelog.d/` 每 MR 一文件 + `release_prep` 聚合 | 0.3.0 每对并行分支都在根 CHANGELOG 同一处相撞,是结构性冲突源 | 0.4.0 | 实现中(P0):规范与 PR 流程已落地,自动聚合待实现 | ## 文档债(快赢,可随任意批次走) diff --git a/docs/release-checklist.md b/docs/release-checklist.md index e2f7e75..fc7fef7 100644 --- a/docs/release-checklist.md +++ b/docs/release-checklist.md @@ -6,6 +6,21 @@ 清单分两半:**脚本项**由 `release_prep` 一次跑完并给红绿,不必人肉逐条比对;**人工项**是脚本 永远不代做的四类动作——打 tag、推送、发布、以及需要向仓外核实的口径。 +## 0. 聚合 CHANGELOG 碎片 + +日常行为 MR 只新增 [`changelog.d/`](../changelog.d/README.md) 碎片,不直接争写根 CHANGELOG。 +定版先按碎片规范校验并聚合为根表的 `## Unreleased` 段,同时删除已消费碎片,再进入下面的 +`release_prep` 流程。 + +PB-040-20 自动化落地前,这一步由 maintainer 在发布 MR 中手工完成;聚合顺序固定为 +`Added → Changed → Deprecated → Removed → Fixed → Security`,同一栏目按文件名升序。自动化落地后, +此处改为核对 `release_prep --check/--apply` 的结果,不再保留另一套手工逻辑。 + +- [ ] 所有非 README 碎片文件名、change-id、类型和正文符合规范 +- [ ] 根 CHANGELOG 的 Unreleased 内容与待发布碎片一一对应 +- [ ] 已聚合碎片在同一发布提交中删除,`changelog.d/README.md` 保留 +- [ ] 没有直接编辑四个包的派生 CHANGELOG + ## 1. 脚本项:跑一遍机检 ```console diff --git a/docs/releases/0.4.0.md b/docs/releases/0.4.0.md index cd22210..1247b65 100644 --- a/docs/releases/0.4.0.md +++ b/docs/releases/0.4.0.md @@ -85,7 +85,7 @@ M0 完成前不进入相关实现 MR。裁决写入 [design.md](../design.md), ### M0:规划和裁决 - 冻结本计划;完成 DG-040-01 至 DG-040-04;为每项指定验收负责人和接入方验证窗口。 -- 建立 `changelog.d/` 与范围变更模板,之后的行为 MR 不直接争写根 CHANGELOG 的 Unreleased 段。 +- `changelog.d/` 规范与 PR 模板已经落地;PB-040-20 继续实现校验、稳定聚合和碎片删除自动化。 ### M1:注册、生成与发布底座