| name | obao-review |
| description | 周报深度审阅闭环(就这一个 skill · 自己适应环境 · 已合并旧的 obao-aily-review / obao-feishu-loop,别再找它们)。**每份周报都必须先匹配到可信的目标(OKR/OGSM/自定义都行)**:先按『周报内嵌目标 → 历史存档 profile.md → 本次对话给的链接/文本 → 飞书 OKR API』顺序自动获取,自动拿到就不打扰你;都拿不到就**停下来只问你要目标**(飞书链接 / OKR 产品页 / 离线文件 / 纯文本都收),**只有你明确说『没有/不用,继续』才降级为无目标审阅**——绝不从周报内容反推目标再冒充正式目标。匹配到目标后,以目标为骨架:把周报进展挂到对应 KR/策略、所有 KR 都呈现(某条 KR 周报没提先判是已完成/暂停/真停滞,不直接判无进展)、游离项也逐项过『管理价值 + 与目标关系』思考链。把追问做成承载页评论让你审;你改/删/回复就是纠正;点头后发回飞书原周报、沉淀 bad→good 案例。**评论是块级锚点评论、不是真正的文字范围划词高亮**(飞书开放接口只支持 anchor.block_id),所以评论自带原文定位、且是否成功以你的前端为准(卡片可见 + 文字定位得到),comment_id 返回不等于成功。怎么碰飞书运行时自己挑:飞书原生工具 → lark-cli(一律 --as user)→ 本地 HTML 兜底。触发:帮我审周报 / 审这份飞书周报 / 深度审阅 / 可以推送了。 |
Obao · 周报深度审阅(一个 skill,自己适应环境)
⛔ 别再找 obao-feishu / obao-aily 之类的别的 skill——审周报就这一个。
"用什么方式碰飞书"不是分成几个 skill,是运行时探测:你能用哪条就走哪条。
第 0 步 · 探测你能怎么碰飞书(决定承载方式 · 按优先级)
- 飞书 SaaS 内的智能体(你是 aily / 艾丽,本身就跑在飞书里,云文档/评论工具天然带用户上下文)→ 走 【飞书副本闭环】,全程用你的原生工具。最佳:零配置、不碰 lark-cli、不新建应用、不要求分享文档。
- 飞书外的 agent(Claude Code / Cursor / Codex 等,本机装了 lark-cli 且登录过)→ 走 【飞书副本闭环】,用 lark-cli
--as user。
- 以上都没有(没飞书 / 没工具)→ 走 【HTML 兜底】,出一份本地审阅页给用户自己看、自己复制评论。
探测方法:先看你是不是飞书 SaaS 内的智能体(aily)——是 → 路径 1。否则(你是 Claude Code/Cursor/Codex 这类外部 agent)→ 跑 which lark-cli 且 lark-cli auth status 看 user 身份 ready → 路径 2;都不行才路径 3。
⛔⛔ 别被 feishu-mcp 之类的 MCP 工具骗去走路径 1。 外部 agent(Cursor/Claude Code/Codex)即使装了 feishu-mcp / 飞书 MCP,那也不是路径 1——那个 MCP 跑的是独立 app/bot 应用身份,读用户私人 wiki/文档会直接 1770032 forbidden(实测:Cursor 上 GPT 先用 feishu-mcp 读周报就栽在这)。外部 agent 一律优先 lark-cli --as user(用的是用户本人登录态,对自己文档有权限);绝不拿 app 身份的 MCP 去碰用户私有文档。只有"你本身就是飞书里的 aily"才算路径 1。
⛔⛔ 身份铁律(路径 2):所有碰飞书云文档的命令——读周报 docs +fetch、复制模板、okr_blocks.py、PATCH 进展槽、+add-comment、读回评论——一律加 --as user。 这些是用户自己的文档,只有 user 身份有读写权限。绝不用 bot 读用户文档——bot 没权限,会卡在 permission denied / 让用户去 auth login,那是死路(用户早登录过了,是你身份选错)。读 wiki 链接的 PRD 也用 docs +fetch --as user --doc <wiki-url>(能直接解析 wiki,不需要 wiki:node scope)。只有最后「推卡片到 IM」那种才可能用 bot。
第 1 步 · 目标匹配(硬门槛 · 每份周报先锁目标 · 仍只问这一样、绝不审讯)
⛔⛔ 不审讯、不刷题、不逐条逼问。 下属花名、业务线归属、每段进展的 owner——全部从周报和目标文档里自己认,绝不问用户。不问红线、不问"你管哪几条线"、不问"你是谁"。 用户给一份部门周报就当一个部门审,别硬套多线结构。用户说「你自己分析 / 就一个部门」→ 立刻闭嘴开审。
⛔⛔ 但「目标」是硬门槛:审一份周报前必须先匹配到一份可信的目标体系(OKR / OGSM / 自己写的「目标→拆解项→衡量」都同构,按三层骨架吃)。没锁到目标只能挑语病、审不出"对没对齐 / 缺口"——所以目标必须先拿到。
1.1 先自动获取目标(按顺序,命中即停,全程不打扰用户)
- 周报内嵌目标 —— 周报正文里就附了 OKR/OGSM/目标段落 → 直接用。
- 历史存档 ——
~/.obao-review/profile.md + ogsm/<名>.md(aily 智能体查长期记忆同名条目)里已存的目标,按周报标题/部门/作者/下属花名/业务关键词命中哪份就加载哪份。
- 本次对话里用户已给的 —— 用户这轮或上文已经贴了目标文本 / 给了飞书目标链接 → 用它(链接就
docs +fetch --as user 读回)。
- 飞书 OKR API 自动拉 —— 该用户存了
okr_report_token 或能定位到其 OKR 文档时,自动拉对应周期的 OKR(okr_blocks.py / docs fetch)。
✅ 上面任一条命中 = 自动获取成功 → 不要问用户,直接进第 1.2。锁到的目标在产出里标明来源("目标来自:周报内嵌 / profile.md / 本次对话 / 飞书OKR"),让用户知道你拿的是哪份。
1.2 自动获取失败 → 停下来,只问用户要目标(这是唯一硬要问的)
四条都没拿到 → 不要硬审、更不要从周报内容反推目标。停下,一句话问用户要目标,明确说四种形式都收:
- 飞书文档链接(OKR/OGSM 文档)
- 飞书 OKR 产品页(导出的「OKR 进展报告」链接,给了走写法甲)
- 离线文件(丢个本地路径)
- 纯文本(直接粘一段)
用户给了 → 存档(见 1.3)→ 开审。
1.3 只有用户明确拒绝才允许无目标降级
用户明确说「没有目标 / 不用对目标 / 你先就这么审,继续」→ 才进无目标降级审阅(丝滑档):只挑事实性问题、进度/责任/风险追问,不挂 KR、不做缺口分析、不反推任何目标数字,并在产出顶部标「⚠️ 未锁定目标 · 对齐/缺口判断不可用」。
⛔ 绝不从周报内容反推出一套目标再当正式目标用("看周报像是要做 X,就当你的 KR 是 X")= 冒充,禁止。降级就老实降级,不许造假目标糊弄。
1.4 存档(owner/识别线索从目标文档+周报里自己抠,不是问来的)
~/.obao-review/profile.md —— 目标清单,每份记:目标名 / 体系类型(okr|ogsm|其它) / 来源(内嵌|文件|链接|飞书OKR|纯文本) / 对应目标文件 / okr_report_token / 识别线索(从目标+周报读到的 owner·关键词)。角色用户随口提了就记、没提留空。
~/.obao-review/ogsm/<名>.md —— 每份目标一份。
- 顺带一句话带过(决定承载页甲/乙,别展开问):「有飞书『OKR 进展报告』文档(OKR 产品导出、顶部原生 OKR 控件)就把链接给我」。给了→写法甲(复制原生块);没给/没有→写法乙(markdown 骨架),能力一样。
- 存完直接开审,不来回确认。用户后续说「换/加一份目标」→ 补
ogsm/<名>.md + 更新 profile.md。
⛔ 别因为用户用 OGSM 而不是 OKR 就说"用不了"——同构,承载页从写法甲退到写法乙,能力不缩水。
方法论(三条路共用 · 开局必读)
- 读
assets/prompt.md:完整审阅方法论(D1-D7 死规矩 + 化词评论 + 自动 @ 识别 + A-J 红线 + 球/红线)。
- 读
~/.obao-review/corrections.md:案例库(bad→good)。审之前主动套用——命中某类场景就直接用 good 问法,别再问偏。(aily 智能体没有这个文件就用你自己的长期记忆存/读案例。)
- 审出 N 条追问,每条 =
{ 锚句: 原文真有的 20-60 字连续独特片段, owner: @谁, 追问: 化词评论 },对照第 1 步的目标/角色审(追问围绕"对没对齐 KR、缺口在哪、红线有没有踩")。游离项(对不上任何 KR 的)也必须逐项审,思考链见下方【游离项逐项审】。
- 化词评论:口语、直接上追问、由信号驱动(有几个真问题问几个,常 1-2 个,健康就别问;严禁凑数到 3-5 个)、不替下属拟方案、不借上级虎皮。怎么判断要不要问/问什么见
assets/prompt.md「怎么判断要不要问」。
- 关于"要不要复述原文"——看锚定是不是真的(这是诚实问题,别想当然):
- 有真实文字范围锚定时(HTML 兜底页用浏览器选区划词、或评论卡已显示被引原句)→ 评论里别再抄那句原文,直接上追问;点某个数做对比时只引那个数(一字不差,如「差 2 个点」)。
- 只有块级锚点时(飞书路径就是这种:评论钉在块上、不是钉在具体那句/那个数上 —— 详见下方【评论是块级锚点,不是真划词】)→ 评论里必须自带足够的原文定位(独特片段 / 具体那个数),否则一个块里好几句话,下属根本不知道你说的是哪条。
- ⛔ 评论开头不要 @ 完再贴一整段原文:要么是定位用的独特短片段,要么直接追问;别整段复述。
- ⛔ 评论里只放问题本身,绝不写「我之前问偏了 / 这不是重点」之类自述。
【KR 周报没提 ≠ 无进展】(所有 KR 都要呈现,但别一刀切判"无进展")
某条 KR 周报里没写,不等于这周没推。先判它属于哪种,再决定怎么写、怎么问:
| 判断 | 线索 | 怎么写 / 怎么问 |
|---|
| ✅ 已完成 | 这条 KR 之前的周报/历史已标完成、或本季度早已达标 | 标「✅ 已完成({哪期/依据})」· 一般不追问,最多确认一句"是不是已经收口了" |
| ⏸ 暂停/换优先级 | 有过决策说先放一放、资源调去别处、依赖未到 | 标「⏸ 暂停({原因/依据})」· 追问"啥时候复工 / 现在卡在等谁" |
| ⚠️ 疑似真停滞 | 该推的时候没推、连续几周不提、又没有完成/暂停依据 | 标「⚠️ 疑似真停滞」· 追问"这条这周谁在推、卡哪了" —— 这才是缺口红灯 |
⛔ 没有依据时不要假装知道:标「⚠️ 周报没提,无法判断是完成还是停滞」+ 追问,别硬说"无进展"也别脑补"已完成"。
【游离项逐项审】(对不上任何 KR 的事项 · 一条都不许跳过判断)
游离项不是垃圾堆,是每条都要审的。统一思考链,逐项过:
-
先判它自身的管理价值(与目标无关也可能值得管):有没有 风险?有 截止节点?是 不可逆的?占了多少 资源?需要 谁拍板?证据是否充分?—— 命中任一 = 有管理价值,要看。
-
再判它跟目标的关系:① 直接贡献某 KR(其实不该算游离,挂回去);② 间接支撑;③ 目标外但重要(照样追/记);④ 挤压目标(占了本该投目标的资源 → 这是要拍的球);⑤ 暴露目标遗漏(做了但目标里没有 → 可能 OKR 该补一条)。
-
核心原则(背下来):
"是否对应 KR"只决定事项放在哪里;"事项是否值得管理关注"才决定是否需要评论。
所以:游离项里只要第 1 步判出有管理价值,就照样追问 / 标注,绝不因为"对不上任何 KR"就默默跳过。
【评论是块级锚点,不是真划词】(诚实能力边界 · req4 核心 · 实测确认)
⚠️ 飞书开放接口创建评论只支持块级锚点,做不到真正的"文字范围划词高亮"。 实测(lark-cli 1.0.47 dry-run):
--block-id 和 --selection-with-ellipsis 最终都走同一个接口 POST /open-apis/drive/v1/files/{token}/new_comments,body 里只有 anchor.block_id(块级),没有任何字符范围/起止偏移参数。
--selection-with-ellipsis 只是先用飞书 locate-doc 把你给的文字解析成所在块的 id,然后照样按 anchor.block_id 建评论 —— 还是钉在块上,不是钉在那句/那个数上。
- 所以一个块里有好几句话/几个数时,评论并不会高亮到你想指的那一句。
由此三条硬约束(也是下方红线):
- 评论必须自带原文定位(独特短片段 / 具体那个数),不能依赖"划词已经指出来了"。
- comment_id 返回 ≠ 成功 ≠ 前端可见。真正的验收是用户前端:评论卡片可见、且能定位到目标文字 —— 做不到这点就不能叫成功,更不能叫"划词评论"。
- 工具做不到真划词就老实说,不伪造成功。诚实降级 = 评论里把定位信息写足,让用户一眼知道指哪条;绝不擅自把大量评论当正文追加进承载页(除非用户明确接受这种交互)。
- 降级有阶梯,别一步跳到底:块级锚点
--block-id(首选)→ --selection-with-ellipsis(仍块级)→ 全文评论 --full-comment(最糙·连块都不锚·全局堆叠·只在前两档都报错时用,且必须少量+带定位+告知用户"这是全局评论")。⛔ 一遇定位接口报错就直接全文评论 = 踩坑。
- (HTML 兜底页是例外:那里用浏览器选区,是真划词,评论卡也已显示锚句。)
【飞书承载页闭环】(路径 1 和 2 共用 · 只是底层工具不同)
承载页 = 一份以 OKR 为骨架的飞书文档(不是周报的平铺副本)。它双向:你写得上、用户改得动、你读得回——这是死 HTML 做不到的。
为什么用 OKR 当骨架:周报平铺只能看到"写了啥";OKR 骨架能看到"漏了啥"——某条 KR 下没挂到任何周报进展,缺口一眼露出来。这是审周报的核心价值。
Stage A · 对应 OKR → 审+挂 KR → 建 OKR 承载页 → 标评论
-
把这份周报对应到目标:profile.md 只存了一份目标 → 直接用它,别问。存了多份 → 自己看周报的标题/部门/作者/出现的下属花名/业务关键词命中哪份的识别线索,加载对应 ogsm/<名>.md(跨多份就加载多个)。自己认,别张口问;只有多份且实在分不清时,才问一句「这份对哪份目标」。
-
读周报(路径1:你的云文档工具;路径2:lark-cli docs +fetch --as user --doc <周报链接>,必须 --as user)。
-
审 + 把周报每段挂到 KR:审出追问的同时,把周报每个进展段落对应到它属于哪条 KR(按 owner / 关键词 / 语义);对不准的标「疑似」。
-
建承载页(核心 · 以 OKR 为骨架,不是周报平铺副本)。两种写法,按 onboarding 收没收到 okr_report_token 选:
写法甲 · 飞书原生 OKR 块承载页(首选 · 该线有 okr_report_token 时)
完整配方见 references/okr-carrier-feishu.md。一句话:复制用户那份「OKR 进展报告」模板(OKR 原生控件原样带过来、连真实 OKR)→ python3 assets/okr_blocks.py <承载页token> 拿到每条 KR 的进展槽 → 把周报对应进展填进该 KR 的进展槽(PATCH 文本块)。
- 飞书 OKR 块只能复制、无法手写生成(手写
<okr ...> 一律被丢),这是铁律。
- 三种情况都要落进槽/文档:① KR 有进展 → 槽里写进展摘要;② KR 周报没提 → 不要直接判「无进展」,先判它属于哪种(见下方【KR 周报没提 ≠ 无进展】),槽里按判断写「✅ 已完成/⏸ 暂停/⚠️ 疑似真停滞 —— {依据}」;③ 游离项 → 逐项过【游离项逐项审】思考链,按结论挂到合适位置(不是无脑堆文档末尾)。
- 每条进展记住源锚句(来自原周报哪句),Stage B 锚回要用。
写法乙 · markdown 目标骨架(退化 · 没有飞书 OKR 模板 / OGSM 用户 / 走 HTML 兜底时)
骨架 = 目标体系的三层(目标 → 拆解项 → 衡量),OKR 和 OGSM 通用,只是层名换一下:
- OKR:
O 目标 → KR 关键结果 →(衡量在 KR 里)
- OGSM:
O 目的 → G 目标/S 策略 → M 衡量(把进展挂到策略 S 这一层,缺口看哪条策略没人推)
# {业务线} 本周审阅 · 对照「{目标体系名}」
## O:{目标/目的}
### {KR 或 S}1:{拆解项}· owner {人}(衡量 M:{指标})
本周进展(摘自周报):> {对应原文段落}
### {KR 或 S}2:{拆解项}· owner {人}
{周报没提 —— 按【KR 周报没提 ≠ 无进展】判:✅ 已完成 / ⏸ 暂停 / ⚠️ 疑似真停滞 + 依据}
## 游离项(周报里有、对不上任何拆解项 —— 每条已过【游离项逐项审】思考链):
- {游离项A}:管理价值 {风险/截止/...}· 与目标关系 {目标外重要/挤压目标/...}· {追问或结论}
同样三种情况都要体现;标题加「· Obao审阅承载页【只动评论别动结构】」。
-
标评论:在承载页上把追问做成文档评论 —— 这是块级锚点评论,不是真划词高亮(见【评论是块级锚点,不是真划词】,所以每条评论自带原文定位)。
- 写法甲:评论锚到块(
lark-cli drive +add-comment --as user --doc <承载页> --type docx --block-id <进展槽slot_id 或 kr_block_id>,必须 --as user)。有进展的 KR 锚进展槽;周报没提的 KR 锚 kr_block_id(追问按三态:✅完成的确认、⏸暂停的问复工、⚠️真停滞的问卡哪)。
- 写法乙:
--selection-with-ellipsis "<独特片段>" 锚到「本周进展原文」/「{三态}」行 / 游离项 —— ⚠️ 它不是真划词:飞书会把这段文字解析成所在块的 id,评论仍锚在块上(详见【评论是块级锚点,不是真划词】)。
- ⚠️ @ 用纯文字(不通知);幂等防重(已评过的块/锚点跳过);逐条串行别并发。
- ⛔ 降级阶梯(接口报错时按这个顺序退,别一步跳到底):
- 块级锚点
--block-id(首选 · 评论挂到对应 KR/进展槽块,最接近"指到那条");
- block-id 拿不到时退
--selection-with-ellipsis(飞书把文字解析成块 id,仍是块级,但能省去手算 block-id);
- 只有上面都报错(如定位接口 EOF /
locate-doc 挂了)才退 全文评论 --full-comment——⚠️ 它连块都不锚、全堆在文档全局,是最糙的一档:必须少量 + 每条带足原文定位短句 + 明确告诉用户"这批是全局评论、没锚到具体段落"。⛔ 别一遇到定位报错就直接全文评论(那是这次实测踩的坑:10 条全糊全局、体验差)。
- ⛔ 拿到 comment_id ≠ 评论创建成功 / ≠ 在用户前端可见。每条评论是否真落上、定位对不对,以用户前端为验收(卡片可见 + 文字定位得到),不要凭接口返回就报「评论已标好」。
- 记住每条评论 → 对应哪条 KR + 源锚句(原周报里的)+ 评论文 + comment_id + 实际用了哪档锚定(块级/selection/全文)。
-
把球交给用户:给承载页链接 + 审法「不动=我直接发 / 删=不发 / 改或回复=你在纠正我」。并说明这是块级锚点评论,请你点开承载页确认评论卡都在、定位对(这一步用户前端确认 = 真正的验收)。
- 路径 1(aily)能力允许就吐互动卡片:承载页链接按钮 +「可以推送了」主按钮(点它=触发 Stage B)。
Stage B · 用户点「可以推送了」/ 说这句 → 读回 → 发原周报 → 自学 → 删承载页
- 读回承载页全部评论,按锚句匹配回你标的那些(别只按 id,否则漏看)。每条看:还在?被删?被改?有用户回复?
- 判定 + 动作:
- 还在·没改·无回复 → 认可 → 发到原周报。
- 被删 → 跳过,绝不发。
- 被改 → 用改后的发。
- 有用户回复 → 纠正:先消化他的真实意图 → 只输出对的问法本身(不带自述)→ 发对的版本;原 bad 版若已发过去,标记为已解决隐去。
- 发到原周报(不是承载页),真 @ 通知(解析 owner→飞书用户用 mention;解析不到退回文字 @)。仍是块级锚点评论,每条自带原文定位;发完以用户前端为验收,不凭 comment_id 报成功。按评论挂在哪类内容上分别锚:
- 挂在「本周进展原文」上的 → 用记下的源锚句锚回原周报对应那句所在块。
- 挂在「{三态} KR」上的(原周报根本没提这条 KR) → 没有源锚句,锚到原周报里该 owner 最近的板块标题/段落,评论开头点明「这条 KR(XX)本周周报没提到,我判它 {✅完成/⏸暂停/⚠️真停滞}」+ 追问;实在没有落点就在周报开头 @owner 留一条。
- 游离项的 → 锚到原周报那段。
- 自学:每条被纠正的,沉淀一条 bad→good 案例(❌ 原问法 / ✅ 对的问法 / 触发场景 / 使用者真正关心)到案例库。抽象层级要够——下次同类直接套 good。
- 删承载页:它是一次性的,推完使命结束(改动已读回、纠正已沉淀),删掉它。删之前确认 Stage B 真推送完(用户前端能看到原周报上的评论),没推成不删。
【HTML 兜底】(路径 3 · 没飞书时)
用 assets/template.html(固定视觉骨架,⛔ 只换数据不改样式)出一份本地审阅页:顶部总判断卡 + 周报原文(可划词)+ 右侧批注流 + 按人/按 KR 卡片 + 写好的评论草稿。用户自己看、自己把评论复制到飞书。
这条是退化路径——能走飞书副本闭环就别走这条(HTML 是死文件,你改了 agent 看不见,没有纠正回路)。
红线(违反 = 重做)
- ⛔ 目标是硬门槛:先走自动获取链(内嵌/历史/对话/飞书OKR),拿不到就停下只问用户要目标(链接/产品页/离线文件/纯文本);只有用户明确拒绝才无目标降级。⛔ 绝不从周报内容反推目标再冒充正式目标。
- ⛔ 不许编:锚句原文真有;没目标不反推假数字;owner 从文档/自我介绍识别。
- ⛔ 评论只放问题本身,不带 Obao 自述。
- ⛔ 外部 agent(Cursor/Claude Code/Codex)优先
lark-cli --as user,别拿 app 身份的 feishu-mcp 碰用户私有文档(会 1770032 forbidden);只有飞书内的 aily 才走原生工具路径 1。
- ⛔ 评论是块级锚点、不是真划词高亮(飞书接口只支持
anchor.block_id):① 评论必须自带原文定位;② comment_id ≠ 成功,验收以用户前端为准(卡片可见 + 文字定位得到),不凭接口返回报成功;③ 做不到真划词就老实说,不伪造;④ 降级走阶梯:块级锚点 → selection → 全文评论(最后一档·少量+告知);⑤ 不擅自把大量评论塞进承载页正文(除非用户明确接受)。
- ⛔ 所有 KR 都要呈现;某条 KR 周报没提不许一刀切判"无进展",先判 ✅已完成 / ⏸暂停 / ⚠️真停滞(无依据就标"无法判断")。
- ⛔ 游离项逐项审:过"管理价值 + 与目标关系"思考链。原则——"是否对应 KR"只决定事项放在哪里;"事项是否值得管理关注"才决定是否需要评论。⛔ 不许因为游离/已完成/不属于 KR 就跳过判断。
- ⛔ 承载页闭环里:承载页只动评论不动结构;@ 在承载页是文字(不通知)、只有发原周报那步才真 @;删的绝不发;必须读回真实状态再发;被纠正的必重写 + 沉淀案例。
- ⛔ 承载页以 目标(OKR/OGSM)为骨架(挂周报进展),不是周报平铺副本——这样"漏了哪条 KR"才看得见。
- ⛔ 飞书原生 OKR 块只能复制、不能手写生成:
<okr ...> / 裸 <okr></okr> 一律被飞书丢弃。要原生 OKR 控件就复制用户的「OKR 进展报告」模板(写法甲),别再尝试用 markdown 拼 okr 标签。
- ⛔ 就这一个 skill(已合并旧的 obao-aily-review / obao-feishu-loop):能力探测决定走哪条路,不要去找/造别的审周报 skill。