agentleFS
RoboZephyrRoboZephyr/lark-skills/skills/progress-report/SKILL.md

progress-report

Skill1 starsChanged 4 months agoMITView on GitHub

Generate a plain-language, decision-oriented engineering progress update from recent repository changes or a specific GitHub PR, with optional local output, Lark/Feishu message delivery, Lark/Feishu document creation, or both. Also powers the unattended daily team report (定时团队日报, launchd-driven, rolling 24h window). Use when the user asks to 同步进度, 生成进度汇报, 团队日报, 发项目进展到群, 创建进度文档, 这个 PR 做了什么, summarize recent code progress, publish engineering progress, explain a PR, or describe what changed, why that approach was chosen, what it means for the workflow, and what to do next based on commits, branches, and PRs.

  • Reads credentials

10 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use handoff.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • MicrosoftSkill

    handoff

    Compact the current conversation into a handoff document for another agent to pick up.

    Also in 3 projects that use this

The file

Files
SKILL.md

Progress Report

生成一份面向团队同步的工程进度报告:从 GitHub 仓库最近代码改动或指定 PR 采集数据,先形成可追溯事实底稿,再改写成平白、面向决策的同步内容,说明“做了什么 / 为什么这样做 / 对工作流有什么意义 / 还有什么待确认 / 下一步是什么”。根据用户请求或 output.mode 决定只本地输出、只发送飞书消息、只创建飞书文档,或创建文档后投递消息。

除按需调用外,本 skill 还承载无人值守的定时团队日报:launchd/com.lark-skills.daily-team-report.plist 每天 21:00 触发 launchd/run-daily-team-report.sh。入口调用 scripts/run_daily_report.py,固定统计北京时间前一天 21:00 到当天 21:00(使用机器本地时区),重试不会移动窗口。脚本采集数据,codex exec 只改写本地正文,随后脚本校验、以 bot 身份向负责人私发 Card 2.0 卡片,并以 bot 身份插入既有 lark.daily_log_doc 文档最前。

运行记录保存在 gitignored 的 .state/daily-report/<窗口结束时间>/,包含原始数据、逐仓缓存、正文、发送回执和留档状态。采集失败只重试缺失数据;消息已发但留档失败时只补留档。成功依据是实际 Lark JSON 回执及消息/文档回读,不从 Codex 日志匹配 om_ 字样。不要删除未完成运行的状态目录。

若出现 Unconfirmed archive insert,说明留档请求可能只写入了部分内容,脚本会停止自动插入。先核查目标文档:已写入的内容应补齐并保留该窗口的统计标识,再用 --deliver-only 回读确认;只有确认完全没有写入时,才可移除 state.json 的 archive_attempted 字段后重试。保留消息回执和其他状态,避免重复发送。

补发:./launchd/run-daily-team-report.sh --range 'YYYY-MM-DD 21:00至YYYY-MM-DD 21:00'。预览:加 --prepare-only 只采集并生成正文,不投递;已准备正文的投递可用 --deliver-only。同一窗口重复运行复用状态;历史漏发日期必须显式指定窗口,不能用执行当时的“过去24小时”替代。独立调用本 skill 的时间范围与输出模式仍按下面规则执行。

定时日报卡片

定时入口采用Card 2.0:蓝色标题,日期与截至时间放在标题区,正文分为今日重点、默认展开的成员进展和可选需关注。每位活跃成员写 1–3 条「事项|状态:数据、进展与下一步」,零活动成员由程序合并一行。程序从 raw.stats 添加个人 PR 状态数;日报不重复统计窗口、历史快照、仓库排除和去重方法等固定说明。细节通过事项 PR 链接追溯。

固定布局由 scripts/daily_report_card.py 生成,Agent 只写正文。--prepare-only 同时生成 card.json 供核对;定时入口只处理当前统计数据并发送卡片;失败重试按内容摘要、发送回执与幂等键恢复。历史重算独立手动运行,输出到新目录,不在定时入口升级旧数据或恢复旧消息格式。飞书文档继续留存可阅读的 Markdown 正文。

Prerequisites

依赖验证命令
lark-clilark-cli auth status;仅 message_only、doc_only、doc_and_message 需要
GitHub tokengh auth status 或环境变量 GITHUB_TOKEN
python3 + ruamel.yaml./scripts/python.sh --check

Input

支持两种同步维度。

时间范围模式:

  • 过去24小时 / 24h → 此刻往前推 24 小时(交互查询使用;定时日报入口另行冻结 21:00 到次日 21:00 的窗口)
  • 今天 → 今天 00:00 到现在
  • 昨天 → 昨天 00:00 到 23:59
  • 本周 → 本周一到今天
  • 上周 → 上一个完整 ISO 周
  • 最近 N 天 → 最近 N 天
  • 未指定 → 使用 config.yaml 的 report.default_days,默认 7 天

PR 模式:

  • GitHub PR URL:https://github.com/org/repo/pull/123
  • 简写:org/repo#123
  • 只有一个 github.repos 时可只写:#123 或 123

当用户说“这个 PR 做了什么”“同步这个 PR 的进度”“根据当前 PR 写汇报”时,优先使用 PR 模式,而不是时间范围模式。

输出模式:

  • local:只生成进度报告或可复制消息,不调用飞书 API;默认模式
  • message_only:只发送一段平白的飞书消息,不创建文档
  • doc_only:创建飞书文档并处理权限,不发送消息
  • doc_and_message:创建飞书文档、处理权限,并发送带文档链接的消息

用户明确要求优先于配置:

  • 只说“生成/写/解释/同步进度”,但没有指定“发群、投递、创建文档”时,使用 local
  • 说“发到群、同步到群、投递消息”且没有要求文档时,使用 message_only
  • 说“创建飞书文档、生成文档”且没有要求发送时,使用 doc_only
  • 说“创建文档并发送、发带链接的进度同步”时,使用 doc_and_message

Execution Flow

Step 1: 读取配置

读取 skills/progress-report/config.yaml。默认配置通过 extends_config 继承 skills/weekly-report/config.yaml,避免重复维护:

  • github.repos
  • github.token
  • team.members
  • team.gitlab_to_github
  • lark.permissions
  • output.mode
  • delivery.targets

progress-report/config.yaml 中显式配置的同名字段覆盖继承配置。

输出模式按以下优先级确定:用户明确要求 > progress-report/config.yaml 的 output.mode > local。不要因为 delivery.targets 存在就自动发送消息,也不要因为配置了 lark.permissions 就自动创建文档。

Step 2: 采集代码进度

运行脚本生成 Markdown 报告和原始 JSON。

时间范围模式:

./scripts/python.sh skills/progress-report/scripts/collect_progress.py \
  --config skills/progress-report/config.yaml \
  --range "<今天|昨天|本周|上周|最近 N 天>" \
  --output /tmp/progress_report.md \
  --raw-output /tmp/progress_report_raw.json

PR 模式:

./scripts/python.sh skills/progress-report/scripts/collect_progress.py \
  --config skills/progress-report/config.yaml \
  --pr "<PR URL | owner/repo#123 | #123>" \
  --output /tmp/progress_report.md \
  --raw-output /tmp/progress_report_raw.json

脚本采集口径:

  • PR 的 updated_at 只用于发现候选;最终只保留窗口内新开、推入 commit、评审/评论、状态推进、关闭或合并的活跃 PR,忽略 head_ref_deleted 等维护事件
  • 活跃 PR 的提交从 GitHub PR commits 读取,因此 squash merge 或删除源分支后仍保留原始提交;先按 SHA 汇集活动证据,并排除已由原始提交代表的 synthetic squash/merge commit;随后读取完整 Git diff,以仓库和 保留空白的 patch-id(避免误合并空白敏感代码) 去重,普通合并提交单列,跨日重复关联先前已审计快照。作者时间早于窗口的改动单列为历史活动,不当成当天新编写,也不据此断言重复劳动
  • 默认扫描所有现存分支(report.include_all_branches: true):GraphQL 按仓库每页 30 个分支批量读取窗口内提交;分支和提交均完整分页,不再受旧 max_branches_per_repo 限制。PR 原始提交及活动证据继续使用 REST,列表分页遇到窗口外日期立即停止。默认 3 个仓库 / 4 个 PR 并发,单请求支持超时、截断响应和暂时性服务错误重试。可用 --cache-dir 复用相同窗口的成功采集结果;任何仓库失败都会明确报错,不把缺失数据写成零活动。
  • 通过 report.excluded_repos 配置排除列表,默认不排除仓库。report.local_git_root 可复用本机仓库只读对象,缺失 SHA 仅 fetch 对象;否则使用 .state/progress-evidence 内的 bare 仓库。完整 diff 获取失败即停止,不能退回 SHA 数冒充去重结果。
  • raw.stats 是数字唯一来源。分类按文件区分业务代码、测试、CI/构建、文档、运行配置/其他;混合补丁可跨类,不能相加。补丁数仅用于审计,不代表功能或工作量,语义改写、拆分及未关联 squash 不承诺自动判重。
  • PR 分开统计窗口内新建、合入 main/master、合入开发分支、关闭未合并,以及采集快照中本期活跃且仍开放的 PR。新建与合并可重叠;进行中不是全仓 backlog。窗口使用左开右闭,避免整点跨日重复。
  • raw.groups 按真实堆叠分支连接提供事项归组证据;结合明确 Issue 关联和描述归并同一事项,不凭相似标题强行合并。先写事项、目的、交付状态、待确认。统计分类和去重审计仅保存到本地 statistics.md,卡片的个人 PR 状态数据由程序生成。正文不以提交数或 PR 总数开头,不按数量排名成员。
  • 历史回算使用 scripts/replay_daily_report.py <原始 raw.json...> --output-dir <独立目录>,按时间顺序处理,前置基线窗口供跨日去重;不覆盖已发送日报或回执。重算输出记录历史窗口和补丁证据。
  • PR 模式只采集该 PR 的 commits、files 和 PR 状态,不受时间范围限制
  • 只保留能匹配团队成员 GitHub login 或 extra_emails 的提交
  • 报告必须只使用采集到的数据,不能编造

Step 3: Agent 叙事改写

读取 /tmp/progress_report.md 和 /tmp/progress_report_raw.json,把脚本生成的事实底稿改写成团队能直接理解的进度同步。生成两类内容:

  • 完整报告:适合本地输出或飞书文档,保留必要证据
  • 简短消息:适合直接发群或回复用户,先讲结论和意义,少放技术细节

完整报告默认结构:

# 项目进度同步 (<scope>)

## 结论
用 1-3 句说明现在进展到哪里,以及这次同步最重要的变化。

## 做了什么
用业务/工作流语言说明完成的事情,不要直接堆 commit 标题。

## 为什么这样做
说明选择这个方案的原因、取舍或规避的风险。

## 对工作流的意义
说明它让团队后续工作更顺、成本更可控、链路更可审计,或减少了什么阻塞。

## 仍需确认
只写真实不确定项,不能把猜测写成事实。

## 下一步
写清楚后续行动,不确定来源的行动项标注为“建议”。

## 代码证据
保留 PR、commit、文件范围等可追溯证据。

必须遵守:

  • 每个已完成事项都要能追溯到 commit、PR 或 PR file diff
  • “接下来”只能来自打开 PR、近期分支名、commit 标题中的明确线索,或标注为“建议”
  • 不确定的事项放到“待确认”,不要写成事实
  • 群消息优先讲人话:先讲结论,再讲原因,再讲意义,再讲下一步
  • 群消息必须让非工程背景的读者也能看懂:内部编号与行话(ADR / OQ / plan / CONTRACT / schema / executor / stage 等)一律转译成日常说法(如「架构决策」「生成器」「环节」)或直接省略,只允许出现在结尾的证据链接里;写完自查一遍,出现读者需要先查内部文档才能懂的词就是不合格
  • 群消息默认精简到 200 字上下、一屏读完;完整技术细节留给本地报告或飞书文档,不要都塞进消息
  • 不要把群消息写成 changelog、commit digest 或测试日志;SHA、文件清单、OQ 编号只作为证据或链接出现
  • 如果代码事实不足以支撑“为什么”和“意义”,保留为待确认或请用户补上下文,不要编造
  • 飞书 Markdown 正文禁止出现 ASCII ~。飞书会把它识别为删除线边界;PR 范围使用 – 或“至”,例如 [#48](...)–[#55](...)。

任何 Markdown 写入飞书消息或文档前,必须先保存为本地文件并执行:

./scripts/python.sh skills/progress-report/scripts/validate_lark_markdown.py --fix <markdown-file>
./scripts/python.sh skills/progress-report/scripts/validate_lark_markdown.py <markdown-file>

第二条命令退出码不是 0 时禁止投递;修正后重新验证。该检查同时适用于 message_only、doc_only、doc_and_message 和定时日报留档。

Step 4: 本地输出

当模式为 local:

  • 不调用 lark-cli docs、lark-cli drive 或 lark-cli im
  • 直接回复用户完整报告,或在用户要求文件时写入 progress_report.md
  • 如果用户要“可发群版本”,同时给出简短消息正文
  • 最终回复包含统计范围、数据来源和“未创建飞书文档 / 未发送消息”

Step 5: 创建飞书文档

仅当模式为 doc_only 或 doc_and_message 时执行。复用 lark-doc-deliver 的流程。把报告复制到当前工作目录,然后创建文档:

cp /tmp/progress_report.md ./progress_report.md
lark-cli docs +create \
  --title "项目进度同步 (<scope>)" \
  --content @progress_report.md \
  --doc-format markdown \
  --parent-token "<继承后的 lark.doc.folder_token>" \
  --as bot

从输出 JSON 提取:

  • doc_url: 优先 .data.document.url,兼容 .data.doc_url / .data.url
  • document_id: 优先 .data.document.document_id,兼容 .data.doc_id / .data.document_id

Step 6: 自动权限转移

仅当已创建飞书文档时执行。创建文档后必须立刻按 lark.permissions 配置执行权限转移。progress-report/config.yaml 默认继承 weekly-report/config.yaml,因此应直接使用继承后的 doc_owner_open_ids 和 bot_open_id。

如果 doc_owner_open_ids[0] 或 bot_open_id 为空,停止后续投递并报告配置缺失;不要发送只有 bot 可见文档的链接。

transfer_owner 和 permission.members.create 是 high-risk-write 操作,必须带 --yes,因为 owner 和 bot open_id 已由配置显式登记。

lark-cli drive permission.members transfer_owner \
  --params '{"token":"<document_id>","type":"docx","stay_put":"<stay_put>","remove_old_owner":"<remove_old_owner>","old_owner_perm":"<old_owner_perm>","need_notification":"false"}' \
  --data '{"member_type":"<member_type>","member_id":"<第一个 doc_owner_open_ids>"}' \
  --as bot \
  --yes

然后重新授权 bot:

lark-cli drive permission.members create \
  --params '{"token":"<document_id>","type":"docx","need_notification":"false"}' \
  --data '{"member_type":"openid","member_id":"<bot_open_id>","perm":"full_access"}' \
  --as bot \
  --yes

如 doc_owner_open_ids 有多个成员,再给其余成员授权:

lark-cli drive permission.members create \
  --params '{"token":"<document_id>","type":"docx","need_notification":"false"}' \
  --data '{"member_type":"<member_type>","member_id":"<open_id>","perm":"full_access"}' \
  --as bot \
  --yes

权限操作失败时记录错误;如果 owner transfer 失败,不要发送群消息,避免投递不可访问的文档。

lark.doc.folder_token 为空时停止创建,禁止回退到云盘根目录。stay_put 必须为 true;转移后先用 drive metas batch_query --user-id-type open_id --as bot 确认 owner_id 等于第一个 doc_owner_open_ids,再用 drive files list --folder-token <lark.doc.folder_token> --page-all --page-size 200 --as bot 确认 document_id 仍在其中。任一验证失败时不要发送消息。

Step 7: 消息投递

仅当模式为 message_only 或 doc_and_message 时执行。发送前检查 delivery.targets;如果没有目标,停止发送并把消息正文返回给用户。

message_only 的消息不包含文档链接:

**项目进度同步 (<scope>)**

同步一下 <项目/模块> 的关键进展。

我们现在完成了 <用平白语言描述的变化>。

这次选择 <方案>,主要是因为 <原因/风险/取舍>。

这对工作流的意义是:<影响>。

目前仍需确认:<不确定项>。

下一步:<行动项>。

doc_and_message 的消息包含文档链接:

**项目进度同步 (<scope>)**

同步一下 <项目/模块> 的关键进展。

我们现在完成了 <用平白语言描述的变化>。

这次选择 <方案>,主要是因为 <原因/风险/取舍>。

这对工作流的意义是:<影响>。

目前仍需确认:<不确定项>。

下一步:<行动项>。

[查看完整进度文档](<doc_url>)

发送到 delivery.targets:

lark-cli im +messages-send --chat-id "<chat_id>" --markdown "$(cat progress_message.md)" --as bot
lark-cli im +messages-send --user-id "<open_id>" --markdown "$(cat progress_message.md)" --as bot

im +messages-send --markdown 不支持 @file,必须用 $(cat file)。

Output

最终回复用户:

输出模式: <local | message_only | doc_only | doc_and_message>
进度文档: <doc_url | 未创建>
已投递: <target.name>, ... | 未投递
统计范围: <since> ~ <until>
数据来源: <repo list>

如有采集、权限或投递失败,列出失败点。

Key Rules

  1. 这是进度同步,不是周报;重点是“现在进展到哪里、接下来做什么”。
  2. GitHub 采集默认包含所有分支,除非用户明确要求只看默认分支。
  3. 用户提到具体 PR 时必须使用 PR 模式;不要用最近 N 天近似替代。
  4. 不要把未合并分支或打开 PR 写成“已上线”或“已合并”。
  5. 0 数据时不要编造,输出“该范围内未匹配到团队成员代码改动”,并建议检查仓库配置、GitHub 用户映射或时间范围。
  6. 默认不要创建飞书文档或发送消息;只有用户明确要求或 output.mode 指定时才执行外部写入。
  7. 飞书文档创建后必须自动 transfer owner,并重新授权 bot;权限命令必须带 --yes。
  8. 飞书文档、群消息及定时日报私聊统一使用 bot 身份;定时日报使用配置的曹有米 profile,由机器人向负责人发送。
  9. 群消息面向团队协作,不面向代码审计;把可追溯证据放进文档或本地报告,不要把第一屏写成提交清单。
  10. 群消息的验收标准是「没读过内部文档的人也能看懂」:默认 200 字上下,零内部行话与编号;发送前先给用户 review 一版,用户确认后再投递。
  11. 所有飞书 Markdown 投递前必须通过 validate_lark_markdown.py;PR 范围不得使用 ASCII ~。
  12. 创建飞书文档必须显式使用继承后的 lark.doc.folder_token;禁止落云盘根目录,转移所有权后必须回读所有者和目标文件夹验证。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.