lark-workflow-prd-sync-a9bb6f — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited lark-workflow-prd-sync-a9bb6f (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md)(若存在),其中包含 lark-cli 的认证、权限处理
write-a-prd ────► [本 skill: prd-sync] ────► prd-to-userstory
(创建) (同步/维护) (拆成 Story)本 skill 是「同步/维护」环节,独立可用:
# 读取文档
lark-cli auth login --scope "docx:document:readonly"
# 读取评论
lark-cli auth login --scope "docs:document.comment:read"
# 更新文档(同步回飞书时)
lark-cli auth login --scope "docx:document:write_only docx:document:readonly"说明:多次 login 的 scope 会累积(增量授权),无需重复授权已有 scope。
每次同步前先识别「本次变更规模」,按下表自动维护本地 PRD 顶部的「版本信息」与「变更日志」表:
| 变更规模 | 版本号增长 | 判定标准 |
|---|---|---|
| 大版本(major) | 1.x → 2.0 | §4 详细设计大幅重写、§5 功能清单新增/删除 ≥ 5 行、整体方案换路 |
| 小版本(minor) | 1.0 → 1.1 | 局部章节微调、零散字段更新、评论解决/补充、OQ 状态变化、版本日志补登 |
操作清单:
飞书文档 URL 或本地 .md 路径
│
▼
Step 0.5: 识别 PRD 元数据来源
├─► 有 frontmatter → 直接读 feishu_url / feishu_doc_token
├─► 有 <!-- 飞书文档:URL --> 注释(旧版本)→ 解析 URL,本次同步后补写 frontmatter
└─► 都没有 → AskUserQuestion 让用户提供飞书 URL
│
▼
Step 1: 下载文档 → 保存 .md 到 prd/YYYY/M/(保留/补全 frontmatter)
│
▼
Step 2: 拉取所有评论
├─► 2.1 未解决评论 → 写入/更新 §6 Open Questions
└─► 2.2 已解决评论 → 删除本地 ⚠️ [评论] 标记 + 更新 OQ 状态为「已解决」
│
▼
Step 3: 分析 §4 需求详细设计
│
├─► 更新 §3.1 整体变更(每条需求对应一行)
└─► 更新 §5 功能清单(每个功能点对应一行)
│
▼
Step 4: 如有未解决 OQ → 在文档标题末尾追加 -draft
│
▼
Step 5: 按 Step 0 规则更新版本号 + 变更日志 + frontmatter.version
│
▼
Step 6: 增量同步回飞书(只更新 §3.1 / §5 / §6 / §2 变更日志,不触碰 §4)
│
▼
Step 7: 输出 [HANDOFF] 块 → 供下游 prd-to-userstory 消费输入分支:
继续 Step 1 下载文档;下载后自动在本地 .md 顶部写入 frontmatter。
Read 本地 .md 头部:
# 伪代码:识别元数据
if 第1行 == "---":
解析 YAML frontmatter,取 feishu_url / feishu_doc_token
elif 某行命中 "<!-- 飞书文档:(.+) -->":
解析 URL,本次同步结束后补写 frontmatter(向下兼容迁移)
else:
AskUserQuestion 让用户提供飞书 URL从 URL 中提取 token:
https://xxx.feishu.cn/docx/TOKEN → token = TOKENhttps://xxx.feishu.cn/wiki/NODE_TOKEN → 需先解析真实 doc token(见下方)# wiki 链接需先获取真实 doc token
lark-cli wiki +get-node --node-token NODE_TOKEN --as user
# 从返回的 obj_token 字段获取真实文档 tokenlark-cli docs +fetch --api-version v2 \
--doc "DOC_TOKEN" \
--doc-format markdown \
--as userprd/YYYY/M/(如 prd/2026/5/)hps-x-v2-selection-prd.md---
prd_id: {文件名 slug}
title: {PRD 标题}
feishu_url: {URL}
feishu_doc_token: {DOC_TOKEN}
version: "{从飞书侧 §1 版本信息读取,缺省 1.0}"
created: "{从飞书侧 §1 版本信息读取,缺省今日}"
status: reviewing # 下载自飞书意味着已在评审中
project: "" # 由用户后续 prd-to-userstory 时填写,或此处由用户显式指定
target_version: ""
---操作:将 docs +fetch 的输出(跳过飞书侧不存在的 frontmatter)写入 frontmatter 之后。⚠️ CLI 实际参数签名:drive file.comments list 使用 --params 传 JSON,不是 --doc-token/--file-type。
lark-cli drive file.comments list \
--params '{"file_token":"DOC_TOKEN","file_type":"docx"}' \
--as user --page-all \
-q '[.data.items[] | {comment_id, is_solved, quote, replies: [.reply_list.replies[].content.elements[] | (.text_run.content // "")] | join("")}]'返回字段说明:
| 字段 | 说明 |
|---|---|
comment_id | 评论 ID |
is_solved | true = 已解决;false = 未解决(需在 OQ 表呈现) |
quote | 评论锚定的原文片段(用于定位章节) |
reply_list.replies[].content.elements[].text_run.content | 评论正文 |
只处理 is_solved: false 的评论,按下表结构写入:
| 编号 | 所在章节 | 问题描述 | 负责人 | 状态 |
| --- | --- | --- | --- | --- |
| OQ-01 | §4.X ... | [评论内容] | TBD | 未解决 |定位章节:根据 quote 在本地 .md 中 grep 匹配最近的标题(## / ###)。
对所有 is_solved: true 的评论:
> ⚠️ **[评论]** ... 行提示:判断飞书侧 §4 是否有更新,可对比 Step 1 下载的最新 markdown 与本地 §4 段落,diff 出新增/修改的关键决策。
## 3.1 整体变更
| 需求背景 | 处理方式 | 变更类型 |
| --- | --- | --- |
| [原始问题/痛点] | [解决方案] | 新增 / 优化 / 修复 |遍历 §4 的每一个子章节(### 4.X.X),提取:
新增(全新功能) / 优化(已有功能改进) / 修复(缺陷修正)每个子章节对应 §3.1 中的一行,一一对应,不要合并。
# 5. 功能清单
| 功能模块 | 功能描述 | 优先级 | 开发状态 | 备注 |
| --- | --- | --- | --- | --- |
| [模块名] | [具体功能] | P0 | 待开发 | §4.X.X,[待确认项] |粒度原则:`## ` 级别的章节 = 一条功能清单行(User Story 粒度),不要按子章节拆分。
子章节(### 级别)的细节作为功能描述的补充说明写在同一行,不单独拆行。若 §6 Open Questions 表格中存在任意一行状态为 未解决,则在文档标题行(第一个 # 开头的标题)末尾追加 -draft:
# PRD:XXX-draft若所有 OQ 均已解决,移除 -draft 后缀。
| 触发条件 | status 值 |
|---|---|
| 存在未解决 OQ | reviewing |
| 全部 OQ 解决,审核人仍为空 | reviewing |
| 全部 OQ 解决且审核人字段已填 | approved |
禁止使用 `--command overwrite`,因为会清空图片、评论和 §4 详细设计内容。 必须使用 逐章节精确替换。
PRD 文档的 §3.1 / §5 / §6 / §2 变更日志 都是单一 <table> block,最佳做法是直接替换整个表格 block。这样:
需要使用 --scope section --start-block-id <heading_id> 模式:
# Step 1: 用 keyword 找到 heading 的 block ID
lark-cli docs +fetch --api-version v2 \
--doc "DOC_TOKEN" \
--detail with-ids \
--scope keyword \
--keyword "整体变更" \
--as user
# Step 2: 用 section 模式拉取 heading 子树(含表格 ID)
lark-cli docs +fetch --api-version v2 \
--doc "DOC_TOKEN" \
--detail with-ids \
--scope section \
--start-block-id "HEADING_ID" \
--as user对 §3.1 / §5 / §6 / §2 变更日志 各重复一次(关键词分别用「整体变更」「功能清单」「Open Questions」「变更日志」)。
注意:变更日志原文是<p><b>变更日志</b></p>,section 模式默认只返回 heading 自身。需要加--scope range --start-block-id <heading_id> --context-after 2才能拿到后续表格 block。
⚠️ lark-cli 限制:--content @文件 只支持当前目录的相对路径,不支持 /tmp/xxx.xml。改用 --content - 走 stdin 输入:
# 1. 把表格 XML 写到临时文件(不带外层 heading,只 <table>...</table>)
cat > /tmp/section_3_1_table.xml <<'EOF'
<table>
<colgroup>...</colgroup>
<thead>...</thead>
<tbody>...</tbody>
</table>
EOF
# 2. 通过 stdin 喂给 lark-cli
lark-cli docs +update --api-version v2 \
--doc "DOC_TOKEN" \
--command block_replace \
--block-id "TABLE_BLOCK_ID" \
--content - --as user < /tmp/section_3_1_table.xml返回体出现 "warnings": [] 就说明替换成功。
若无法精确获取 block ID,可使用 markdown 模式的 str_replace:
lark-cli docs +update --api-version v2 \
--doc "DOC_TOKEN" \
--command str_replace \
--doc-format markdown \
--pattern "## 3.1 整体变更...## 3.2" \
--content - <<'EOF'
## 3.1 整体变更
| 需求背景 | 处理方式 | 变更类型 |
| --- | --- | --- |
| ... |
## 3.2
EOF注意:...省略号语法会将从前缀到后缀的所有内容(含两端)整体替换为--content,所以 content 中必须包含前缀和后缀。
Skill 完成后必须打印以下块,作为下游 prd-to-userstory 的输入:
✅ PRD 同步完成
📄 本地文件:{local_path}
🔗 飞书文档:{feishu_url}
📌 版本:{new_version}({变更规模 major|minor})
📝 状态:{status}
变更概览:
- §3.1 整体变更:{+N 行/-M 行}
- §5 功能清单:{+N 行/-M 行}
- §6 Open Questions:未解决 {N} 条 / 已解决 {M} 条
[HANDOFF: prd-sync → prd-to-userstory]
- local_path: {local_path}
- feishu_url: {feishu_url}
- feishu_doc_token: {doc_token}
- version: {new_version}
- status: {reviewing | approved}
- feature_count: {§5 P0 行数}
- unresolved_oq: {未解决 OQ 数}
- project: {frontmatter.project 或空}
- target_version: {frontmatter.target_version 或空}| 操作 | CLI 命令 | 所需 Scope |
|---|---|---|
| 读文档 | docs +fetch | docx:document:readonly |
| 读评论 | drive file.comments list | docs:document.comment:read |
| 改文档 | docs +update | docx:document:write_only docx:document:readonly |
../lark-shared/SKILL.md — lark-cli 认证、权限处理(必读,若已安装 lark-shared skill)../lark-doc/references/lark-doc-update.md — docs +update 详细用法../lark-doc/references/lark-doc-fetch.md — docs +fetch 局部读取策略../lark-drive/SKILL.md — drive file.comments list 用法../write-a-prd/SKILL.md — 上游:PRD 骨架生成../lark-workflow-prd-to-userstory/SKILL.md — 下游:PRD → User Story~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.