diff --git a/.vala_skill_hashes b/.vala_skill_hashes
index e7b2ae7..5b29689 100644
--- a/.vala_skill_hashes
+++ b/.vala_skill_hashes
@@ -14,4 +14,4 @@ user-feedback-collector c0320451bf7ea0ce3d8ceaa603ae0a7b55c373c048363a5142258a4c
user-feedback-data-source a95eb9142f3019fd193c46f89147dc7e0bf01dfe250202565a86f8bc52f37b13
feishu-group-msg-sync 085f95a5b89fec3b6a627da25d66ffeeb0be430098387739a64f7903f0ee88d4
user-feedback-processor 61783a8e9f03a973c187b359a87749ad1993dc71f8364b0a853d8b3ff64c75e8
-feishu-feedback-sync 1fe2d72586096fc49cb39f5aa1d3f3e364664d8c7578a27ae49ef1be8f7a9896
+feishu-feedback-sync b046dd9f252ba6672acfac66aa732442cded924f0cd3c70e46cba5c6e300af6d
diff --git a/memory/.dreams/events.jsonl b/memory/.dreams/events.jsonl
index 758e45b..13cc865 100644
--- a/memory/.dreams/events.jsonl
+++ b/memory/.dreams/events.jsonl
@@ -2,3 +2,7 @@
{"type":"memory.recall.recorded","timestamp":"2026-04-30T06:52:35.560Z","query":"用户反馈数据源 飞书群 微信群 数据库表","resultCount":1,"results":[{"path":"memory/2026-04-18.md","startLine":1,"endLine":5,"score":1}]}
{"type":"memory.recall.recorded","timestamp":"2026-04-30T08:11:39.116Z","query":"飞书群反馈表格 token E8vFsCmPBhT4SCtNmnJchqeJnJe 内容测试问题反馈","resultCount":1,"results":[{"path":"memory/2026-04-18.md","startLine":1,"endLine":5,"score":1}]}
{"type":"memory.recall.recorded","timestamp":"2026-05-06T13:30:08.593Z","query":"内容测试反馈群 群聊规则 GroupSystemPrompt","resultCount":5,"results":[{"path":"memory/2026-04-30.md","startLine":198,"endLine":224,"score":1},{"path":"memory/2026-04-30.md","startLine":116,"endLine":142,"score":1},{"path":"memory/2026-04-30.md","startLine":134,"endLine":166,"score":1},{"path":"memory/2026-04-30.md","startLine":177,"endLine":205,"score":1},{"path":"memory/2026-04-18.md","startLine":1,"endLine":5,"score":1}]}
+{"type":"memory.recall.recorded","timestamp":"2026-05-07T02:22:47.713Z","query":"用户反馈问题汇总 文档 写入逻辑 覆盖 overwrite","resultCount":6,"results":[{"path":"memory/2026-05-06.md","startLine":61,"endLine":86,"score":1},{"path":"memory/2026-04-30.md","startLine":116,"endLine":142,"score":1},{"path":"memory/2026-04-30.md","startLine":177,"endLine":205,"score":1},{"path":"memory/2026-04-30.md","startLine":198,"endLine":224,"score":1},{"path":"memory/2026-04-30.md","startLine":134,"endLine":166,"score":1},{"path":"memory/2026-04-30.md","startLine":73,"endLine":102,"score":1}]}
+{"type":"memory.recall.recorded","timestamp":"2026-05-07T02:22:52.564Z","query":"用户反馈问题汇总 写入知识库 append overwrite 文档模式 feishu-feedback-sync","resultCount":6,"results":[{"path":"memory/2026-05-06.md","startLine":61,"endLine":86,"score":1},{"path":"memory/2026-04-30.md","startLine":116,"endLine":142,"score":1},{"path":"memory/2026-04-30.md","startLine":177,"endLine":205,"score":1},{"path":"memory/2026-04-30.md","startLine":198,"endLine":224,"score":1},{"path":"memory/2026-04-30.md","startLine":134,"endLine":166,"score":1},{"path":"memory/2026-04-30.md","startLine":73,"endLine":102,"score":1}]}
+{"type":"memory.recall.recorded","timestamp":"2026-05-07T02:55:43.649Z","query":"问题分类 分类规则 版本更新 声音音频 UI显示 启动运行 语音识别 关卡内容 priority_classifier","resultCount":6,"results":[{"path":"memory/2026-05-06.md","startLine":61,"endLine":86,"score":1},{"path":"memory/2026-04-30.md","startLine":116,"endLine":142,"score":1},{"path":"memory/2026-04-30.md","startLine":177,"endLine":205,"score":1},{"path":"memory/2026-04-30.md","startLine":198,"endLine":224,"score":1},{"path":"memory/2026-04-30.md","startLine":134,"endLine":166,"score":1},{"path":"memory/2026-04-30.md","startLine":73,"endLine":102,"score":1}]}
+{"type":"memory.recall.recorded","timestamp":"2026-05-07T03:19:39.321Z","query":"小葵小葵群 chat_id 发消息 bot","resultCount":1,"results":[{"path":"memory/2026-04-18.md","startLine":1,"endLine":5,"score":1}]}
diff --git a/memory/.dreams/short-term-recall.json b/memory/.dreams/short-term-recall.json
index b2a26d0..0863336 100644
--- a/memory/.dreams/short-term-recall.json
+++ b/memory/.dreams/short-term-recall.json
@@ -1,6 +1,6 @@
{
"version": 1,
- "updatedAt": "2026-05-06T13:30:08.593Z",
+ "updatedAt": "2026-05-07T03:19:39.321Z",
"entries": {
"memory:memory/2026-04-18.md:1:5": {
"key": "memory:memory/2026-04-18.md:1:5",
@@ -9,22 +9,24 @@
"endLine": 5,
"source": "memory",
"snippet": "# 2026-04-18 工作日志 ## 术语共识 [李若松确认] 术语「飞书反馈消息数据库」默认指代用户反馈收集技能中的飞书内部测试反馈MySQL数据表 `vala_test.lark_group_message`,存储「内容测试问题反馈」群(oc_fabff7672e62a9ced7b326ee4a286c26)的同步消息数据。",
- "recallCount": 4,
+ "recallCount": 5,
"dailyCount": 0,
"groundedCount": 0,
- "totalScore": 4,
+ "totalScore": 5,
"maxScore": 1,
"firstRecalledAt": "2026-04-30T03:47:21.989Z",
- "lastRecalledAt": "2026-05-06T13:30:08.593Z",
+ "lastRecalledAt": "2026-05-07T03:19:39.321Z",
"queryHashes": [
"353f9765c086",
"a6b740c99377",
"9625ed0029fd",
- "f865295b9ac7"
+ "f865295b9ac7",
+ "42fe8210f22c"
],
"recallDays": [
"2026-04-30",
- "2026-05-06"
+ "2026-05-06",
+ "2026-05-07"
],
"conceptTags": [
"vala-test.lark-group-message",
@@ -44,18 +46,22 @@
"endLine": 224,
"source": "memory",
"snippet": "3. 问题描述留 `[AI归纳]` 占位符 - 运行时 AI(即助手本身)根据元数据 + 对话上下文,生成精炼的问题描述 #### AI 归纳的最终输出格式(固定模板) ```markdown ### 问题 N > **在{端}端{环节}内({课程}),{角色/组件}出现了{现象}** | 发言人 | 要点 | |--------|------| | ... | ... | **当前问题排查结论:** ... ``` #### 结论提取规则增强 - 解释性关键词:上云/预下载/加载/原因是/改为了/首次 → 标记为分析性发言 - 分析性发言 + 日志上传 → 输出「疑似{原因},已上传日志,排查中」 - 分析性发言 + 无日志 → 输出「{原因},待确认」 - 无分析 + 无日志 → 改为「暂未排查到问题」(刘新玉确认,比「暂未排查到根因」更准确) #### 4/28 最终归纳结果(AI 生成) 1. **NPC HUD 显示**:在移动端关卡内(11-2),NPC 头上的 HUD 偶尔变成一小条 → 暂未排查到问题 2. **iOS Loading 慢**:在 iOS 端关卡内(L1 3-2),Loading 耗时约 10 秒(正常 3 秒),导致组件数据丢失/无音频 → 疑似关卡内容上云加载导致,已上传日志,排查中 #### 结论提取的边界 - 刘新玉指出:\"暂未排查到问题\" vs \"暂未排查到根因\" → 前者更准确(问题被描述了但可能没被排查)",
- "recallCount": 1,
+ "recallCount": 4,
"dailyCount": 0,
"groundedCount": 0,
- "totalScore": 1,
+ "totalScore": 4,
"maxScore": 1,
"firstRecalledAt": "2026-05-06T13:30:08.593Z",
- "lastRecalledAt": "2026-05-06T13:30:08.593Z",
+ "lastRecalledAt": "2026-05-07T02:55:43.649Z",
"queryHashes": [
- "f865295b9ac7"
+ "f865295b9ac7",
+ "cd9c89262c30",
+ "ac7fd0b52a4e",
+ "49c0959dc960"
],
"recallDays": [
- "2026-05-06"
+ "2026-05-06",
+ "2026-05-07"
],
"conceptTags": [
"角色/组件",
@@ -75,18 +81,22 @@
"endLine": 142,
"source": "memory",
"snippet": "问题:很多消息有关联但没有 `quote_message_id`(飞书 API 的 `root_id`/`parent_id` 未采集) **推断规则(按优先级)**: 1. **@提及匹配**:消息中 @了某人 → 关联到被@者最近一条消息 2. **同发送者聚类**:同一人在 2 分钟窗口内连续发多条 → 认为是对同一目标消息的回复 3. **最近不同发送者**:关联到最近一条不同发送者的消息(30 分钟内) 已测试效果:上午 NPC HUD 问题链成功串联,下午 iOS 问题链准确分组。部分跨话题误判仍需 AI 语义辅助(策略3,待后续评估)。 #### 触发方式 - 手动:「同步飞书反馈」「整理反馈对话链」 - 定时:每天 10:00 crontab 自动执行 ## 步骤4:问题归纳功能开发 [刘新玉] - 2026-04-30 18:38 完成 ### 步骤4 包含两部分 1. **问题描述**:在{端}{环节}内({课程}),{角色/组件}出现了{现象} 2. **当前问题排查结论**:从对话最后 1-2 条提取,匹配规则: - \"日志上传/排查/查\" → \"日志已上传,排查中\" - \"确认/确实\" → \"已确认,待修复\" - \"已修复/已解决\" → \"已修复\" - \"不是 bug/设计如此\" → \"非问题,设计如此\" - 无明确结论 → \"暂未排查到根因\" ### 归纳格式 ```markdown ### 问题 N",
- "recallCount": 1,
+ "recallCount": 4,
"dailyCount": 0,
"groundedCount": 0,
- "totalScore": 1,
+ "totalScore": 4,
"maxScore": 1,
"firstRecalledAt": "2026-05-06T13:30:08.593Z",
- "lastRecalledAt": "2026-05-06T13:30:08.593Z",
+ "lastRecalledAt": "2026-05-07T02:55:43.649Z",
"queryHashes": [
- "f865295b9ac7"
+ "f865295b9ac7",
+ "cd9c89262c30",
+ "ac7fd0b52a4e",
+ "49c0959dc960"
],
"recallDays": [
- "2026-05-06"
+ "2026-05-06",
+ "2026-05-07"
],
"conceptTags": [
"quote-message-id",
@@ -106,18 +116,22 @@
"endLine": 166,
"source": "memory",
"snippet": "- \"日志上传/排查/查\" → \"日志已上传,排查中\" - \"确认/确实\" → \"已确认,待修复\" - \"已修复/已解决\" → \"已修复\" - \"不是 bug/设计如此\" → \"非问题,设计如此\" - 无明确结论 → \"暂未排查到根因\" ### 归纳格式 ```markdown ### 问题 N > **在{端}端{环节}内({课程}),{角色/组件}出现了{现象}** | 发言人 | 要点 | |--------|------| | 报告人 | 🚩 报告:... | | ... | ... | | 最终人 | ✅ 结论/待排查 | ``` ### 维度提取规则 | 维度 | 优先级/来源 | |------|------------| | 端 | iOS > iPad > pad端 > Android > 移动端 > PC(正则匹配,忽略大小写) | | 环节 | 关卡内/知识巩固/单元挑战/听力挑战/阅读挑战/口语挑战/写作挑战/单元强化/瓦拉学院/报告(从消息文本匹配) | | 课程 | 匹配数字编号(如 11-2、L1 3-2) | | 角色/组件 | NPC/HUD/音频/组件/数据/Loading/加载/日志(从消息文本匹配) | | 现象 | 从消息中提取要害描述,截断在 35 字符以内 | ### 现象提取逻辑 1. 优先从包含 \"Bug的表现是这样的:\"、\"问题是\"、\"发现\"、\"出现\" 等关键词的消息中截取描述句 2. 提取的句子去除 URL、图片标记、疑问句 3. 截断到 35 字符防止过长 ### Bug 修复记录",
- "recallCount": 1,
+ "recallCount": 4,
"dailyCount": 0,
"groundedCount": 0,
- "totalScore": 1,
+ "totalScore": 4,
"maxScore": 1,
"firstRecalledAt": "2026-05-06T13:30:08.593Z",
- "lastRecalledAt": "2026-05-06T13:30:08.593Z",
+ "lastRecalledAt": "2026-05-07T02:55:43.649Z",
"queryHashes": [
- "f865295b9ac7"
+ "f865295b9ac7",
+ "cd9c89262c30",
+ "ac7fd0b52a4e",
+ "49c0959dc960"
],
"recallDays": [
- "2026-05-06"
+ "2026-05-06",
+ "2026-05-07"
],
"conceptTags": [
"日志上传/排查/查",
@@ -137,18 +151,22 @@
"endLine": 205,
"source": "memory",
"snippet": "- iOS 的两个相关话题(组件无音频 / Loading 慢)因无引用关系而分成两个簇(需策略3语义聚类解决) - 单消息簇被跳过(需至少 2 条消息才能形成问题) ### Skill 文件最终状态 - `skills/feishu-feedback-sync/SKILL.md`:已包含完整步骤1-4的文档 - `skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py`:已集成 `summarize_cluster()`、`extract_location_elements()`、`generate_summary()` 函数 - crontab 每日 10:00 执行(与步骤3一起) ### 步骤4 架构调整:AI 归纳取代规则生成 [刘新玉] - 2026-04-30 19:07 #### 问题 脚本规则匹配生成的问题描述质量差: - 组件匹配失败(NPC/HUD → \"未知组件\") - 现象摘取了完整原始消息(含 @、无关词) - 端识别不稳定 #### 决策 **脚本输出结构化元数据 + 对话表,AI 负责归纳描述。** - 脚本 `summarize_cluster` 改为输出: 1. 位置元数据(端/环节/课程/组件)— 由 `extract_location_elements` 提取 2. 发言人-要点表格(规则生成) 3. 问题描述留 `[AI归纳]` 占位符 - 运行时 AI(即助手本身)根据元数据 + 对话上下文,生成精炼的问题描述 #### AI 归纳的最终输出格式(固",
- "recallCount": 1,
+ "recallCount": 4,
"dailyCount": 0,
"groundedCount": 0,
- "totalScore": 1,
+ "totalScore": 4,
"maxScore": 1,
"firstRecalledAt": "2026-05-06T13:30:08.593Z",
- "lastRecalledAt": "2026-05-06T13:30:08.593Z",
+ "lastRecalledAt": "2026-05-07T02:55:43.649Z",
"queryHashes": [
- "f865295b9ac7"
+ "f865295b9ac7",
+ "cd9c89262c30",
+ "ac7fd0b52a4e",
+ "49c0959dc960"
],
"recallDays": [
- "2026-05-06"
+ "2026-05-06",
+ "2026-05-07"
],
"conceptTags": [
"已包含完整步骤1-4的文档",
@@ -160,6 +178,72 @@
"发言人-要点表格",
"ios"
]
+ },
+ "memory:memory/2026-05-06.md:61:86": {
+ "key": "memory:memory/2026-05-06.md:61:86",
+ "path": "memory/2026-05-06.md",
+ "startLine": 61,
+ "endLine": 86,
+ "source": "memory",
+ "snippet": "- `generate_summary()` 调用 `compute_final_priority()` + `sort_by_priority()` 排序 - 新增 `--skip-priority` CLI 参数 - 修复了推断引用算法的孤立簇问题:在 sort_threads Union-Find 后增加合并单条孤立消息到有发送者重叠的大簇的逻辑 #### 3. 更新 SKILL.md 文档 - 增加了步骤5的完整文档说明 - 增加了优先级判定规则速查表 #### 4. 真实数据验证结果 - 2026-04-28 数据:2个问题 - P0:iOS端Loading超时致数据丢失/无音频(15条) - P1:移动端NPC HUD偶尔变成一小条(8条) #### 5. 刘新玉要求简化文档格式(~11:46) - 反馈文档太繁琐,只要在原有格式把\"问题 1\"改成\"P0-问题 1\" - 去掉了优先级分布汇总、额外信息行,只保留标题前缀 + 一行判定依据 - 最终格式:`### P0-问题 1` + `**优先级判定:** 规则...` - 知识库文档已更新为简洁版 #### 6. 修复推断引用算法 Bug - 策略2的 else 分支(同发送者无引用时往前找不同发送者)缺少时间限制 - 导致胡陈辰 20:45 的媒体消息被推断引用到徐思清 12:29(跨8小时) - 修复:加了 `GAP_THRESHOLD_MIN` 检查 #### 7. 文档写入方式改进 - 从 `insert_before` + `replace_range` 改为 `append` 模式",
+ "recallCount": 3,
+ "dailyCount": 0,
+ "groundedCount": 0,
+ "totalScore": 3,
+ "maxScore": 1,
+ "firstRecalledAt": "2026-05-07T02:22:47.713Z",
+ "lastRecalledAt": "2026-05-07T02:55:43.649Z",
+ "queryHashes": [
+ "cd9c89262c30",
+ "ac7fd0b52a4e",
+ "49c0959dc960"
+ ],
+ "recallDays": [
+ "2026-05-07"
+ ],
+ "conceptTags": [
+ "generate-summary",
+ "compute-final-priority",
+ "sort-by-priority",
+ "skip-priority",
+ "sort-threads",
+ "union-find",
+ "skill.md",
+ "ios端loading超时致数据丢失/无音频"
+ ]
+ },
+ "memory:memory/2026-04-30.md:73:102": {
+ "key": "memory:memory/2026-04-30.md:73:102",
+ "path": "memory/2026-04-30.md",
+ "startLine": 73,
+ "endLine": 102,
+ "source": "memory",
+ "snippet": "### 飞书问题反馈按引用关系重新排序 [刘新玉] 要求按问题完整解决过程排序——通过 `quote_message_id` 串联同一问题的讨论链。 #### 排序逻辑 1. 从数据库读取全部消息及引用关系 2. 构建引用图:每个消息的 `quote_message_id` 指向其父消息 3. 聚合问题链(cluster):同一引用链的消息归为一组,连续排列 4. 同 cluster 内按时间排序,子回复紧跟父消息 5. Cluster 间按最早时间排序 6. 无引用关系的独立消息按时间线补充 #### 处理过程 - 写入前先通过 `lark-cli sheets +write` 清空 sheet(`--raw-data=\"[]\"`) - 4/28 23条 → 生成完整引用链排序,写入 - 4/29 2条 → 无引用关系,直接写入 #### 4/28 问题链总结 | 问题 | 涉及人 | 消息数 | |------|--------|--------| | NPC HUD显示bug(仅移动端) | 徐思清→王胤鑫 | 3 | | 关卡出现规律 | 王胤鑫→庞鸿潇→梁晨 | 4 | | Playtesting数据记录 | 孙时敏 | 1 | | iOS组件无音频+Loading慢/数据丢失 | 胡陈辰→安君仪/毋益飞/王胤鑫 | 11 | | 网络问题(4/29) | Ann | 2 | ### 飞书群 4/25-4/27 数据查询结果 - 查询 MySQL `lark_group_message` 2026-04-25 ~ 2026-04-27 数据 - 结果:0 条,",
+ "recallCount": 3,
+ "dailyCount": 0,
+ "groundedCount": 0,
+ "totalScore": 3,
+ "maxScore": 1,
+ "firstRecalledAt": "2026-05-07T02:22:47.713Z",
+ "lastRecalledAt": "2026-05-07T02:55:43.649Z",
+ "queryHashes": [
+ "cd9c89262c30",
+ "ac7fd0b52a4e",
+ "49c0959dc960"
+ ],
+ "recallDays": [
+ "2026-05-07"
+ ],
+ "conceptTags": [
+ "网络",
+ "quote-message-id",
+ "lark-cli",
+ "raw-data",
+ "4/28",
+ "4/29",
+ "loading慢/数据丢失",
+ "安君仪/毋益飞/王胤鑫"
+ ]
}
}
}
diff --git a/memory/2026-05-07-2032.md b/memory/2026-05-07-2032.md
new file mode 100644
index 0000000..2081902
--- /dev/null
+++ b/memory/2026-05-07-2032.md
@@ -0,0 +1,12 @@
+# Session: 2026-05-07 20:32:56 GMT+8
+
+- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880
+- **Session ID**: 4d87bbc1-5d38-4c8c-bf62-555c32351d24
+- **Source**: feishu
+
+## Conversation Summary
+
+user: (continue)
+assistant: 最新一期看完了。最近几期都挺有意思的,Gemini 3 的 agent 能力确实让人印象深刻,那个"自己开浏览器去购物"的演示挺震撼。Claude 被 Gemini 压得有点狠,不过 Opus 4.6 如果能按时出应该能扳回一局。你对哪块最感兴趣?
+user: 你好
+assistant: 若松好。今天的工作日志里记录了不少刘新玉那边的变更——反馈文档结构调整、问题分类规则、消息分发到「小葵小葵」群都落地了。有什么需要处理的?
diff --git a/memory/2026-05-07-2049.md b/memory/2026-05-07-2049.md
new file mode 100644
index 0000000..2dea937
--- /dev/null
+++ b/memory/2026-05-07-2049.md
@@ -0,0 +1,44 @@
+# Session: 2026-05-07 20:49:03 GMT+8
+
+- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880
+- **Session ID**: 7ab6e9db-9453-4c3b-8667-87b587bfe6a3
+- **Source**: feishu
+
+## Conversation Summary
+
+assistant: 创建成功,让我验证一下文档是否在正确的位置。
+assistant: 已在「小葵」节点下成功创建子文档 **研发调试**。
+
+- **父节点:** 小葵 (`Ih0VwOhd4io22Pkm3fGcTHb6nRg`)
+- **新文档:** 研发调试
+- **链接:** https://makee-interactive.feishu.cn/wiki/RnUPwsSYKiQjYAkLQqyciI81nLc
+- **空间:** `7612229802338045122`
+user: 好的 现在在文档中 再追加一句话 "你好明天"
+assistant: 已追加。文档链接:https://makee-interactive.feishu.cn/wiki/RnUPwsSYKiQjYAkLQqyciI81nLc
+user: 好的 现在尝试 删除刚才追加的这句话
+assistant: 验证一下:
+assistant: 已删除"你好明天",文档恢复为只保留标题和入口说明。链接不变:https://makee-interactive.feishu.cn/wiki/RnUPwsSYKiQjYAkLQqyciI81nLc
+user: 好的 现在尝试删除这个文档
+assistant: Bot 应用缺少 `wiki:node:create` 权限,无法删除知识库节点。需要在飞书开发者后台给小葵应用开通此权限:
+
+**操作步骤:**
+1. 打开:https://open.feishu.cn/app/cli_a9311791083adcc1/auth?q=wiki:node:create
+2. 开通 `wiki:node:create` 权限
+3. 开通后告诉我,我继续执行删除
+
+这是飞书知识库 API 的设计,删除节点需要 `wiki:node:create` 这个 scope。
+user: 已开通 再次尝试
+assistant: `obj_type=wiki` 成功了!删除是异步任务。让我验证一下结果。
+assistant: 已删除。「研发调试」文档已从知识库中移除,验证结果:
+
+- 节点查询返回 `not found` ✅
+- 父节点「小葵」下只剩原来的两个文档 ✅
+
+关键发现:删除知识库节点时,`obj_type` 需传 `wiki`(而非 `docx`),这是一个异步任务,飞书返回了 `task_id` 确认已处理。
+user: 删除知识库节点时,obj_type 需传 wiki(而非 docx),这是一个异步任务 这个信息 是否已经记录在 /root/.openclaw/skills/lark_wiki_operate_as_bot 中?
+assistant: 没有记录。该技能目前只覆盖了**读取/遍历**操作,未涉及创建和删除。我现在把删除操作的关键发现补充进去。
+assistant: 已补充。更新内容:
+
+- **适用场景** 增加了"删除知识库节点"和"创建知识库文档"
+- **新增步骤5:删除知识库节点** — 记录了完整命令、`obj_type` 必须传 `wiki` 的关键发现、异步任务机制、以及验证方法
+- **权限表** 增加了 `wiki:node:create` 读写权限
diff --git a/memory/2026-05-07-2051.md b/memory/2026-05-07-2051.md
new file mode 100644
index 0000000..6c359c2
--- /dev/null
+++ b/memory/2026-05-07-2051.md
@@ -0,0 +1,29 @@
+# Session: 2026-05-07 20:51:44 GMT+8
+
+- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880
+- **Session ID**: fbadd4ba-035c-4aaa-a673-e7ab49d2b411
+- **Source**: feishu
+
+## Conversation Summary
+
+user: 测试下 https://makee-interactive.feishu.cn/wiki/Ih0VwOhd4io22Pkm3fGcTHb6nRg?fromScene=spaceOverview 在这个节点下 新建一个 子文档 "研发调试"
+assistant: 好的,我先获取该节点信息,然后在其下创建子文档"研发调试"。
+assistant: 需要先绑定配置。让我查一下绑定方式。
+assistant: 需要先绑定 OpenClaw 上下文。让我查看绑定方式后执行。
+assistant: 需要先绑定 lark-cli 到 OpenClaw 上下文。我取一下 app-id:
+assistant: `lark-cli` 尚未绑定 OpenClaw 上下文,需要先做一次性绑定。绑定后所有 Wiki 操作将以 Bot 身份执行(`bot-only`,不触发用户授权),符合我们的安全规范。
+
+确认绑定吗?
+user: 好‘
+assistant: 绑定成功。现在获取目标节点信息,然后创建子文档。
+assistant: 节点信息已获取。在「小葵」目录下创建子文档「研发调试」:
+assistant: ✅ 创建成功!
+
+**「研发调试」** 文档已创建在「小葵」节点下:
+
+| 项目 | 值 |
+|------|-----|
+| 文档标题 | 研发调试 |
+| Wiki 链接 | https://makee-interactive.feishu.cn/wiki/KSUpwNEMKiyjbiklSsIc2YC2n2D |
+| obj_token | `SrCTdxan4oBad4xoQiXcdIKHnNh` |
+| 父节点 | 小葵 |
diff --git a/memory/2026-05-07-feishu-group-test.md b/memory/2026-05-07-feishu-group-test.md
new file mode 100644
index 0000000..ad1afe7
--- /dev/null
+++ b/memory/2026-05-07-feishu-group-test.md
@@ -0,0 +1,43 @@
+# Session: 2026-05-07 18:25:53 GMT+8
+
+- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880
+- **Session ID**: 76c1e3aa-0a11-45dc-8eaa-bf12193fa334
+- **Source**: feishu
+
+## Conversation Summary
+
+assistant: 我来查一下之前的对话记录,看看发生了什么。
+assistant: 让我进一步搜索关于"小葵小葵"群的具体对话记录,以及和刘新玉关于群的沟通。
+assistant: 没有找到关于"小葵小葵"这个具体群名的记录。让我搜索最近的日记忆文件和刘新玉相关的对话。
+assistant: 我没有找到和刘新玉关于"小葵小葵"这个群的直接对话。让我看看最近的记忆,以及查一下刘新玉最近和我的对话记录。
+assistant: 我在最近的记忆中没有发现和刘新玉关于"小葵小葵"群的对话记录。让我直接通过飞书 API 来确认当前 Bot 是否在"小葵小葵"群里。
+assistant: 这走的是用户身份授权。让我用 Bot 身份来查询。
+assistant: 好,让我用 Bot 身份来搜索"小葵小葵"群。
+assistant: 结果很清楚:**小葵Bot确实已经在"小葵小葵"群里**,`chat_id` 为 `oc_4171a2188f2554522a4309f2d7c27753`。
+
+你说得对,这是我的问题。回顾一下:
+
+**事实上**"小葵小葵"群(`oc_4171a2188f2554522a4309f2d7c27753`)一直在小葵Bot的群列表中,Bot确实可以往这个群里发消息。
+
+**我之前和刘新玉说的"Bot 不在群里"**,那指的是「内容测试问题反馈」群(`oc_fabff7672e62a9ced7b326ee4a286c26`)——当时(4月10日-20日期间)那个群 Bot 确实没加入,后来应该已经加上了。但我在表述时可能没有区分清楚,让刘新玉误以为我在所有群都不在,包括"小葵小葵"群。
+
+这是我的疏忽——我应该明确说明"不在**特定群**"而不是笼统说"不在群里"。同一个 Bot 在不同群的加入状态是不同的,不能混为一谈。
+
+已经验证确认:小葵Bot 在"小葵小葵"群(`oc_4171a2188f2554522a4309f2d7c27753`)中,完全可以往里面发消息。需要我现在往这个群发什么吗?
+user: 好 现在发送一个 "测试信息"
+assistant: 已发送。✅ 「测试信息」已成功发到"小葵小葵"群(`oc_4171a2188f2554522a4309f2d7c27753`),message_id: `om_x100b50f41db41c3cb2b8bb5619e89cd`。
+user: 记住 这个群,以后相关负责人需要你往这个群里发消息时,请准确执行。
+assistant: 已记录。「小葵小葵」群 `chat_id: oc_4171a2188f2554522a4309f2d7c27753`,以后相关负责人要求往这个群发消息时,直接执行即可。
+assistant: 🔧 Bot 权限申请
+
+以下两个应用需要开通 wiki:node:create 权限:
+
+小研 (cli_a931175d41799cc7)
+https://open.feishu.cn/app/cli_a931175d41799cc7/auth?q=wiki:node:create
+
+小葵 (cli_a9311791083adcc1)
+https://open.feishu.cn/app/cli_a9311791083adcc1/auth?q=wiki:node:create
+
+原因:用户反馈问题汇总下出现重复子文档,需通过 API 删除多余节点。
+user: hi
+assistant: hi 若松,有什么需要处理的?
diff --git a/memory/2026-05-07-greeting-hi.md b/memory/2026-05-07-greeting-hi.md
new file mode 100644
index 0000000..b197919
--- /dev/null
+++ b/memory/2026-05-07-greeting-hi.md
@@ -0,0 +1,18 @@
+# Session: 2026-05-07 19:38:30 GMT+8
+
+- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880
+- **Session ID**: 650e0d77-aad3-48d3-ad3b-1bef33d439a2
+- **Source**: feishu
+
+## Conversation Summary
+
+assistant: 下午好😊,我是你的数字员工小葵,有什么需要协助处理的工作可以随时告诉我。
+user: hi
+assistant: 你好若松,下午好😊 有什么需要我处理的直接说~
+user: hi
+assistant: 嗨,若松~ 在呢,随时吩咐 😄
+user: hi
+user: [Thu 2026-05-07 19:28 GMT+8] [System] Your previous turn was interrupted by a gateway restart while OpenClaw was waiting on tool/model work. Continue from the existing transcript and finish the interrupted response.
+assistant: 嗨若松,我在~ 有什么需要帮忙的吗?
+user: hi
+assistant: 若松,我在呢~ 看起来你连着发了几次消息但都被打断了,有什么需要直接说就好 😄
diff --git a/memory/2026-05-07.md b/memory/2026-05-07.md
new file mode 100644
index 0000000..462e200
--- /dev/null
+++ b/memory/2026-05-07.md
@@ -0,0 +1,208 @@
+
+## 用户反馈问题汇总文档结构调整 [刘新玉] - 2026-05-07 10:45
+
+### 变更内容
+1. 「用户反馈问题汇总」文档改为按日期创建独立子文档,每天一个
+2. 子文档标题格式:`YYYY-MM-DD 问题反馈`
+3. 父文档(RaL6whoYMijyYHkSlWrc7OLLnBy)改为索引说明页
+4. 子文档 obj_token:
+ - 2026-05-06: ISpQdgf6QoIKIyxdZjPcTAa4nEe
+ - 2026-04-28: UusFdRBEioSs4ox9JhPcXGfCnzf
+
+### 脚本修改
+- `sync_feishu_feedback.py` 中新增 `update_summary_doc_as_children()` 函数
+- 逻辑:先 `list_child_nodes()` 查已有子文档 → 存在则更新、不存在才创建
+- **核心规则:每天只新增一个对应日期的子文档,绝不重复创建**
+
+### 同步清理
+- 数据库中 sender_name='未知' 的3条无效记录已删除
+- 「内容测试问题反馈」电子表格中也清理了"未知"发送者的行
+- 该电子表格已从"飞书问题反馈-近3天"重命名为"内容测试问题反馈"
+
+### 飞书群信息 [李若松确认] - 2026-05-07 11:23
+- 「小葵小葵」群 chat_id: `oc_4171a2188f2554522a4309f2d7c27753`,小葵Bot已在该群中
+- 相关负责人需要往此群发消息时,直接用 Bot 身份向该 chat_id 发送
+
+### 知识空间信息
+- space_id: 7612229802338045122
+- 父节点 node_token: RaL6whoYMijyYHkSlWrc7OLLnBy
+- 父节点 obj_token: J8bKd4dbYoofZixxVsCc06bhnFc (docx)
+
+## 用户反馈问题汇总文档结构调整 [刘新玉] - 2026-05-07 10:45
+
+### 变更内容
+1. 「用户反馈问题汇总」文档改为按日期创建独立子文档,每天一个
+2. 子文档标题格式:`YYYY-MM-DD 问题反馈`
+3. 父文档(RaL6whoYMijyYHkSlWrc7OLLnBy)改为索引说明页
+4. 子文档 obj_token:
+ - 2026-05-06: ISpQdgf6QoIKIyxdZjPcTAa4nEe
+ - 2026-04-28: UusFdRBEioSs4ox9JhPcXGfCnzf
+
+### 脚本修改
+- `sync_feishu_feedback.py` 中新增 `update_summary_doc_as_children()` 函数
+- 逻辑:先 `list_child_nodes()` 查已有子文档 → 存在则更新、不存在才创建
+- **核心规则:每天只新增一个对应日期的子文档,绝不重复创建**
+
+### 同步清理
+- 数据库中 sender_name='未知' 的3条无效记录已删除
+- 「内容测试问题反馈」电子表格中也清理了"未知"发送者的行
+- 该电子表格已从"飞书问题反馈-近3天"重命名为"内容测试问题反馈"
+
+### 飞书群信息 [李若松确认] - 2026-05-07 11:23
+- 「小葵小葵」群 chat_id: `oc_4171a2188f2554522a4309f2d7c27753`,小葵Bot已在该群中
+- 相关负责人需要往此群发消息时,直接用 Bot 身份向该 chat_id 发送
+
+### 知识空间信息
+- space_id: 7612229802338045122
+- 父节点 node_token: RaL6whoYMijyYHkSlWrc7OLLnBy
+- 父节点 obj_token: J8bKd4dbYoofZixxVsCc06bhnFc (docx)
+
+---
+
+## 今日问题归纳增加问题分类 [刘新玉] - 2026-05-07 10:55
+
+### 新增步骤6:问题分类
+在优先级判定之后,对每个问题添加分类标签。输出格式:
+```
+**⚠️ P0级核心问题(需优先处理)**
+1. **Loading/加载类**
+ - 问题描述...
+**⚡ P1级重要问题**
+1. **关卡/内容类**
+ - 问题描述...
+```
+
+### 问题分类规则(按匹配优先级从上到下)
+| 优先级 | 分类 | 匹配关键词 |
+|--------|------|-----------|
+| 1 | 启动/运行异常 | 闪退、崩溃、crash、进不去、卡死、黑屏、重启、服务器宕机、服务器挂了 |
+| 2 | 版本/更新类 | 更新、升级、新版、版本、安装失败、OTA、热更新、无法更新、下载更新 |
+| 3 | Loading/加载类 | 加载、loading、loading卡死、转星星、加载慢、加载超时、loading超时、一直加载 |
+| 4 | 数据/进度类 | 数据丢失、数据异常、进度丢失、数据错误、分数异常、进度不对、记录丢失、数据对不上 |
+| 5 | 声音/音频类 | 无声、声音、音频、没声音、音效 |
+| 6 | 语音识别/判分类 | 判分、识别、语音识别、发音、评分、打分、AI判分 |
+| 7 | 关卡/内容类 | 关卡、题目、答案、内容 |
+| 8 | UI显示类 | 显示、界面、UI、HUD、动画、层级、图层、渲染 |
+| 9 | 用户反馈问题 | 建议、反馈、体验、优化 |
+| 10 | 其他问题 | (默认兜底) |
+
+### 脚本修改
+- `priority_classifier.py` 新增 `proble m_category(keyword)` 函数和 `CATEGORY_KEYWORDS` 规则
+- `sync_feishu_feedback.py` 中 `summarize_cluster()` 新增 `category` 字段
+- `generate_summary()` 输出格式改为按优先级+分类分组
+
+---
+
+## 新增步骤7:问题分发 [刘新玉] - 2026-05-07 11:09
+
+### 需求
+将每日问题归纳同步到「小葵小葵」群,P0问题@相关负责人跟进。
+
+### 分发规则
+1. 将"今日问题归纳"内容发送到指定群(格式:标题+归纳正文+文档链接)
+2. P0问题 @相关负责人的 @列表(从 `summarize_cluster` 的 `operators` 字段提取发言人)
+
+### Bot身份问题
+- Bot应用名:**小研**(App ID: `cli_a931175d41799cc7`)
+- Bot发消息需要已经加入目标群
+- 小葵Bot在「小葵小葵」群中发消息报 500 "chat does not exist" → 可能是不同应用
+- **待解决**:需要确认"小葵小葵"群里加的是哪个应用,或者把小研Bot加进去
+
+### 脚本修改
+- `sync_feishu_feedback.py` 新增 `dispatch_to_group()` 函数
+- 新增 `--dispatch` 参数控制是否执行步骤7
+- 新增 `--dispatch-chat-id` 参数指定目标群(默认 oc_4171a2188f2554522a4309f2d7c27753)
+
+### 关键配置
+- 目标群 chat_id: `oc_4171a2188f2554522a4309f2d7c27753`
+- 毋益飞 user_id: `eggbg21g`
+- SKILL.md 已从"五步流程"更新为"七步流程"
+
+---
+
+## 当日待跟进事项
+1. 「小葵小葵」群Bot发消息报错问题 → 需确认群内有哪个Bot应用,或引入小研Bot
+
+---
+
+## 步骤7格式调整 [刘新玉] - 2026-05-07 11:40
+
+### 最终消息格式(已确认并更新到脚本和SKILL.md)
+```
+📋 2026-04-28 用户反馈问题归纳
+
+**⚠️ P0级核心问题(需优先处理)** @毋益飞
+1. **Loading/加载类**
+ - 在iOS 端关卡内(3-2),Loading 耗时约 10 秒...
+
+**⚡ P1级重要问题**
+1. **关卡/内容类**
+ - 【偶现】在移动端关卡内(11-2),NPC 头上的 HUD...
+
+📄 详细反馈文档:https://makee-interactive.feishu.cn/wiki/CQ0UwjRTZijvvEk6tSecEUTXnFg
+```
+- @逻辑:P0标题行后面直接@发言人,@列表从 `summarize_cluster` 的 `operators` 提取
+- 非P0问题不@
+
+### H5链接
+- 尝试生成公开H5链接失败,Bot无 `drive:permission` 权限
+- 当前使用飞书wiki链接,飞书App内可直接打开
+- 若需外部浏览器访问,需在知识空间设置"互联网上可查看"
+
+### 小葵Bot身份确认
+- xiaokui 凭证目录:`/root/.openclaw/credentials/xiaokui`
+- xiaoyan 凭证目录:`/root/.openclaw/credentials/xiaoyan`
+- 发「小葵小葵」群消息用 xiaokui 身份成功
+
+---
+
+## 当前定时任务清单 [刘新玉] - 2026-05-07 14:59
+
+| 时间 | 任务 |
+|------|------|
+| 每天 02:00 | vala_skill_auto_push.sh(技能推送) |
+| 每天 08:00-22:00 每2小时 | run_lark_group_sync.sh(反馈群消息同步到数据库) |
+| 每天 08:10 | backup.sh(工作区Git备份) |
+| 每分钟 | sync_wechat_feedback_minutely.py(微信用户反馈实时同步) |
+| 每天 09:30 | daily_feedback_report.sh(每日反馈报告) |
+| 每天 09:00 | run_export_lark_feedback.sh(飞书反馈数据导出) |
+| **每天 10:00** | **sync_feishu_feedback_wrapper.sh(飞书问题反馈同步,含7步+分发到群)** |
+
+---
+
+## 定时任务演化记录 [刘新玉] - 2026-05-07 15:03~15:56
+
+### 已移除的任务
+- `sync_wechat_feedback_minutely.py`(微信用户反馈实时同步)— 已删除
+- `daily_feedback_report.sh`(每日反馈报告)— 已删除
+
+### 最终定时任务清单(2026-05-07 15:56)
+
+| 频率 | 脚本 | 步骤 | 说明 |
+|------|------|------|------|
+| 每天 02:00 | `vala_skill_auto_push.sh` | — | 技能推送到 SkillHub |
+| 每分钟 | `run_lark_group_sync.sh` | — | 群消息同步到数据库 |
+| 每天 08:10 | `backup.sh` | — | Git 工作区备份 |
+| 每分钟 | `run_export_lark_feedback.sh` | — | 当天数据实时导出 Excel |
+| 每分钟 | `sync_feishu_feedback_realtime.sh` | 1-3 | 实时写入电子表格 |
+| 每分钟 | `sync_feishu_feedback_summary.sh` | 4-6 | 归纳+分类 → 子文档 |
+| 每分钟 | `sync_feishu_feedback_dispatch_p0.sh` | 7(仅P0) | P0问题实时分发到群 |
+| 每天 10:00 | `sync_feishu_feedback_wrapper.sh` | 7(全部) | 全量分发到群 |
+
+### 完整数据流
+```
+群消息 → 每1分钟入MySQL → 每1分钟刷新表格 → 每1分钟归纳+分类 → P0实时发群 / 每天10:00全量发群
+```
+
+### 关键技术细节
+- **拆分方式**:`sync_feishu_feedback.py` 新增 `--steps` 参数(如 `--steps 1-3`、`--steps 4-6`、`--steps 7`)
+- **分发模式**:新增 `--dispatch-mode` 参数,`p0` 只发P0级,`all` 发全部
+- **电子表格**:`TVivwmzqXiW3YakDUzucFMRenvf`("内容测试问题反馈")
+- **归纳子文档父节点**:`RaL6whoYMijyYHkSlWrc7OLLnBy`(space_id: 7612229802338045122)
+- **分发目标群**:`oc_4171a2188f2554522a4309f2d7c27753`(「小葵小葵」群)
+- **分发Bot**:xiaokui(`/root/.openclaw/credentials/xiaokui`)
+- **新 wrapper 脚本**:
+ - `scripts/sync_feishu_feedback_realtime.sh`(步骤1-3)
+ - `scripts/sync_feishu_feedback_summary.sh`(步骤4-6)
+ - `scripts/sync_feishu_feedback_dispatch_p0.sh`(步骤7 P0)
+ - `scripts/sync_feishu_feedback_wrapper.sh`(步骤7 全量,每天10:00)
diff --git a/output/daily_feedback/飞书反馈_2026-05-06.xlsx b/output/daily_feedback/飞书反馈_2026-05-06.xlsx
new file mode 100644
index 0000000..a80eded
Binary files /dev/null and b/output/daily_feedback/飞书反馈_2026-05-06.xlsx differ
diff --git a/output/daily_feedback/飞书反馈_2026-05-07.xlsx b/output/daily_feedback/飞书反馈_2026-05-07.xlsx
new file mode 100644
index 0000000..25917b7
Binary files /dev/null and b/output/daily_feedback/飞书反馈_2026-05-07.xlsx differ
diff --git a/scripts/export_lark_feedback_to_wiki.py b/scripts/export_lark_feedback_to_wiki.py
index 7b88de9..7ba5908 100644
--- a/scripts/export_lark_feedback_to_wiki.py
+++ b/scripts/export_lark_feedback_to_wiki.py
@@ -1,11 +1,11 @@
#!/usr/bin/env python3
"""
-飞书反馈数据每日导出 Excel 并上传到知识库
-- 从 MySQL vala_test.lark_group_message 表导出前一天新增数据
+飞书反馈数据实时导出 Excel 并上传到知识库
+- 从 MySQL vala_test.lark_group_message 表导出当天数据
- 生成 Excel 文件
- 通过 Bot 身份上传到飞书知识库指定目录下
-定时任务:每天 09:00 执行
+定时任务:每 5 分钟执行一次
"""
import os
import sys
@@ -75,13 +75,13 @@ def get_db_connection():
)
-def query_yesterday_data():
- """查询前一天的飞书反馈数据"""
+def query_today_data():
+ """查询当天的飞书反馈数据"""
now = datetime.now(TZ)
- yesterday_start = (now - timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0)
- yesterday_end = yesterday_start + timedelta(days=1)
+ today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
+ today_end = today_start + timedelta(days=1)
- logger.info(f"查询时间范围: {yesterday_start.strftime('%Y-%m-%d %H:%M:%S')} ~ {yesterday_end.strftime('%Y-%m-%d %H:%M:%S')}")
+ logger.info(f"查询时间范围: {today_start.strftime('%Y-%m-%d %H:%M:%S')} ~ {today_end.strftime('%Y-%m-%d %H:%M:%S')}")
conn = get_db_connection()
try:
@@ -96,12 +96,12 @@ def query_yesterday_data():
ORDER BY msg_timestamp ASC
"""
cursor.execute(sql, (
- yesterday_start.strftime("%Y-%m-%d %H:%M:%S"),
- yesterday_end.strftime("%Y-%m-%d %H:%M:%S")
+ today_start.strftime("%Y-%m-%d %H:%M:%S"),
+ today_end.strftime("%Y-%m-%d %H:%M:%S")
))
rows = cursor.fetchall()
logger.info(f"查询到 {len(rows)} 条记录")
- return rows, yesterday_start
+ return rows, today_start
finally:
conn.close()
@@ -336,11 +336,11 @@ def main():
try:
# 1. 查询前一天数据
- rows, date_obj = query_yesterday_data()
+ rows, date_obj = query_today_data()
# 2. 判断是否有有效数据
if not rows:
- logger.info("前一天无新增数据,跳过导出")
+ logger.info("当天尚无数据,跳过导出")
return
# 3. 生成 Excel
@@ -355,7 +355,7 @@ def main():
# 6. 发送成功通知
date_str = date_obj.strftime("%Y-%m-%d")
send_notification(True,
- f"📊 飞书反馈日报导出成功\n"
+ f"📊 飞书反馈实时导出成功\n"
f"日期:{date_str}\n"
f"记录数:{len(rows)} 条\n"
f"文件:{wiki_url}"
diff --git a/scripts/run_export_lark_feedback.sh b/scripts/run_export_lark_feedback.sh
index 7dd2bed..a621218 100755
--- a/scripts/run_export_lark_feedback.sh
+++ b/scripts/run_export_lark_feedback.sh
@@ -1,7 +1,7 @@
#!/bin/bash
-# 飞书反馈数据每日导出到知识库
-# 定时任务:每天 09:00 执行
-# 从 MySQL lark_group_message 表导出前一天新增数据为 Excel,上传到飞书知识库
+# 飞书反馈数据实时导出到知识库
+# 定时任务:每 5 分钟执行
+# 从 MySQL lark_group_message 表导出当天数据为 Excel,上传到飞书知识库
set -e
diff --git a/scripts/sync_feishu_feedback_dispatch_p0.sh b/scripts/sync_feishu_feedback_dispatch_p0.sh
new file mode 100755
index 0000000..676908f
--- /dev/null
+++ b/scripts/sync_feishu_feedback_dispatch_p0.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# 任务名称:飞书问题反馈 P0 实时分发到群(步骤7,仅P0)
+# 执行时间:每分钟
+# 归属 Agent:小葵 xiaokui
+
+set -e
+
+export PATH=/root/.nvm/versions/node/v24.14.0/bin:$PATH
+LOG_FILE="/var/log/xiaokui_feedback_dispatch_p0.log"
+
+log() {
+ echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
+}
+
+log "=== P0 实时分发开始 ==="
+
+cd /root/.openclaw/workspace-xiaokui
+python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 1 --steps 7 --dispatch-mode p0 >> "$LOG_FILE" 2>&1
+
+log "=== P0 实时分发结束 ==="
+exit 0
diff --git a/scripts/sync_feishu_feedback_realtime.sh b/scripts/sync_feishu_feedback_realtime.sh
new file mode 100755
index 0000000..1272056
--- /dev/null
+++ b/scripts/sync_feishu_feedback_realtime.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# 任务名称:飞书问题反馈实时同步(步骤1-3:写入电子表格)
+# 执行时间:每 5 分钟
+# 归属 Agent:小葵 xiaokui
+
+set -e
+
+export PATH=/root/.nvm/versions/node/v24.14.0/bin:$PATH
+LOG_FILE="/var/log/xiaokui_feedback_realtime.log"
+
+log() {
+ echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
+}
+
+log "=== 实时同步开始 ==="
+
+cd /root/.openclaw/workspace-xiaokui
+python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 3 --steps 1-3 >> "$LOG_FILE" 2>&1
+
+log "=== 实时同步结束 ==="
+exit 0
diff --git a/scripts/sync_feishu_feedback_summary.sh b/scripts/sync_feishu_feedback_summary.sh
new file mode 100755
index 0000000..43f22d3
--- /dev/null
+++ b/scripts/sync_feishu_feedback_summary.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# 任务名称:飞书问题反馈归纳与分类(步骤4-6)
+# 执行时间:每分钟
+# 归属 Agent:小葵 xiaokui
+
+set -e
+
+export PATH=/root/.nvm/versions/node/v24.14.0/bin:$PATH
+LOG_FILE="/var/log/xiaokui_feedback_summary.log"
+
+log() {
+ echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
+}
+
+log "=== 归纳与分类开始 ==="
+
+cd /root/.openclaw/workspace-xiaokui
+python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 1 --steps 4-6 --skip-dispatch >> "$LOG_FILE" 2>&1
+
+log "=== 归纳与分类结束 ==="
+exit 0
diff --git a/scripts/sync_feishu_feedback_wrapper.sh b/scripts/sync_feishu_feedback_wrapper.sh
index 058e9f1..f6c3730 100755
--- a/scripts/sync_feishu_feedback_wrapper.sh
+++ b/scripts/sync_feishu_feedback_wrapper.sh
@@ -1,21 +1,21 @@
#!/bin/bash
-# 任务名称:飞书问题反馈同步与对话链排序
+# 任务名称:飞书问题反馈每日全量分发(步骤7,全部问题)
# 执行时间:每天 10:00
# 归属 Agent:小葵 xiaokui
set -e
export PATH=/root/.nvm/versions/node/v24.14.0/bin:$PATH
-LOG_FILE="/var/log/xiaokui_feedback_sync.log"
+LOG_FILE="/var/log/xiaokui_feedback_dispatch_daily.log"
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
-log "=== 飞书问题反馈同步开始 ==="
+log "=== 每日全量分发开始 ==="
cd /root/.openclaw/workspace-xiaokui
-python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 3 >> "$LOG_FILE" 2>&1
+python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 1 --steps 7 --dispatch-mode all >> "$LOG_FILE" 2>&1
-log "=== 同步完成 ==="
+log "=== 每日全量分发结束 ==="
exit 0
diff --git a/skills/feishu-feedback-sync/SKILL.md b/skills/feishu-feedback-sync/SKILL.md
index fcdb945..68a881d 100644
--- a/skills/feishu-feedback-sync/SKILL.md
+++ b/skills/feishu-feedback-sync/SKILL.md
@@ -1,39 +1,41 @@
---
name: feishu-feedback-sync
-description: 同步飞书「内容测试问题反馈」群消息到知识库电子表格并执行对话链排序。用于:(1) 刘新玉说"同步飞书反馈"、"更新飞书问题反馈表格"、"整理反馈对话链"时触发;(2) 定时任务每日自动同步。数据源为 MySQL vala_test.lark_group_message,目标为知识库飞书问题反馈-近3天表格。含五步完整流程:数据同步 → 写入表格 → 对话链排序 → 问题归纳 → 优先级判定排序。
+description: 同步飞书「内容测试问题反馈」群消息到知识库电子表格并执行对话链排序。用于:(1) 刘新玉说"同步飞书反馈"、"更新飞书问题反馈表格"、"整理反馈对话链"时触发;(2) 定时任务每日自动同步。数据源为 MySQL vala_test.lark_group_message,目标为知识库内容测试问题反馈表格。含七步完整流程:数据同步 → 写入表格 → 对话链排序 → 问题归纳 → 优先级判定排序 → 问题分类 → 问题分发。
---
-# 飞书问题反馈同步(五步完整流程)
+# 飞书问题反馈同步(七步完整流程)
## 概述
-从 MySQL `vala_test.lark_group_message` 读取飞书群消息,执行五步完整处理流程。
+从 MySQL `vala_test.lark_group_message` 读取飞书群消息,执行七步完整处理流程。
-### 五步流程总览
+### 七步流程总览
-| 步骤 | 名称 | 目标文档 | 产出 |
+| 步骤 | 名称 | 目标文档/群 | 产出 |
|------|------|---------|------|
| 步骤 1 | 查询数据库 | — | 原始消息数据 |
| 步骤 2 | 写入飞书表格 | `AHtnsehwShUVyDtjasSciIvgn7b` | 按天分 sheet 的原始数据 |
| 步骤 3 | 反馈对话链排序 | `AHtnsehwShUVyDtjasSciIvgn7b` | 已排序的问题簇 |
-| 步骤 4 | 问题归纳 | `RaL6whoYMijyYHkSlWrc7OLLnBy` | 结构化问题描述+对话表格+结论 |
-| 步骤 5 | 优先级判定与排序 | `RaL6whoYMijyYHkSlWrc7OLLnBy` | 按 P0>P1>P2>P3 排序的问题列表 |
+| 步骤 4 | 问题归纳 | `RaL6whoYMijyYHkSlWrc7OLLnBy`(子文档) | 结构化问题描述+对话表格+结论 |
+| 步骤 5 | 优先级判定与排序 | `RaL6whoYMijyYHkSlWrc7OLLnBy`(子文档) | 按 P0>P1>P2>P3 排序的问题列表 |
+| 步骤 6 | 问题分类 | `RaL6whoYMijyYHkSlWrc7OLLnBy`(子文档) | 按优先级+分类展示的问题列表 |
+| 步骤 7 | 问题分发 | 「小葵小葵」群 `oc_4171a2188f2554522a4309f2d7c27753` | P0问题@通知到群 |
## 关键标识
| 项目 | 值 |
|------|-----|
-| 数据库 | MySQL `bj-cdb-8frbdwju.sql.tencentcdb.com:25413`,user `chatbot`,密码 `xhuBx7d@uT2gUVv`,database `vala_test` |
+| 数据库 | MySQL `bj-cdb-8frbdwju.sql.tencentcdb.com:25413`,user `chatbot`,密码 `xhuBx7d@uT2gUVv`,database `vala_test` |
| 源表 | `lark_group_message` |
-| 目标表格 token | `AHtnsehwShUVyDtjasSciIvgn7b`(步骤1-3:原始数据整理) |
-| 目标归纳文档 token | `RaL6whoYMijyYHkSlWrc7OLLnBy`(步骤4:问题归纳输出) |
+| 目标表格 token | `AHtnsehwShUVyDtjasSciIvgn7b`(步骤1-3:原始数据整理) |
+| 目标归纳文档 token | `RaL6whoYMijyYHkSlWrc7OLLnBy`(步骤4:问题归纳输出) |
| 目标知识库节点 | `TVivwmzqXiW3YakDUzucFMRenvf` |
| 知识空间 space_id | `7612229802338045122` |
| 群 chat_id | `oc_fabff7672e62a9ced7b326ee4a286c26` |
| Bot App ID | `cli_a9311791083adcc1` |
| Bot App Secret | `ThhLL1I0F2AIKnSbpozKnhm40LTPfyap` |
-## 表格字段(与数据库一致)
+## 表格字段(与数据库一致)
| 列 | 数据库字段 |
|----|-----------|
@@ -48,7 +50,7 @@ description: 同步飞书「内容测试问题反馈」群消息到知识库电
## 执行流程
-### 步骤 1:查询数据库
+### 步骤 1:查询数据库
```sql
SELECT message_id, sender_name, msg_type, content, media_url, quote_message_id,
@@ -58,23 +60,23 @@ WHERE msg_time >= '{date} 00:00:00' AND msg_time < '{next_date} 00:00:00'
ORDER BY msg_time ASC
```
-默认同步最近 3 天的数据。如果表格已有当天 sheet,则追加新数据(去重写入,按 message_id 去重);如无则创建新 sheet。
+默认同步最近 3 天的数据。如果表格已有当天 sheet,则追加新数据(去重写入,按 message_id 去重);如无则创建新 sheet。
-### 步骤 2:写入飞书表格
+### 步骤 2:写入飞书表格
-使用 `lark-cli sheets +write`(Bot 身份)批量写入:
-- 按天分 sheet(sheet 名为日期,如 `2026-04-28`)
+使用 `lark-cli sheets +write`(Bot 身份)批量写入:
+- 按天分 sheet(sheet 名为日期,如 `2026-04-28`)
- 表头固定为 8 列
-- 每 sheet 最多一次写入(或分批,不超过 500 行/批)
+- 每 sheet 最多一次写入(或分批,不超过 500 行/批)
-**凭证环境:**
+**凭证环境:**
```bash
export PATH=/root/.nvm/versions/node/v24.14.0/bin:$PATH
export LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/xiaokui
export HOME=/root
```
-**写入命令格式:**
+**写入命令格式:**
```bash
lark-cli sheets +write \
--spreadsheet-token AHtnsehwShUVyDtjasSciIvgn7b \
@@ -83,51 +85,51 @@ lark-cli sheets +write \
--as bot
```
-### 步骤 3:反馈对话链排序
+### 步骤 3:反馈对话链排序
-对每个 sheet 中的数据执行引用链排序(详见下文排序逻辑),使每个问题的完整讨论过程在表格中连续呈现。
+对每个 sheet 中的数据执行引用链排序(详见下文排序逻辑),使每个问题的完整讨论过程在表格中连续呈现。
## 反馈对话链排序逻辑
### 两阶段排序
-#### 阶段 A:推断缺失引用(策略2)
+#### 阶段 A:推断缺失引用(策略2)
-由于飞书群消息同步时仅采集了 `quote_message_id`(显式引用),大量通过飞书「直接回复」功能产生的消息没有引用关系。策略2通过启发式规则补全:
+由于飞书群消息同步时仅采集了 `quote_message_id`(显式引用),大量通过飞书「直接回复」功能产生的消息没有引用关系。策略2通过启发式规则补全:
-1. **@提及匹配**(最高优先级):消息中 `@某人` → 关联到被@者最近一条消息
-2. **同发送者聚类**:同一发送者在 2 分钟窗口内连续发多条消息 → 认为是对同一目标的回复
-3. **最近不同发送者**(fallback):关联到最近一条不同发送者的消息(需在 30 分钟内,防止跨话题误关联)
+1. **@提及匹配**(最高优先级):消息中 `@某人` → 关联到被@者最近一条消息
+2. **同发送者聚类**:同一发送者在 2 分钟窗口内连续发多条消息 → 认为是对同一目标的回复
+3. **最近不同发送者**(fallback):关联到最近一条不同发送者的消息(需在 30 分钟内,防止跨话题误关联)
```
-示例:
+示例:
12:18 徐思清: NPC HUD 报告 (无引用)
-12:19 王胤鑫: o3 分支? (无引用 → 推断关联12:18,因为12:18是最近不同发送者)
-12:19 王胤鑫: 有固定关卡吗 (无引用 → 推断关联12:18,因为同发送者2分钟窗口内)
+12:19 王胤鑫: o3 分支? (无引用 → 推断关联12:18,因为12:18是最近不同发送者)
+12:19 王胤鑫: 有固定关卡吗 (无引用 → 推断关联12:18,因为同发送者2分钟窗口内)
```
-#### 阶段 B:引用链排序
+#### 阶段 B:引用链排序
-1. **Union-Find 聚类**:将有引用关系的消息(含推断引用)合并为同一「问题簇」
-2. **簇内递归展开**:从根消息开始,子回复紧跟父消息(子节点按时间排序)
-3. **簇间排序**:按每个簇最早消息的时间排序
+1. **Union-Find 聚类**:将有引用关系的消息(含推断引用)合并为同一「问题簇」
+2. **簇内递归展开**:从根消息开始,子回复紧跟父消息(子节点按时间排序)
+3. **簇间排序**:按每个簇最早消息的时间排序
### 排序效果对比
-排序前(时间平铺):
+排序前(时间平铺):
```
12:18 徐思清: NPC HUD 报告
-12:19 王胤鑫: o3 分支?
+12:19 王胤鑫: o3 分支?
12:19 王胤鑫: 有固定关卡出现吗
12:20 庞鸿潇: @王胤鑫 11-2 (引用"有固定关卡")
12:22 梁晨: @王胤鑫 没啥规律 (引用"有固定关卡")
12:28 王胤鑫: 是否只在移动端 (引用NPC HUD)
```
-排序后(问题链聚合):
+排序后(问题链聚合):
```
12:18 徐思清: NPC HUD 报告
- 12:19 王胤鑫: o3 分支? (推断引用12:18)
+ 12:19 王胤鑫: o3 分支? (推断引用12:18)
12:19 王胤鑫: 有固定关卡吗 (推断引用12:18)
12:20 庞鸿潇: 11-2 (引用"有固定关卡")
12:22 梁晨: 没啥规律 (引用"有固定关卡")
@@ -135,18 +137,18 @@ lark-cli sheets +write \
12:26 孙时敏: Playtesting有数据 (推断引用12:22)
```
-> 缩进行为对该根消息的直接或间接回复,形成完整的「问题 → 追问 → 诊断 → 结论」链路。
+> 缩进行为对该根消息的直接或间接回复,形成完整的「问题 → 追问 → 诊断 → 结论」链路。
-### 步骤 4:问题归纳
+### 步骤 4:问题归纳
-对每个问题簇生成结构化归纳,分两个部分:
-1. **问题描述**:按固定格式描述问题
-2. **当前问题排查结论**:从对话最后几条消息中提取排查状态
+对每个问题簇生成结构化归纳,分两个部分:
+1. **问题描述**:按固定格式描述问题
+2. **当前问题排查结论**:从对话最后几条消息中提取排查状态
#### 4.1 问题描述格式
```
-> **在{端}端{环节}内({课程}),{角色/组件}出现了{现象}**
+> **在{端}端{环节}内({课程}),{角色/组件}出现了{现象}**
```
#### 位置要素提取维度
@@ -161,82 +163,82 @@ lark-cli sheets +write \
#### 4.2 归纳输出格式
-每个问题簇输出一个结构化块(结论在表格上方,表格放原始对话):
+每个问题簇输出一个结构化块(结论在表格上方,表格放原始对话):
```markdown
### 问题 N
-**问题描述:** {AI 归纳后的精炼描述}
+**问题描述:** {AI 归纳后的精炼描述}
-**当前问题排查结论:** {结论}
+**当前问题排查结论:** {结论}
| 发言人 | 对话信息 |
|--------|---------|
-| 报告人 | 🚩 报告:原始对话内容 |
-| ... | 原始对话内容(含媒体 URL) |
+| 报告人 | 🚩 报告:原始对话内容 |
+| ... | 原始对话内容(含媒体 URL) |
| 最终人 | ✅ 原始对话内容 |
```
```
#### 4.3 排查结论提取规则
-脚本从**全部消息**(而非仅最后 1-2 条)中提取结论。优先匹配以下模式:
+脚本从**全部消息**(而非仅最后 1-2 条)中提取结论。优先匹配以下模式:
| 优先级 | 匹配模式 | 结论 |
|--------|---------|------|
| 1 | 已修复/已解决/修好了 | 已修复 |
-| 2 | 确认是bug/确实是问题 | 已确认,待修复 |
-| 3 | 不是bug/设计如此/非问题 | 非问题,设计如此 |
-| 4 | 有解释性分析 + 日志已上传 + 排查中 | 疑似{原因},已上传日志,排查中 |
-| 5 | 日志已上传 + 排查中 | 已上传日志,排查中 |
+| 2 | 确认是bug/确实是问题 | 已确认,待修复 |
+| 3 | 不是bug/设计如此/非问题 | 非问题,设计如此 |
+| 4 | 有解释性分析 + 日志已上传 + 排查中 | 疑似{原因},已上传日志,排查中 |
+| 5 | 日志已上传 + 排查中 | 已上传日志,排查中 |
| 6 | 暂未/没复现/未复现 | 暂未排查到问题 |
-| 7 | 其他(无明确结论) | 暂未排查到问题 |
+| 7 | 其他(无明确结论) | 暂未排查到问题 |
-**解释性分析** 的来源:消息中匹配 "因为/原因是/应该是/改为了/导致/预下载/上云/首次/正常情况" 等关键词,提取对应发言人的判断句作为疑似原因。
+**解释性分析** 的来源:消息中匹配 "因为/原因是/应该是/改为了/导致/预下载/上云/首次/正常情况" 等关键词,提取对应发言人的判断句作为疑似原因。
-> 注意:脚本的规则匹配是辅助手段。运行时的 AI 可以根据完整对话上下文,修正或补全结论。
+> 注意:脚本的规则匹配是辅助手段。运行时的 AI 可以根据完整对话上下文,修正或补全结论。
#### 4.4 归纳示例
```markdown
### 问题一
-> **在移动端关卡内(11-2 等),NPC 头上的 HUD 偶尔变成一小条**
+> **在移动端关卡内(11-2 等),NPC 头上的 HUD 偶尔变成一小条**
| 发言人 | 要点 |
|--------|------|
-| 徐思清 | 🚩 报告:最近经常出现,无明显规律 |
-| 王胤鑫 | 追问:o3 分支?只在手机包出现,unity 里正常? |
-| 庞鸿潇 | 确认:11-2 出现了 |
-| 梁晨 | 补充:只在 APP 里发现过 |
-| 徐思清 | ✅ 确认:确实只在移动端出现 |
+| 徐思清 | 🚩 报告:最近经常出现,无明显规律 |
+| 王胤鑫 | 追问:o3 分支?只在手机包出现,unity 里正常? |
+| 庞鸿潇 | 确认:11-2 出现了 |
+| 梁晨 | 补充:只在 APP 里发现过 |
+| 徐思清 | ✅ 确认:确实只在移动端出现 |
-**当前问题排查结论:** 暂未排查到问题
+**当前问题排查结论:** 暂未排查到问题
```
```markdown
### 问题二
-> **在 iOS 端关卡内(L1 3-2),组件数据丢失,无音频,Loading 耗时约 10 秒**
+> **在 iOS 端关卡内(L1 3-2),组件数据丢失,无音频,Loading 耗时约 10 秒**
| 发言人 | 要点 |
|--------|------|
-| 胡陈辰 | 🚩 报告:iOS 线上 L1 3-2 组件无音频 |
-| 安君仪 | 询问:哪个组件? |
-| 胡陈辰 | 复现:Loading 约 10 秒,组件数据丢失,杀 APP 重进恢复正常 |
-| 毋益飞 | 解释:Loading 慢因内容上云加载;要求上传日志 |
-| 胡陈辰 | ✅ 日志已上传,待明天排查 |
+| 胡陈辰 | 🚩 报告:iOS 线上 L1 3-2 组件无音频 |
+| 安君仪 | 询问:哪个组件? |
+| 胡陈辰 | 复现:Loading 约 10 秒,组件数据丢失,杀 APP 重进恢复正常 |
+| 毋益飞 | 解释:Loading 慢因内容上云加载;要求上传日志 |
+| 胡陈辰 | ✅ 日志已上传,待明天排查 |
-**当前问题排查结论:** 日志已上传,排查中
+**当前问题排查结论:** 日志已上传,排查中
```
-### 步骤 5:优先级判定与排序
+### 步骤 5:优先级判定与排序
-基于《用户反馈问题优先级判断文档》,对步骤4归纳的问题自动评定优先级(P0-P3),并按优先级从高到低排序输出。
+基于《用户反馈问题优先级判断文档》,对步骤4归纳的问题自动评定优先级(P0-P3),并按优先级从高到低排序输出。
#### 5.1 判定维度
| 维度 | 说明 | 来源 |
|------|------|------|
-| 基础优先级 | 根据问题严重程度(崩溃/功能异常/体验瑕疵/细节优化) | 关键词规则匹配 |
+| 基础优先级 | 根据问题严重程度(崩溃/功能异常/体验瑕疵/细节优化) | 关键词规则匹配 |
| 出现概率 | 必现/高概率/中概率/低概率/偶现 | 消息内容关键词 |
| 影响范围 | 全部用户/大部分用户/部分用户/极少数用户 | 消息内容关键词 |
@@ -244,8 +246,8 @@ lark-cli sheets +write \
| 规则 | 条件 | 效果 |
|------|------|------|
-| 必现升级 | 出现概率为必现/高概率 | 原有优先级 +1 级(P1→P0, P2→P1) |
-| 偶现降级 | 出现概率为低概率/偶现 | 原有优先级 -1 级(最多降一级,P1→P2) |
+| 必现升级 | 出现概率为必现/高概率 | 原有优先级 +1 级(P1→P0, P2→P1) |
+| 偶现降级 | 出现概率为低概率/偶现 | 原有优先级 -1 级(最多降一级,P1→P2) |
| 范围升级 | 影响全部用户 | 原有优先级 +1 级 |
| 范围降级 | 仅影响极少数用户 | 原有优先级 -1 级 |
@@ -253,31 +255,31 @@ lark-cli sheets +write \
| 级别 | 定义 | 修复时限 | 典型关键词 |
|------|------|----------|-----------|
-| 🔴 **P0** | 孩子完全上不了课 / 核心功能崩溃 | 2小时内处理,当天解决 | 闪退、崩溃、进不去、数据丢失、服务器宕机 |
+| 🔴 **P0** | 孩子完全上不了课 / 核心功能崩溃 | 2小时内处理,当天解决 | 闪退、崩溃、进不去、数据丢失、服务器宕机 |
| 🟠 **P1** | 功能能用但不对劲 / 学习效果打折扣 | 3天内修复上线 | 音频异常、判分错误、进度保存失败、奖励未发放 |
| 🟡 **P2** | 偶尔小毛病 / 界面瑕疵 / 刷新就好 | 当周修复 | UI显示异常、偶尔不显示、拖拽不流畅、刷新恢复 |
| 🟢 **P3** | 几乎不影响使用 / 追求完美细节 | 不单独排期 | 分辨率略低、错别字、背景音不统一 |
#### 5.4 输出格式
-在步骤4归纳结果的基础上,每个问题标题追加优先级标签,并新增优先级信息行:
+在步骤4归纳结果的基础上,每个问题标题追加优先级标签,并新增优先级信息行:
```markdown
### 问题 1 🔴 P0
-**优先级:** 🔴 P0 | 基础优先级: P1(匹配P1规则:learning_func);出现频率: 必现;动态调整: 升级 1 级
-**修复时限:** 2小时内处理,当天解决
+**优先级:** 🔴 P0 | 基础优先级: P1(匹配P1规则:learning_func);出现频率: 必现;动态调整: 升级 1 级
+**修复时限:** 2小时内处理,当天解决
> **[AI归纳: 问题描述]**
...
```
-问题在文档中按 **P0 → P1 → P2 → P3** 排列,同优先级内按最早消息时间排序。
+问题在文档中按 **P0 → P1 → P2 → P3** 排列,同优先级内按最早消息时间排序。
-在归纳开头先输出优先级分布汇总:
+在归纳开头先输出优先级分布汇总:
```markdown
-**优先级分布:** P0:1个 | P1:3个 | P2:5个 | P3:2个
+**优先级分布:** P0:1个 | P1:3个 | P2:5个 | P3:2个
```
#### 5.5 执行方式
@@ -286,23 +288,147 @@ lark-cli sheets +write \
# 默认启用步骤5
python3 sync_feishu_feedback.py --days 3
-# 跳过步骤5(仅执行步骤1-4)
+# 跳过步骤5(仅执行步骤1-4)
python3 sync_feishu_feedback.py --days 3 --skip-priority
```
-优先级判定函数位于独立模块 `scripts/priority_classifier.py`,可单独测试:
+优先级判定函数位于独立模块 `scripts/priority_classifier.py`,可单独测试:
```bash
python3 priority_classifier.py
```
-## 定时任务
+### 步骤 6:问题分类
-建议每日执行一次,在飞书群消息同步完毕后(`feishu-group-msg-sync` 之后)运行。
+对每个问题簇自动判定问题类别,在"今日问题归纳"部分按 **优先级 + 分类** 分组展示。
-### 创建定时任务(crontab)
+#### 6.1 问题分类规则
+
+按匹配优先级从上到下执行,命中第一个即返回:
+
+| 分类名称 | 匹配关键词场景 |
+|---------|----------------|
+| 启动/运行异常 | 闪退、崩溃、卡死、无法启动、进不去、服务器宕机 |
+| 版本/更新类 | 更新失败、版本异常、升级后无法使用 |
+| Loading/加载类 | 加载慢、加载超时、转星星、Loading 耗时异常 |
+| 数据/进度类 | 数据丢失、进度不对、白学、保存失败 |
+| 声音/音频类 | 无声、音频异常、播放问题、听不到 |
+| 语音识别/判分类 | 判分不对、识别错误、评测异常 |
+| 关卡/内容类 | 关卡异常、课程问题、层级问题、题目错误 |
+| UI显示类 | 界面异常、HUD显示、动画、错位、截断 |
+| 用户反馈问题 | 反馈、建议 |
+| 其他问题 | 默认兆底 |
+
+#### 6.2 "今日问题归纳"输出格式
+
+```markdown
+## 今日问题归纳
+
+**⚠️ P0级核心问题(需优先处理)**
+1. **Loading/加载类**
+ - 在iOS 端关卡内(3-2),Loading 耗时约 10 秒...
+
+**⚡ P1级重要问题**
+1. **关卡/内容类**
+ - 【偶现】在移动端关卡内,NPC 头上的 HUD 偶尔变成一小条
+
+**📌 P2级一般问题**
+1. **UI显示类**
+ - ...
+
+**📝 P3级低优先级**
+1. **其他问题**
+ - ...
+```
+
+#### 6.3 优先级标题映射
+
+| 优先级 | 标题格式 |
+|--------|----------|
+| P0 | ⚠️ P0级核心问题(需优先处理) |
+| P1 | ⚡ P1级重要问题 |
+| P2 | 📌 P2级一般问题 |
+| P3 | 📝 P3级低优先级 |
+
+#### 6.4 分类函数
+
+位于 `sync_feishu_feedback.py` 中的 `classify_problem(cluster_msgs)` 函数,基于 `CATEGORY_PATTERNS` 列表顺序匹配。
+
+### 文档输出结构(子文档模式)
+
+「用户反馈问题汇总」采用子文档模式,每个日期独立一个子文档:
+
+```
+📂 用户反馈问题汇总 (node: RaL6whoYMijyYHkSlWrc7OLLnBy)
+ ├── 2026-05-06 问题反馈
+ ├── 2026-04-28 问题反馈
+ └── ...更多日期
+```
+
+**规则:**
+- 每天只新增一个对应日期的子文档,绝不重复创建
+- 子文档标题格式:`YYYY-MM-DD 问题反馈`
+- 已有同日期子文档则覆盖更新内容
+- 实现函数:`update_summary_doc_as_children(day_sections)`
+- 依赖:`list_child_nodes()` 查询已有子文档,`create_child_doc()` 创建新节点
+
+### 步骤 7:问题分发
+
+将每日问题归纳同步到「小葵小葵」问题反馈群(chat_id: `oc_4171a2188f2554522a4309f2d7c27753`),P0问题 @相关负责人及时跟进。
+
+#### 7.1 分发规则
+
+| 规则 | 说明 |
+|------|------|
+| 内容 | 仅发送"今日问题归纳"部分(不含"今日问题拆解"详细表格) |
+| 格式 | 富文本 post 消息,含标题 + 归纳正文 + 文档链接 |
+| P0 @通知 | 自动 @配置列表中的负责人(当前:毋益飞 eggbg21g) |
+| 身份 | 使用小葵Bot(凭证目录 `DIS PATCH_CRED_DIR`)直接调用 API |
+| 频率 | 每天每条汇总发送一次 |
+
+#### 7.2 消息格式示例
+
+```
+📋 2026-04-28 用户反馈问题归纳
+
+⚠️ P0级核心问题(需优先处理) @毋益飞
+1. Loading/加载类
+ - 在iOS 端关卡内(3-2),Loading 耗时约 10 秒...
+
+⚡ P1级重要问题
+1. 关卡/内容类
+ - 【偶现】在移动端关卡内(11-2),NPC 头上的 HUD 偶尔变成一小条
+
+📄 详细文档:2026-04-28 问题反馈 [链接]
+```
+
+#### 7.3 配置
+
+位于 `sync_feishu_feedback.py`:
+
+| 配置项 | 值 | 说明 |
+|--------|-----|------|
+| DISPATCH_CHAT_ID | `oc_4171a2188f2554522a4309f2d7c27753` | 目标群 |
+| P0_NOTIFY_USERS | `["eggbg21g"]` | P0问题 @列表 |
+| DISPATCH_CRED_DIR | `/root/.openclaw/credentials/xiaokui` | Bot身份凭证 |
+
+#### 7.4 执行方式
```bash
-# 每天 10:00 执行(确保消息已同步入库)
+# 默认执行步骤7
+python3 sync_feishu_feedback.py --days 3
+
+# 跳过步骤7
+python3 sync_feishu_feedback.py --days 3 --skip-dispatch
+```
+
+## 定时任务
+
+建议每日执行一次,在飞书群消息同步完毕后(`feishu-group-msg-sync` 之后)运行。
+
+### 创建定时任务(crontab)
+
+```bash
+# 每天 10:00 执行(确保消息已同步入库)
0 10 * * * /bin/bash /root/.openclaw/workspace-xiaokui/scripts/sync_feishu_feedback_wrapper.sh >> /var/log/xiaokui_feedback_sync.log 2>&1
```
diff --git a/skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py b/skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py
index e86981a..46e7470 100755
--- a/skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py
+++ b/skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py
@@ -531,6 +531,38 @@ def generate_problem_description(cluster_msgs, location, root_text):
return result
+# ============================================================
+# 问题分类(用于“今日问题归纳”部分的分类展示)
+# ============================================================
+
+CATEGORY_PATTERNS = [
+ ("启动/运行异常", r'闪退|崩溃|卡死|无法启动|打不开|进不去|登不上|无法.*进入|无法.*连接|服务器.*挂|宕机'),
+ ("版本/更新类", r'(更新|版本|升级).*(失败|无法|出问题|异常|后.*(无法|不能|收不到))'),
+ ("Loading/加载类", r'loading|加载.*(慢|长|卡|超时|失败)|进入.*慢|转星星'),
+ ("数据/进度类", r'数据.*(丢失|没记录|白学|全没|消失|不对|错误)|进度.*(显示|记录|保存).*(错|不对|失败)'),
+ ("声音/音频类", r'音频|声音|播放|没声音|无声|听不到|没音|没声|无音频|音量'),
+ ("语音识别/判分类", r'判分|打分|识别|评测|跟读.*(异常|不对|错误)|明明.*对.*系统.*(说|判断).*不对'),
+ ("关卡/内容类", r'关卡|课程|单元|知识巩固|题目|选项|内容.*(异常|有问题|错误)|层级|墙.*层级'),
+ ("UI显示类", r'界面|UI|显示|排版|文案|图标|动画|动效|截断|错位|HUD|不显示'),
+ ("用户反馈问题", r'反馈|建议'),
+ ("其他问题", r'.*'), # 默认分类
+]
+
+
+def classify_problem(cluster_msgs) -> str:
+ """
+ 根据问题簇的消息内容判定问题分类。
+ 返回分类名称字符串。
+ """
+ all_text = " ".join(str(m[3]) or "" for m in cluster_msgs)
+ all_text = re.sub(r'\[Image:[^\]]+\]', '', all_text)
+
+ for category_name, pattern in CATEGORY_PATTERNS:
+ if re.search(pattern, all_text, re.IGNORECASE):
+ return category_name
+ return "其他问题"
+
+
def summarize_cluster(cluster_msgs, idx, priority_info=None):
"""
生成单个问题簇的结构化归纳。
@@ -707,23 +739,39 @@ def generate_summary(clusters, cluster_order, skip_priority=False):
# 按优先级排序:P0 > P1 > P2 > P3,同优先级按时间
valid_clusters = sort_by_priority(valid_clusters)
- # 生成层汇总索引
+ # 生成层汇总索引(按优先级 + 分类)
grouped = defaultdict(list)
for vc in valid_clusters:
p = vc.get("priority_info", {}).get("priority", "P2") if not skip_priority else "P2"
+ vc["category"] = classify_problem(vc["msgs"])
grouped[p].append(vc)
+ priority_headers = {
+ "P0": "⚠️ P0级核心问题(需优先处理)",
+ "P1": "⚡ P1级重要问题",
+ "P2": "📌 P2级一般问题",
+ "P3": "📝 P3级低优先级",
+ }
+
for p_level in ["P0", "P1", "P2", "P3"]:
items = grouped.get(p_level, [])
if not items:
continue
- lines.append(f"**【{p_level}问题】**")
- item_idx = 0
+ lines.append(f"**{priority_headers[p_level]}**")
+
+ # 按分类分组
+ by_category = defaultdict(list)
for vc in items:
- item_idx += 1
- desc = generate_problem_description(vc["msgs"],
- extract_location_elements(vc["msgs"]), "")
- lines.append(f"{item_idx},{desc}")
+ by_category[vc["category"]].append(vc)
+
+ cat_idx = 0
+ for cat_name, cat_items in by_category.items():
+ cat_idx += 1
+ lines.append(f"{cat_idx}. **{cat_name}**")
+ for vc in cat_items:
+ desc = generate_problem_description(vc["msgs"],
+ extract_location_elements(vc["msgs"]), "")
+ lines.append(f" - {desc}")
lines.append("")
# 问题拆解
@@ -740,31 +788,129 @@ def generate_summary(clusters, cluster_order, skip_priority=False):
# === 步骤5写入目标文档配置 ===
-SUMMARY_DOC_TOKEN = "J8bKd4dbYoofZixxVsCc06bhnFc" # 用户反馈问题汇总.docx obj_token
+SUMMARY_PARENT_NODE = "RaL6whoYMijyYHkSlWrc7OLLnBy" # 用户反馈问题汇总 wiki node_token
+SUMMARY_SPACE_ID = "7612229802338045122" # 知识空间 ID
-def update_summary_doc(markdown_content, day_label, mode="overwrite"):
+
+def get_tenant_token(cred_dir=None):
+ """获取 Bot 的 tenant_access_token。cred_dir 可选指定凭证目录。"""
+ import urllib.request
+ if cred_dir is None:
+ cred_dir = os.environ.get("LARKSUITE_CLI_CONFIG_DIR", "/root/.openclaw/credentials/xiaoyan")
+ config = json.load(open(os.path.join(cred_dir, "config.json")))
+ app_id = config["apps"][0]["appId"]
+ app_secret = config["apps"][0]["appSecret"]
+
+ req = urllib.request.Request(
+ "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
+ data=json.dumps({"app_id": app_id, "app_secret": app_secret}).encode(),
+ headers={"Content-Type": "application/json"},
+ method="POST"
+ )
+ resp = urllib.request.urlopen(req, timeout=10)
+ return json.loads(resp.read())["tenant_access_token"]
+
+
+def list_child_nodes():
+ """列出「用户反馈问题汇总」下的所有子节点,返回 {title: {node_token, obj_token}}。同名节点取 obj_edit_time 最新的。"""
+ import urllib.request
+ token = get_tenant_token()
+ url = f"https://open.feishu.cn/open-apis/wiki/v2/spaces/{SUMMARY_SPACE_ID}/nodes?parent_node_token={SUMMARY_PARENT_NODE}"
+ req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"})
+ resp = urllib.request.urlopen(req, timeout=10)
+ data = json.loads(resp.read())
+
+ nodes = {}
+ for item in data.get("data", {}).get("items", []):
+ title = item["title"]
+ edit_time = item.get("obj_edit_time", "0")
+ # 同名取更新时间最近的
+ if title not in nodes or edit_time > nodes[title].get("_edit_time", "0"):
+ nodes[title] = {
+ "node_token": item["node_token"],
+ "obj_token": item["obj_token"],
+ "_edit_time": edit_time
+ }
+ return nodes
+
+
+def create_child_doc(title):
+ """在「用户反馈问题汇总」下创建子文档,返回 obj_token"""
+ import urllib.request
+ token = get_tenant_token()
+ url = f"https://open.feishu.cn/open-apis/wiki/v2/spaces/{SUMMARY_SPACE_ID}/nodes"
+ body = json.dumps({
+ "obj_type": "docx",
+ "node_type": "origin",
+ "parent_node_token": SUMMARY_PARENT_NODE,
+ "title": title
+ }).encode()
+ req = urllib.request.Request(url, data=body, headers={
+ "Authorization": f"Bearer {token}",
+ "Content-Type": "application/json"
+ }, method="POST")
+ resp = urllib.request.urlopen(req, timeout=10)
+ data = json.loads(resp.read())
+ if data.get("code") == 0:
+ return data["data"]["node"]["obj_token"]
+ print(f" ⚠️ 创建子文档失败: {data}")
+ return None
+
+
+def update_summary_doc_as_children(day_sections):
"""
- 将当日归纳结果写入「用户反馈问题汇总」文档。
- mode: 'overwrite'(覆盖,默认,第一天使用) / 'append'(追加,多天时后续天使用)
+ 将各日期的归纳结果写入「用户反馈问题汇总」的子文档中。
+ day_sections: dict, key=日期字符串(如'2026-05-06'), value=该日的归纳 markdown
+
+ 逻辑:
+ 1. 列出已有子文档
+ 2. 对每个日期:已有则覆盖更新,无则创建新子文档
+ 3. 写入内容
"""
env = get_env()
+ existing_nodes = list_child_nodes()
- full_md = f"## {day_label} 飞书问题反馈归纳\n\n" + markdown_content
+ for day in sorted(day_sections.keys(), reverse=True):
+ title = f"{day} 问题反馈"
+ content = day_sections[day]
+
+ # 双重检查:重新列一次子节点,避免并发创建重复
+ existing_nodes = list_child_nodes()
+ if title in existing_nodes:
+ obj_token = existing_nodes[title]["obj_token"]
+ print(f" 📝 更新子文档: {title}")
+ else:
+ obj_token = create_child_doc(title)
+ if not obj_token:
+ # 创建失败可能是并发冲突,再查一次
+ existing_nodes = list_child_nodes()
+ if title in existing_nodes:
+ obj_token = existing_nodes[title]["obj_token"]
+ print(f" 📝 已存在,使用已有子文档: {title}")
+ else:
+ continue
+ else:
+ print(f" ➕ 创建子文档: {title}")
+
+ # 写入内容
+ result = subprocess.run(
+ [CLI, "docs", "+update", "--doc", obj_token, "--as", "bot",
+ "--mode", "overwrite",
+ "--markdown", content],
+ env=env, capture_output=True, text=True, timeout=15
+ )
+
+ try:
+ d = json.loads(result.stdout)
+ if d.get("ok"):
+ print(f" ✅ {title} 写入成功")
+ else:
+ print(f" ⚠️ {title} 写入失败: {result.stdout[:100]}")
+ except Exception:
+ print(f" ⚠️ {title} 写入异常: {result.stderr[:100]}")
- result = subprocess.run(
- [CLI, "docs", "+update", "--doc", SUMMARY_DOC_TOKEN, "--as", "bot",
- "--mode", mode,
- "--markdown", full_md],
- env=env, capture_output=True, text=True, timeout=15
- )
-
- d = json.loads(result.stdout)
- if d.get("ok"):
- print(f" ✅ 归纳结果已{'覆盖写入' if mode == 'overwrite' else '追加'}到「用户反馈问题汇总」文档")
- return True
- else:
- print(f" ⚠️ 文档写入失败: {result.stdout[:200]}")
- return False
+ print(f" 📂 共处理 {len(day_sections)} 个日期的子文档")
+ return True
def main():
@@ -772,6 +918,9 @@ def main():
parser.add_argument("--days", type=int, default=3, help="同步最近 N 天(默认 3)")
parser.add_argument("--dry-run", action="store_true", help="仅预览不写入")
parser.add_argument("--skip-priority", action="store_true", help="跳过步骤5优先级判定")
+ parser.add_argument("--skip-dispatch", action="store_true", help="跳过步骤7问题分发")
+ parser.add_argument("--dispatch-mode", type=str, default="all", choices=["all", "p0"], help="分发模式:all=发全部, p0=仅发P0级问题(默认 all)")
+ parser.add_argument("--steps", type=str, default="1-7", help="执行步骤范围,如 '1-3'(仅写入表格)或 '4-7'(归纳+分类+分发)")
args = parser.parse_args()
end_date = date.today()
@@ -806,7 +955,7 @@ def main():
print(f"📑 现有 sheet:{list(existing.keys())}")
total_written = 0
- first_day_written = False
+ day_summaries = {} # 收集所有天的归纳结果
for day in sorted(groups.keys()):
msgs = groups[day]
@@ -823,26 +972,26 @@ def main():
sorted_msgs, clusters, cluster_order = sort_threads(msgs)
print(f" 排序完成:{len(sorted_msgs)} 条")
- # 步骤 4:问题归纳
- # 步骤 5:优先级判定(默认启用,--skip-priority 可跳过)
- summary, has_content = generate_summary(clusters, cluster_order, skip_priority=args.skip_priority)
- if has_content:
- priority_count = summary.count('优先级:') if not args.skip_priority else 0
- print(f" 归纳完成:{summary.count('### 问题')} 个问题")
- if not args.skip_priority:
- print(f" 步骤5 优先级判定完成:{priority_count} 个问题已评定优先级并排序")
- print(f" (归纳内容见下方)")
- print(summary)
-
- # 写入「用户反馈问题汇总」文档
- # 第一个有内容的天用 overwrite,后续用 append
- doc_mode = "overwrite" if not first_day_written else "append"
- update_summary_doc(summary, day, mode=doc_mode)
- first_day_written = True
- else:
- print(" ⚠️ 无有效问题簇可归纳")
+ # 根据 --steps 参数决定是否执行步骤4-6
+ run_steps = args.steps
+ do_summary = "4" in run_steps or "5" in run_steps or "6" in run_steps or "7" in run_steps
+
+ if do_summary:
+ # 步骤 4:问题归纳
+ # 步骤 5:优先级判定(默认启用,--skip-priority 可跳过)
+ summary, has_content = generate_summary(clusters, cluster_order, skip_priority=args.skip_priority)
+ if has_content:
+ priority_count = summary.count('优先级:') if not args.skip_priority else 0
+ print(f" 归纳完成:{summary.count('### 问题')} 个问题")
+ if not args.skip_priority:
+ print(f" 步骤5 优先级判定完成:{priority_count} 个问题已评定优先级并排序")
+ print(f" (归纳内容见下方)")
+ print(summary)
+ day_summaries[day] = summary
+ else:
+ print(" ⚠️ 无有效问题簇可归纳")
- # 写入
+ # 写入表格(步骤2)
success = write_sheet(sheet_id, sorted_msgs)
if success:
total_written += len(sorted_msgs)
@@ -850,8 +999,174 @@ def main():
else:
print(f" ❌ 写入失败")
+ # 统一写入「用户反馈问题汇总」文档(增量更新,保留已有日期内容)— 步骤4-6
+ if day_summaries and do_summary:
+ update_summary_doc_as_children(day_summaries)
+
+ # 步骤7:问题分发(发送到群聊 + @相关人)
+ if do_summary and not args.skip_dispatch:
+ dispatch_mode = args.dispatch_mode
+ print(f"\n📨 步骤7:问题分发(模式: {dispatch_mode})...")
+ for day, info in day_summaries.items():
+ # 检查当天归纳中是否有 P0 问题
+ has_p0 = "⚠️ P0级" in info["summary"]
+ if dispatch_mode == "p0" and not has_p0:
+ print(f" [{day}] 无P0问题,跳过分发")
+ continue
+ dispatch_summary_to_chat(day, info["summary"], p0_only=(dispatch_mode == "p0"))
+
print(f"\n🎉 同步完成,总计写入 {total_written} 条")
if __name__ == "__main__":
main()
+
+
+# ============================================================
+# 步骤 7:问题分发(发送到群聊 + @相关人)
+# ============================================================
+
+# 分发目标群配置
+DISPATCH_CHAT_ID = "oc_4171a2188f2554522a4309f2d7c27753" # 「小葵小葵」问题反馈群
+
+# P0问题默认@的人(user_id)
+P0_NOTIFY_USERS = [
+ "eggbg21g", # 毋益飞
+]
+
+# Bot身份: 使用 xiaokui(小葵)的凭证发消息
+DISPATCH_CRED_DIR = "/root/.openclaw/credentials/xiaokui"
+
+
+def dispatch_summary_to_chat(day_label, summary_text, p0_only=False):
+ """
+ 将「今日问题归纳」部分发送到指定群聊。
+ P0问题会 @指定人员。
+
+ 参数:
+ day_label: 日期标签,如 '2026-04-28'
+ summary_text: 今日问题归纳的 markdown 文本
+ p0_only: True=仅发送 P0 部分,False=发送全部
+ """
+ if not DISPATCH_CHAT_ID:
+ print(" ⚠️ 未配置分发群 chat_id,跳过步骤7")
+ return False
+
+ # 构建消息内容
+ # 提取「今日问题归纳」部分(到「今日问题拆解」之前)
+ lines = summary_text.split("\n")
+ 归纳_lines = []
+ in_归纳 = False
+ for line in lines:
+ if "今日问题归纳" in line:
+ in_归纳 = True
+ continue
+ if "今日问题拆解" in line:
+ break
+ if in_归纳:
+ 归纳_lines.append(line)
+
+ 归纳_content = "\n".join(归纳_lines).strip()
+ if not 归纳_content:
+ print(" ⚠️ 无归纳内容可分发")
+ return False
+
+ # 检查是否有 P0 问题
+ has_p0 = "⚠️ P0级" in 归纳_content
+
+ # 如果 p0_only 模式,裁剪掉非 P0 部分
+ if p0_only and has_p0:
+ # 保留 P0 部分,去掉后面的 P1/P2/P3
+ # 找到下一个优先级标题的位置
+ for marker in ["⚡ P1级", "📌 P2级", "📝 P3级"]:
+ idx = 归纳_content.find(marker)
+ if idx > 0:
+ 归纳_content = 归纳_content[:idx].strip()
+ break
+
+ # 构建富文本消息(post 格式)
+ # P0 @跟在标题行后面,不放单独段落
+ title = f"📋 {day_label} 用户反馈问题归纳"
+
+ # 将归纳内容中的 P0 标题行注入 @人
+ # 格式:⚠️ P0级核心问题(需优先处理) → ⚠️ P0级核心问题(需优先处理) @某某
+ if has_p0 and P0_NOTIFY_USERS:
+ at_str = "".join(f"" for uid in P0_NOTIFY_USERS)
+ # 在 P0 标题行后面插入 @
+ 归纳_content = re.sub(
+ r'(⚠️ P0级核心问题(需优先处理))',
+ rf'\1 {at_str}',
+ 归纳_content
+ )
+
+ # 飞书 post 消息不支持 HTML 标签的 at,需要用富文本 tag
+ # 所以改为:把归纳内容按 P0/P1/P2/P3 段落拆分,P0 段落后追加 at tag
+ content_parts = []
+
+ if has_p0 and P0_NOTIFY_USERS:
+ # 找到 P0 标题行并插入 @
+ p0_header = "⚠️ P0级核心问题(需优先处理)"
+ if p0_header in 归纳_content:
+ parts_before = 归纳_content.split(p0_header, 1)
+ before_p0 = parts_before[0].strip()
+ after_p0 = parts_before[1].lstrip()
+
+ if before_p0:
+ content_parts.append([{"tag": "text", "text": before_p0 + "\n"}])
+
+ # P0 标题行 + @ + 后续内容
+ p0_line = [{"tag": "text", "text": p0_header + " "}]
+ for uid in P0_NOTIFY_USERS:
+ p0_line.append({"tag": "at", "user_id": uid})
+ p0_line.append({"tag": "text", "text": " "})
+ p0_line.append({"tag": "text", "text": "\n" + after_p0})
+ content_parts.append(p0_line)
+ else:
+ content_parts.append([{"tag": "text", "text": 归纳_content}])
+ else:
+ content_parts.append([{"tag": "text", "text": 归纳_content}])
+
+ # 追加文档链接
+ content_parts.append([
+ {"tag": "text", "text": "\n📄 详细文档:"},
+ {"tag": "a", "text": f"{day_label} 问题反馈", "href": f"https://makee-interactive.feishu.cn/wiki/RaL6whoYMijyYHkSlWrc7OLLnBy"}
+ ])
+
+ post_content = json.dumps({
+ "zh_cn": {
+ "title": title,
+ "content": content_parts
+ }
+ }, ensure_ascii=False)
+
+ # 使用小葵(xiaokui)Bot 身份直接调用飞书 API 发送
+ try:
+ import urllib.request
+ token = get_tenant_token(cred_dir=DISPATCH_CRED_DIR)
+
+ body = json.dumps({
+ "receive_id": DISPATCH_CHAT_ID,
+ "msg_type": "post",
+ "content": post_content
+ }, ensure_ascii=False).encode()
+
+ req = urllib.request.Request(
+ "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id",
+ data=body,
+ headers={
+ "Authorization": f"Bearer {token}",
+ "Content-Type": "application/json"
+ },
+ method="POST"
+ )
+ resp = urllib.request.urlopen(req, timeout=10)
+ d = json.loads(resp.read())
+ if d.get("code") == 0:
+ print(f" ✅ 问题归纳已分发到群聊" + (" (含P0 @通知)" if has_p0 else ""))
+ return True
+ else:
+ print(f" ⚠️ 分发失败: {d.get('msg', '')[:100]}")
+ except Exception as e:
+ print(f" ⚠️ 分发异常: {e}")
+
+ return False
diff --git a/skills/lark_wiki_operate_as_bot.vala/SKILL.md b/skills/lark_wiki_operate_as_bot.vala/SKILL.md
deleted file mode 100644
index 679ea45..0000000
--- a/skills/lark_wiki_operate_as_bot.vala/SKILL.md
+++ /dev/null
@@ -1,75 +0,0 @@
----
-name: lark_wiki_operate_as_bot
-version: 1.0.0
-description: "飞书知识库Bot身份操作专用技能,统一使用Bot身份遍历目录、读取知识库文档内容,禁止触发用户身份授权"
-metadata:
- requires:
- permissions: ["wiki:node:retrieve", "docx:document:readonly"]
----
-
-# lark_wiki_operate_as_bot 技能规范
-
-## 核心规则(强制执行)
-1. **身份限制**:所有知识库操作**永远使用Bot身份**执行,绝对不触发任何用户身份授权弹窗
-2. **文档范围限制**:仅支持读取飞书知识库(`/wiki/`开头的链接)文档,**不支持读取用户私有个人文档**(`/doc/`/`/sheet/`等非wiki开头的个人路径)
-3. **权限告知规则**:
- - 收到非知识库文档链接:直接回复「我仅支持读取飞书知识库(Wiki)文档,暂不支持读取个人私有文档,请提供知识库链接」
- - Bot无权限访问目标知识空间:回复「当前Bot无访问该知识空间权限,请将Bot应用添加为该知识空间成员并授予查看权限后重试」
-
-## 适用场景
-- 遍历知识库目录下的子文档/子目录
-- 读取知识库文档内容
-- 批量导出知识库文档
-- 所有知识库相关的查询、读取操作
-
-## 完整执行链路
-
-### 步骤1:链接解析
-- 从用户提供的链接中提取`wiki_token`:例如链接`https://xxx.feishu.cn/wiki/XXXXXXX`中的`XXXXXXX`即为`wiki_token`
-- 若链接不含`/wiki/`路径,直接按非知识库文档规则回复
-
-### 步骤2:获取节点基础信息
-```bash
-LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/xiaoyan lark-cli wiki spaces get_node --params '{"token":""}' --as bot
-```
-返回结果中提取关键信息:
-- `space_id`:知识空间ID
-- `obj_token`:文档真实ID(若节点为文档)
-- `has_child`:是否为目录(含子节点)
-- `obj_type`:节点类型(docx/sheet/bitable等)
-
-### 步骤3:遍历目录子节点(仅当has_child=true时)
-#### 3.1 获取Bot租户访问凭证
-```bash
-curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
- -H "Content-Type: application/json" \
- -d '{"app_id":"cli_xxx","app_secret":"xxx"}' \
- | jq -r '.tenant_access_token'
-```
-得到`tenant_access_token`(有效期2小时)
-
-#### 3.2 调用Wiki V2接口获取子节点列表
-```bash
-curl -s -X GET "https://open.feishu.cn/open-apis/wiki/v2/spaces//nodes?parent_node_token=" \
- -H "Authorization: Bearer "
-```
-返回子节点完整列表(名称、链接、类型等)
-
-### 步骤4:读取文档内容(仅当节点为文档时)
-```bash
-LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/xiaoyan lark-cli docs +fetch --doc --as bot
-```
-
-## 权限要求
-### 1. 应用权限(飞书开发者后台配置)
-| 权限名称 | Scope | 类型 |
-|---------|-------|------|
-| 获取知识空间节点信息 | `wiki:node:retrieve` | 只读 |
-| 查看文档内容 | `docx:document:readonly` | 只读 |
-
-### 2. 知识空间配置
-需要将Bot应用添加到目标知识空间的成员列表,授予至少「可查看」权限
-
-## 异常处理
-- 接口返回`99991401`(无权限):按权限不足规则回复用户
-- 接口返回`404`:检查`wiki_token`/`space_id`是否正确,确认链接为有效知识库链接