feat(ack): add Feishu bug review approval gate
This commit is contained in:
@@ -1,24 +1,37 @@
|
||||
# 飞书 Base Bug 收件箱
|
||||
# 飞书 Base Bug 整理与审核
|
||||
|
||||
这是可选的只读接入。项目在 `docs/ack/tasks.yaml` 的 `project.bugIntake` 声明
|
||||
`provider: feishu-base`、显式 `profile`、`baseToken`、`tableId`、ACK Ready 的 `viewId`
|
||||
和八个字段映射;不要保存 App Secret、access token 或任何 profile 凭据。
|
||||
飞书 Base 是 Bug 在**审核通过前的唯一协作区**。用户先在飞书记录 Bug 描述,
|
||||
Coordinator 读取记录和项目现状,补全或修改修复逻辑、验收标准,再写回同一条飞书
|
||||
记录。用户可以继续在飞书反馈,Coordinator 按反馈反复修订。只有用户明确表示审核
|
||||
通过后,Coordinator 才把最终版本写入 `docs/ack/tasks.yaml`,随后启动 ACK 三角色闭环。
|
||||
|
||||
审核前不创建或刷新 `tasks.yaml` 中的 ACK 任务,不得启动 worker,不得派发
|
||||
Developer/Test,也不得修改应用代码。飞书字段已填满、记录进入某个 view、用户暂时没有
|
||||
回复,都不等于审核通过。
|
||||
|
||||
## 项目配置
|
||||
|
||||
项目在 `docs/ack/tasks.yaml` 的 `project.bugIntake` 声明 `provider: feishu-base`、
|
||||
`workflow: reviewed-writeback-v1`、显式 `profile`、`baseToken`、`tableId`、用于候选 Bug
|
||||
的 `viewId` 和字段映射;不要保存 App Secret、access token 或任何 profile 凭据。
|
||||
|
||||
原有八字段配置在未声明 `workflow` 时按 `read-only-v1` 兼容读取,不得写回或进入本节
|
||||
流程。启用审核前协作必须显式选择 `reviewed-writeback-v1`,并在 `title`、`actual`、
|
||||
`expected`、`stepsToReproduce`、`acceptance`、`priority`、`attachments`、`updatedAt`
|
||||
之外配置可写文本字段 `fixLogic`。其中 `fixLogic` 和 `acceptance` 由 Coordinator 维护;
|
||||
用户提供的标题、实际表现、预期结果和附件属于来源事实,Coordinator 不得覆盖。
|
||||
|
||||
## 一次性安装与 profile 设置
|
||||
|
||||
在账号级可信工具目录安装官方 CLI;ACK 读取器只会搜索账号的 `~/.local/bin`、mise/cargo
|
||||
shim 目录和固定系统目录,绝不会采用项目 `PATH` 中的同名文件。它同时识别官方 npm
|
||||
包生成的 `lark-cli -> @larksuite/cli/scripts/run.js` wrapper,并校验 package 名与 bin
|
||||
映射,然后直接执行该官方包下载的 native binary;这样不依赖 nvm PATH,也不会让 Node
|
||||
运行时变量进入凭据边界。缺少 native binary 或同名仿冒 wrapper 都会被拒绝:
|
||||
映射,然后直接执行该官方包下载的 native binary:
|
||||
|
||||
```bash
|
||||
npm install --global --prefix "$HOME/.local" @larksuite/cli@latest
|
||||
```
|
||||
|
||||
固定 `--prefix "$HOME/.local"` 是接入契约的一部分,确保 npm wrapper 落在读取器会检查的
|
||||
账号级可信目录;不要依赖 nvm 或其它由当前 shell 动态注入的 PATH 位置。
|
||||
|
||||
随后在受控终端中用 stdin 提供 App Secret,选择 Feishu brand,避免 secret 进入 shell
|
||||
history、进程参数或项目文件:
|
||||
|
||||
@@ -28,14 +41,13 @@ printf '%s' "$FEISHU_APP_SECRET" | lark-cli profile add \
|
||||
--app-secret-stdin --brand feishu
|
||||
```
|
||||
|
||||
随后在 project 配置里只填写 `profile: project-feishu`。不要执行 `profile use`,也不要
|
||||
依赖 active profile;每次读取和附件下载都由 adapter 显式传 `--profile project-feishu`。
|
||||
为读取记录和下载附件,profile 必须具有 `base:record:read` 和
|
||||
`docs:document.media:download`。请在飞书开发者后台的应用权限中为该 app 授予这两个
|
||||
scope;不要把 `lark-cli auth check` 当作 app/bot scope 的证明,因为它检查的是当前用户的
|
||||
项目配置只填写 `profile: project-feishu`。不要执行 `profile use`,也不要依赖 active
|
||||
profile;读取、附件下载和写回都必须显式传 `--profile project-feishu`。profile 至少需要
|
||||
`base:record:read`、`base:record:write` 和 `docs:document.media:download`。
|
||||
不要把 `lark-cli auth check` 当作 app/bot scope 的证明,因为它检查的是当前用户的
|
||||
stored user token。
|
||||
|
||||
## 使用
|
||||
## 读取与整理计划
|
||||
|
||||
```bash
|
||||
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py check docs/ack/tasks.yaml
|
||||
@@ -46,48 +58,84 @@ python3 <ack-skill-dir>/scripts/feishu_bug_intake.py plan docs/ack/tasks.yaml \
|
||||
--output-dir "$tmpdir"
|
||||
```
|
||||
|
||||
`fetch` 只调用官方 `base +record-list`(限定配置的 view 和字段)和按配置附件字段的
|
||||
`base +record-download-attachment`。它输出单一 JSON,验证行矩阵、分页和下载路径;CLI、
|
||||
profile、JSON、分页、附件或路径任一异常都会失败且不输出伪成功结果。
|
||||
`fetch` 只调用官方 `base +record-list` 和附件下载命令,输出标准化 JSON,并为每条记录
|
||||
计算覆盖来源事实、附件元数据和审核字段的 `draftRevision`。`plan` 只生成
|
||||
`create` / `refresh` / `unchanged` / `drift` 候选动作,不修改飞书或任务板。**审核通过前
|
||||
不得执行这些候选动作**;它们只用于查重和预览最终导入结果。
|
||||
|
||||
`plan` 在同一批标准化记录上读取现有 `tasks`,只输出整理计划而不修改文件:新来源为
|
||||
`create`,同来源且现有任务为 `open`、来源时间有变化时为 `refresh`,未变化为
|
||||
`unchanged`,其它 ACK 状态发生来源变化时为 `drift`。任务板或读取结果出现重复
|
||||
`sourceRef` 会直接失败。标题、实际表现、预期结果和更新时间属于来源事实,任一缺失时
|
||||
读取失败;复现步骤、验收标准和优先级属于 Coordinator 可整理字段,缺失时记录与 action
|
||||
会返回 `enrichmentRequired`,不阻断整批。没有附件且所有 Bug 内容字段都为空的误建行会
|
||||
跳过,并在批次 `warnings` 中返回 `blank_record_skipped`。
|
||||
标题、实际表现、预期结果和更新时间属于来源事实,任一缺失时读取失败。复现步骤、
|
||||
修复逻辑、验收标准和优先级属于 Coordinator 可整理字段;缺失时记录与 action 返回
|
||||
`enrichmentRequired`。没有附件且所有 Bug 内容字段都为空的误建行会跳过,并在批次
|
||||
`warnings` 中返回 `blank_record_skipped`。
|
||||
|
||||
子进程只收到实际账号 HOME、可信 PATH 和基础 locale;调用者环境中的
|
||||
`LARKSUITE_CLI_*`、`FEISHU_*`、`NODE_OPTIONS` 等变量不会传入,避免环境凭据或运行时
|
||||
注入绕过项目 profile。每条记录最多 10 个附件、单批最多 100 个,单个附件最多
|
||||
20 MiB、合计最多 200 MiB,整批附件下载最多 5 分钟,并校验声明大小与落盘大小;
|
||||
请始终使用新的临时目录作为 `--output-dir`。
|
||||
`LARKSUITE_CLI_*`、`FEISHU_*`、`NODE_OPTIONS` 等变量不会传入。每条记录最多 10 个
|
||||
附件、单批最多 100 个,单个附件最多 20 MiB、合计最多 200 MiB,整批下载最多 5 分钟;
|
||||
始终使用新的临时目录作为 `--output-dir`。
|
||||
|
||||
`profile list` 只作存在性检查,不会输出 profile 内容。官方 record-list JSON 使用
|
||||
`data.fields`、`data.record_id_list` 与同长度的 `data.data` 行矩阵;`ok: true` 或
|
||||
`code: 0` 是唯一可接受的成功 envelope。
|
||||
## 审核前协作循环
|
||||
|
||||
## Coordinator 整理
|
||||
对每条候选 Bug,Coordinator 按以下顺序工作:
|
||||
|
||||
读取结果的每条 `sourceRef` 是稳定且不透明的键,例如
|
||||
`feishu-base:sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef`。
|
||||
导入时写入 task 的
|
||||
`source.kind: feishu-base`、`source.ref`、`source.recordId` 与 `source.updatedAt`;先按
|
||||
`source.ref` 查重。相同来源只更新 `open` 任务;`dispatched`、`fixed_by_dev`、
|
||||
`retesting`、`failed_retest`、`verified`、`blocked` 和 `leftover` 任务只告警来源漂移,
|
||||
由用户决定是否新建任务;飞书记录消失、不可访问或同步失败时,已有 ACK 任务一律保留。
|
||||
1. 读取用户填写的来源事实、附件和项目代码/测试,确认问题边界;证据不足时把不确定点
|
||||
明确写成假设,不伪装成用户原文。
|
||||
2. 整理复现步骤和优先级,并生成:
|
||||
- `fixLogic`:说明根因判断、计划修改的位置与行为、需要保持的不变量,以及回归风险;
|
||||
它是待审核的实现方向,不宣称代码已经修改。
|
||||
- `acceptance`:写成可观测、可独立复测的标准,至少覆盖用户可见结果、真实状态或 API
|
||||
结果,以及原失败不再出现;不扩张用户没有表达的产品范围。
|
||||
3. 把本轮草案保存为不超过 64 KiB 的临时 JSON:只包含非空字符串 `fixLogic` 和非空
|
||||
字符串数组 `acceptance`。通过安全适配器写回当前飞书记录:
|
||||
|
||||
当 action 带 `enrichmentRequired` 时,由 Coordinator 补齐后再写入任务板,不要求报告者
|
||||
返回飞书机械补字段:
|
||||
```bash
|
||||
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py write-draft \
|
||||
docs/ack/tasks.yaml --record-id <record-id> \
|
||||
--expected-source-ref <sourceRef> \
|
||||
--expected-draft-revision <draftRevision> --input <draft.json>
|
||||
```
|
||||
|
||||
- `steps`:根据标题、实际表现、附件和项目现状整理 2 至 5 个可复现步骤;证据不足时明确
|
||||
写成待 Developer 首轮确认的复现假设,不能把假设伪装成来源原文。
|
||||
- `acceptance`:把预期结果改写成可观测信号,至少覆盖用户可见结果、真实状态或 API 结果,
|
||||
以及原失败不再出现;不扩张飞书记录没有表达的产品范围。
|
||||
- `priority`:主流程阻断、数据损坏/丢失或安全风险定为 P0;普通功能错误默认 P1;纯样式或
|
||||
低频体验问题可定为 P2。无法判断时使用 P1,并保留判断依据。
|
||||
`write-draft` 会在写前确认 record 属于配置 view,且 `sourceRef`、`draftRevision` 与调用者
|
||||
看到的版本一致;它只允许覆盖配置映射的 `fixLogic` 和 `acceptance`,拒绝 symlink、超限
|
||||
或多余字段输入,并复用读取器的可信 CLI、显式 profile、最小环境和成功 envelope 校验。
|
||||
不得绕过适配器直接调用 PATH 中的 CLI,也不得改标题、实际表现、预期结果、附件或其它
|
||||
用户字段。
|
||||
4. `write-draft` 会回读同一记录、确认落盘值一致并返回当前 `draftRevision`。把这个 revision
|
||||
连同记录交给用户审核;不能只展示没有 revision 的自由文本。
|
||||
5. 用户提出意见时,重新读取最新记录和反馈,修订后再次写回、回读、等待审核;不要在
|
||||
本地或聊天中维护一份与飞书分叉的“最终草案”。
|
||||
|
||||
在任务 `evidence.intakeEnrichment` 中记录哪些字段由 Coordinator 推断及依据。Developer
|
||||
必须先复现或用失败测试确认推断步骤;Test 仍按任务中的可观测验收信号独立复测。标题、
|
||||
实际表现和预期结果不得由 Coordinator 补造,部分缺失时继续 fail closed。
|
||||
任一写回、回读或字段校验失败时停止本轮并报告,不能转入任务板或三角色处理。
|
||||
|
||||
## 审核门禁与导入
|
||||
|
||||
只有用户针对当前飞书记录的明确 `draftRevision` 表示“审核通过”“可以执行”或等价授权,
|
||||
才解除门禁。授权必须发生在最后一次草案写回和回读之后;之后若用户字段、附件、
|
||||
`fixLogic` 或 `acceptance` 再次变化,revision 会变化,原授权失效,必须重新审核。
|
||||
|
||||
审核通过后,Coordinator 才执行以下动作:
|
||||
|
||||
1. 通过适配器重新读取并生成规范任务草案;命令会要求当前 `sourceRef` 和
|
||||
`draftRevision` 精确等于用户批准值:
|
||||
|
||||
```bash
|
||||
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py import-approved \
|
||||
docs/ack/tasks.yaml --record-id <record-id> \
|
||||
--expected-source-ref <approved-sourceRef> \
|
||||
--expected-draft-revision <approved-draftRevision>
|
||||
```
|
||||
|
||||
不一致时停止并重新审核。输出的 `taskDraft` 包含批准后的规范字段以及
|
||||
`source.workflow`、`source.approvedRevision`、`source.approvedPayloadHash`。
|
||||
2. 按 `source.ref` 查重,把 `taskDraft` 原样合并到新的 ACK task,只补任务 ID、状态、
|
||||
dispatch 等 ACK 运行字段;不得手工改写 `fixLogic`、`acceptanceCriteria` 或其它审核字段。
|
||||
可在 `evidence.intakeEnrichment` 标明 Coordinator 推断依据,但它不替代规范字段。
|
||||
3. 运行 `validate_tasks.py`。校验器会重算 `approvedPayloadHash`;只有写入和校验都成功,
|
||||
任务才可作为已确认的 `open` 任务
|
||||
进入 ACK 闭环。
|
||||
4. 按 Coordinator → Developer → Test 的标准流程派发、实现和独立复测。
|
||||
|
||||
相同来源只更新尚未派发的 `open` 任务;`dispatched`、`fixed_by_dev`、`retesting`、
|
||||
`failed_retest`、`verified`、`blocked` 和 `leftover` 任务只告警来源漂移,由用户决定是否
|
||||
新建任务。项目启用 reviewed workflow 后,历史 `verified` / `leftover` 只读来源继续保留;
|
||||
其它仍可执行的 legacy 飞书任务必须先按当前流程重新整理和审核,不能通过省略或降级
|
||||
`source.workflow` 绕过门禁。飞书记录消失、不可访问或同步失败时,已有 ACK 任务一律保留。
|
||||
|
||||
Reference in New Issue
Block a user