# ACK 飞书多维表格 Bug 收件箱 ## 目标 让用户在飞书多维表格中跨设备记录文字和截图,随后由 ACK Coordinator 通过官方 `lark-cli` 读取项目配置的 `ACK Ready` 视图,整理为独立、可验收、可幂等追踪的 ACK 任务。不同项目通过不同 CLI profile 访问各自飞书租户。 ## 非目标 - 不用 Skill 承担人工记录入口。 - 不抓取公开网页或依赖浏览器登录态。 - 不把 App Secret、access token 或飞书用户凭据写入项目。 - 第一版不反向更新飞书记录,不把飞书状态与 ACK 状态做双向同步。 - 不把多条互不相关的 Bug 合成一次 Developer 派发。 ## 项目配置契约 可选配置位于 `docs/ack/tasks.yaml` 的 `project.bugIntake`。未配置时 ACK 保持现有行为。 配置存在时必须包含: | 字段 | 约束 | |------|------| | `provider` | 固定为 `feishu-base` | | `profile` | `lark-cli` profile 名称;每次命令显式传入 | | `baseToken` | 飞书 Base token | | `tableId` | 数据表 ID | | `viewId` | 只包含可导入记录的 `ACK Ready` 视图 ID | | `fields` | 逻辑字段到飞书字段 ID/名称的映射 | `fields` 必须映射 `title`、`actual`、`expected`、`stepsToReproduce`、 `acceptance`、`priority`、`attachments`、`updatedAt`。字段值只作为单个 argv 传给 `lark-cli`,不经过 shell。 ## CLI 契约 - 可执行文件固定为可信路径中的 `lark-cli`。 - 允许官方 npm 包生成且 package/bin 映射校验通过的 `run.js` wrapper,并解析到包内 native binary 执行;拒绝缺少 native binary 或其它同名软链接目标。 - profile 由项目显式选择;不得执行 `profile use` 或读取 active profile作为回退。 - 子进程使用最小环境,不继承可能覆盖 profile/config/凭据或注入运行时的环境变量。 - 记录读取使用 `base +record-list`、JSON 输出、指定 Base/table/view 和投影字段。 - 记录超过一页时按 offset/limit 继续读取,并设置总页数/记录数上限。 - 附件仅通过 `base +record-download-attachment` 下载到调用者显式提供的临时目录。 - 附件数量、单文件大小、批次总大小和子进程文件写入均有硬上限;落盘大小必须与 元数据一致。 - 标准输出必须是单一 JSON;CLI stderr 只作为错误摘要,不把可能的凭据写入结果。 ## 标准化结果 读取器输出批次元数据和 `records`。每条记录至少包含: - `sourceRef`:对 provider、profile、Base、table、record ID 做域隔离 SHA-256 后得到的稳定匿名引用;原始 profile、Base token 与 record ID 不拼入引用文本; - `recordId` 与 `updatedAt`; - title、actual、expected、steps、acceptance、priority; - `enrichmentRequired`:缺失但允许 Coordinator 整理的 steps、acceptance、priority; - 附件的 name/type/size 与可选本地临时路径;附件 token 只在下载命令内部使用; - 原始字段中无法映射但不影响导入的警告。 输出不得包含 App ID、App Secret、Base token、附件 file token、tenant/user access token 或 CLI 配置文件内容。 ## Coordinator 整理规则 1. 先运行读取器 `check`,确认 `lark-cli`、项目 profile 和所需只读能力可用。 2. 运行读取器 `plan` 读取 `ACK Ready` 视图并生成 create/refresh/unchanged/drift 整理动作;需要看截图时使用临时下载目录。 3. 将记录分类为 Bug、已有功能、接受的改进、样式偏好或超范围;只导入确认接受的项。 4. 每条导入任务保存 `source.kind=feishu-base`、`source.ref`、`source.recordId`、 `source.updatedAt`,并把截图观察转成文字证据。 5. 导入前扫描已有任务的 `source.ref`。相同来源不得新建第二条任务。 6. 来源更新但任务尚为 `open` 时可由 Coordinator刷新描述;任务已派发或进入终态时只报告漂移,由用户决定是否新开任务。 7. 飞书记录删除、不可访问或 CLI 暂时失败时保留已有 ACK 任务,不反向删除。 8. title、actual、expected、updatedAt 是不可推断的来源事实,部分缺失时 fail closed; steps、acceptance、priority 缺失时由 Coordinator 根据来源事实和项目上下文补齐, 并写入 `evidence.intakeEnrichment`,不要求报告者返回飞书机械补录。 9. 没有附件且所有 Bug 内容字段均为空的误建行跳过并输出 `blank_record_skipped`;带部分 来源事实的残缺行不得静默跳过。 ## 可观测验收信号 1. 两个假租户 profile 同时存在时,项目指定 `tenant-b`,所有记录和附件命令都显式包含 `--profile tenant-b`,不会读取 active 的 `tenant-a`。 2. 只读取配置的 `ACK Ready` view ID,并投影配置字段;不查询整张表或其它视图。 3. 一条含截图附件的假记录被标准化为稳定 `sourceRef`、完整文字字段和本地附件路径,输出中不存在任何 secret/token 凭据。 4. CLI 缺失、profile 缺失、畸形 JSON、错位矩阵、分页越界、路径穿越或附件下载失败均返回非零退出码且不输出伪成功结果。 5. ACK 文档明确要求按 `source.ref` 幂等整理;同一读取结果重复提交不会生成第二个来源任务。 6. 现有无 `bugIntake` 的 ACK 项目仍能通过任务板校验并按原流程工作。 7. 缺少 steps、acceptance、priority 的记录仍生成 create/refresh 计划并列出 `enrichmentRequired`;全空误建行被跳过,缺 title/actual/expected 的部分记录失败。 ## 最脆弱假设与降级 本设计假设官方 `lark-cli` 的 Base JSON 输出保持 `fields`、`record_id_list` 与行矩阵 对应关系。读取器必须校验三者长度和字段映射;若上游输出契约变化,立即失败并提示 升级适配器,不能错列生成 Bug。飞书或 CLI 不可用时,只停止新的同步,已经进入 `tasks.yaml` 的任务继续按 ACK 闭环执行。