Skill: myd2002/skill-b-pre-brief (version 1.0.1)

--- name: skill-b-pre-brief description: "【会前简报定时任务】每15分钟由 OpenClaw cron 触发一次。负责在会议开始前15分钟至6小时内自动生成并发送会前进度简报。不处理会议创建、会议修改、取消会议、会后纪要等场景。触发关键词：会前简报、pre_brief、发简报、会前准备报告。cron 场景下自动触发，无需用户主动输入。" author: mayidan --- # Skill-B: pre_brief — 会前简报自动发送 ## 定位 本技能是 **cron 定时执行的会前简报流程总控**。 职责分工： - **OpenClaw（本次对话/cron 任务）** - 触发本技能 scan 脚本 - 读取 scan 返回的会议列表 - 对每场会议：调用 gitea-routine-report 拉取 Gitea 活动数据 - 作为 AI 生成 ai_overview / ai_suggestion / member_summaries / risk_notes - 调用 gitea-routine-report 的 render_email.py 渲染 HTML - 调用本技能 commit 脚本保存文件并更新状态 - 调用 imap-smtp-email 向全体参会人发送简报邮件 - **Skill-B（本技能）** - scan：遍历所有受管仓库，找出需要发简报的会议，计算时间窗口 - commit：将简报存入 Gitea 会议目录，更新 meta.yaml 状态，写日志，返回邮件参数 - **gitea-routine-report** - 只做数据拉取 + HTML 渲染 - 不直接触发其自带邮件发送逻辑（由 OpenClaw 决定发给谁） - **imap-smtp-email** - 发送最终简报邮件给全体参会人 --- ## 配置要求 配置文件：`~/.config/skill-b-pre-brief/.env` 首次使用前运行： ```bash bash setup.sh ``` --- ## 严格工作流（每次 cron 触发必须按顺序执行） --- ### 第一步：运行 scan，获取待发简报会议列表 ```bash node main.js scan ``` 返回 JSON，`meetings` 字段包含所有需要处理的会议，每条有以下字段： - `action`：`"generate_brief"` = 正常发简报；`"mark_only"` = 改期会议只改状态不发邮件 - `repo`：仓库全名，如 `HKU-AIFusion/dexterous-hand` - `meeting_dir`：会议目录名，如 `2026-04-22-1500` - `topic`：会议主题 - `scheduled_time`：会议时间（ISO8601） - `organizer`：组织者 Gitea 用户名 - `attendees`：参会人 Gitea 用户名列表 - `attendee_emails`：参会人邮箱列表 - `since`：Gitea 活动统计开始时间（ISO8601） - `until`：Gitea 活动统计结束时间（ISO8601） - `report_params`：传给 gitea-routine-report 的参数 `{repo, since, until}` **只有会议时间落在“开始前 15 分钟到 6 小时”这个窗口内，才会被 scan 命中。** **如果 `meetings` 为空，本次 cron 无需继续执行。** --- ### 第二步：对 `action == "mark_only"` 的会议，直接更新状态 对每条 `action == "mark_only"` 的会议，运行： ```bash node main.js commit \ --repo "HKU-AIFusion/dexterous-hand" \ --meeting-dir "2026-04-22-1500" \ --mark-only ``` 这会直接将 meta.yaml status 改为 `brief-sent`，不生成简报、不发邮件。 --- ### 第三步：对 `action == "generate_brief"` 的会议，逐条生成并发送简报 对每条 `action == "generate_brief"` 的会议，按以下子步骤处理： #### 3a. 调用 gitea-routine-report 拉取 Gitea 活动数据 使用 scan 返回的 `report_params`： ```bash python <gitea-routine-report路径>/scripts/generate_report.py \ --repo "HKU-AIFusion/dexterous-hand" \ --since "2026-04-15" \ --until "2026-04-22" ``` 输出是 JSON 数组，取 `[0]` 元素作为本次会议仓库的数据。 > **注意**：`since` / `until` 日期格式为 `YYYY-MM-DD`，从 scan 返回的 `report_params.since` / `report_params.until` 字段取值（已格式化为此格式）。 #### 3b. OpenClaw 作为 AI 生成纯文字内容 **严格按照 gitea-routine-report 的 SKILL.md 第三步格式输出**，对上一步的数据生成： ```json { "ai_overview": "...", "ai_suggestion": "...", "member_summaries": { "成员名": "一句话摘要" }, "risk_notes": "..." } ``` 规则同 gitea-routine-report： - 只输出 JSON，不加任何 markdown 代码块标记 - `member_summaries` 键名必须与数据中成员用户名完全一致 - 严禁编造数据中没有的内容 - `risk_notes` 无风险时填空字符串 `""` #### 3c. 将 AI JSON 保存到临时文件 将上一步 JSON 内容存入 `/tmp/ai_brief_{meeting_dir}.json`（`meeting_dir` 中 `/` 替换为 `_`）： ```bash echo '{"ai_overview": "...", ...}' > /tmp/ai_brief_2026-04-22-1500.json ``` #### 3d. 调用 gitea-routine-report 渲染 HTML ```bash python -c " import json, sys, os sys.path.insert(0, '<gitea-routine-report路径>/scripts') from render_email import render data = json.loads(open('/tmp/report_data.json').read()) ai_content = json.loads(open('/tmp/ai_brief_MEETING_DIR.json').read()) repo_data = data[0] html = render(repo_data, ai_content) open('/tmp/brief_body_MEETING_DIR.html', 'w').write(html) print('HTML 已生成，长度：', len(html)) " ``` > 注意：`generate_report.py` 的输出需要先保存到 `/tmp/report_data.json`，再供 render 使用。`MEETING_DIR` 替换为实际目录名（如 `2026-04-22-1500`）。 #### 3e. 调用本技能 commit，保存简报文件并更新状态 ```bash node main.js commit \ --repo "HKU-AIFusion/dexterous-hand" \ --meeting-dir "2026-04-22-1500" \ --topic "v2 设计评审" \ --html-file "/tmp/brief_body_2026-04-22-1500.html" \ --attendee-emails "[REDACTED_SECRET],[REDACTED_SECRET]" \ --since "2026-04-15" \ --until "2026-04-22" ``` 返回 JSON，关键字段： - `success`：是否成功 - `brief_email.to`：收件人邮箱列表 - `brief_email.subject`：邮件主题 - `brief_email.html`：邮件 HTML 正文 #### 3f. 调用 imap-smtp-email 发送简报邮件 使用 commit 返回的 `brief_email` 字段，调用 imap-smtp-email 发送。 收件人：`brief_email.to`（全体参会人邮箱） 主题：`brief_email.subject` 正文：`brief_email.html`（HTML 格式） --- ## 错误处理规则 | 错误场景 | 处理方式 | |----------|----------| | scan 无结果 | 正常退出，本次 cron 结束 | | generate_report.py 失败 | 记录错误，跳过本条会议，继续处理下一条 | | AI 内容生成失败 | 记录错误，跳过本条会议 | | render_email 失败 | 记录错误，跳过本条会议 | | commit 写 Gitea 失败 | 记录错误，不发邮件，下次 cron 重试（status 未变，仍为 scheduled） | | 邮件发送失败 | 记录错误，但 status 已更新为 brief-sent（日志标注 email_failed） | --- ## 幂等性说明 - scan 只返回 `status == scheduled` 且不含 `rescheduled_from` 的会议 - commit 成功后 status → `brief-sent` - 下次 cron 不会再次命中同一场会议 - commit 失败时 status 不变，下次 cron 自动重试


Security scan verdicts — ClawScan: suspicious | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)