loop-weekly-report
这是一个 loop skill(自动化循环),沉淀的是「怎么用定时 + headless AI 把自己一周的工作痕迹自动写成周报」的设计与去敏参考实现。真实运行需按
config.example.sh填本地配置,并把文档/通知层换成你自己的工具。
一句话:每周一自动读我上周和 Claude 的所有对话,归纳成一篇分类周报,建成云文档、归档进索引、把链接发我手机。 我不用再手写周报。
为什么值得自动化
周报的原始素材其实全在你一周的工作痕迹里(每个 session 干了什么、解决了什么、结论是什么),只是散、且回忆有偏差。让 AI 从结构化摘要里归纳,比人凭记忆写更全、更省时,还不容易漏掉长会话里真正的重头戏。
架构:三步流水线
- 提取(digest.py):扫过去一周
[上周一, 本周一)窗口内所有 session transcript,每个 session 压成一条结构化摘要——项目、时间、PR/issue 号、按首/中/末采样的多条用户消息、助手正文里的高信号行、子代理关键词命中、最终结论。 - 归纳(headless claude):
claude -p通读摘要,按固定大类(需求承接 / 稳定性排查 / 用户反馈 / 架构设计 / 基础组件 / 研发效能)归纳成 1000~1500 字周报 + 「下周重点」,创建云文档,并把 URL 用固定格式WEEKLY_DOC_URL=<url>打到 stdout 供脚本捕获。 - 归档(archive-to-index.sh):把这周的链接插到「汇总索引文档」锚点段落之后(最新在最上),再推通知。
关键设计决策与踩过的坑
- 采样别只取首条消息:早期 digest 只取「首条用户请求 + 末条助手回复」,结果续接会话和长会话的主线全丢——一个 session 聊了 5 个话题,只看到第一个。改成对去重后的真实用户消息按位置(首/中/末)采样,才抓得住主线。
- 子代理命中兜底话题漂移:真正的重活常常 fan-out 到 subagent 里做,主线程摘要看不到。所以额外扫每个 session 关联的
subagents/目录,统计领域关键词命中次数——命中高的关键词往往才是这个 session 的重头戏。这些关键词要按你自己的业务领域定制(脚本里给的是通用工程词)。 - 高信号行摘取:助手正文里含「上线/合入/事故/验收/压测…」这类里程碑词的行单独摘出,避免归纳时漏掉关键成果。同样建议按业务补词。
- URL 用固定标记回传:headless claude 建完文档后,约定用
WEEKLY_DOC_URL=<url>单独一行输出,外层脚本用grep -oE抓,比让模型「告诉我链接」稳定得多。这是让 headless AI 和外层脚本可靠交接结果的通用技巧。 - 锚点按关键词定位,不硬编码 block-id:归档时在索引文档里按锚点关键词找插入位置,而不是记死某个段落 id——文档结构一变,硬编码就失效。
- 数字必须来自素材、不许编造:prompt 里明确要求所有数字/结论/PR 号来自摘要文件;元操作类 session(讨论周报本身)和测试 session 不计入工作量。
- 单次喂给 headless 的输入必须有上界,体量涨了会静默炸:digest 随 session 数增长(观测:一周从约 200 KB 涨到约 310 KB 后,headless 在读文件阶段连续三次自动压缩后放弃——没建文档、没归档,只剩一条失败通知)。两层修法:① digest 先过噪声过滤——跳过 headless/自动化入口的会话、0 条真实用户消息的会话、只有几行的空壳(这些是 jsonl 里的结构化字段,判定确定);② 脚本改 map-reduce:外层按固定大小(如 ≤60 KB)切块,每块一次
claude -p只做"提炼成结构化工作项清单",再把几 KB 的条目拼起来喂最后一次claude -p写周报。上界由 shell 保证,不靠 prompt 里让模型"分块读"的自觉——炸掉那次就是模型自己选的块大小。仓库里的参考脚本仍是单次归纳版,切块与拼接按这个思路自行加。 - 换模型档位(省成本)时要同时核上下文窗口,并用真实体量复跑一次:把归纳阶段切到更便宜的模型后,第一次真实运行就在 reduce 阶段撑爆——输入没变,变的是新模型的上下文窗口更小,往期都过只因为往期跑的是大窗口模型。选档看三个维度:任务复杂度(巡检/播报类走轻量档,跨源推理与写代码保留强档)、输入体量(digest 大的选大上下文档位,或先把输入切小)、时效(loop 里内嵌的外部评审步骤按等待预算选快档,最强的那个往往最慢)。换档不是改一行配置就完,要拿最近一次真实大小的 digest 复跑通过才算切换完成。
- 确定性副作用收回 shell 层,模型的活到
Write为止:建文档 / 推通知 / 归档索引是确定性操作,放在 headless 会话尾部意味着模型只要在最后一步前炸掉,前面写好的正文就全丢。改成模型只负责把正文写成本地文件,shell 检测到文件即接手建文档、通知、归档——会话后半段再炸也不影响交付,失败时留下的正文还能人工补发。 - headless 会话的起步窗口要体检:不用的 MCP 工具定义会白占大半上下文:定位第二次撑爆时才发现,会话第一轮还没读任何文件,系统提示 + 挂载的 MCP 工具定义就吃掉了 200K 窗口的三分之二(两个与周报无关的 MCP server 合计约 88K token);再读几十 KB 条目、再让模型现场"学一遍"文档 CLI 的用法,必炸。周报这类流水线根本不用 MCP。规矩:① 定时 headless 任务默认以空 MCP 配置启动(
claude -p加--strict-mcp-config --mcp-config '{"mcpServers":{}}'),真要用哪个再显式挂哪个;② 用"只回一个字"的空跑看首轮 cache 体量,就是起步成本,换模型、加输入之前先看它还剩多少;③ 固定不变的用法(文档 XML 格式、通知命令)写死进 prompt 或收回 shell,不让模型每周重学一遍。同一套 cron 家族(日报复盘、各类盯守)都背着同样的起步成本,只是还没炸——修一处时顺手把全家改掉。 - "换便宜模型省成本"要以网关/账单侧的实际应答模型核实,别信 CLI 回显的键名:切档五天后查代理请求日志才发现,请求的便宜模型被上游网关静默路由回了原来的强模型——几十条请求无一例外——所谓省 20 多倍一分钱没省;当初对比出的成本差其实是两次探测的 cache 体量差,不是单价差。带大窗口后缀的模型名同理:CLI 侧按大窗口推迟自动压缩,上游真实窗口没变,输入一超就不是压缩而是硬失败。规矩:验模型看代理/账单日志里"实际应答模型"那一列(或响应头),成本对比按同一 cache 体量做;切档后至少一次真实运行用这个方法核过才算切成。
- 定时交付物已知坏了,下次触发前必须闭环,与拍板无关的必做修复不等拍板:周报连续两个周一失败。第一次失败当天就诊断清楚、修了一半;第二天把剩余修复清单连同"用哪个模型"的选择题一起发给用户等拍板,清单里已经标了"这条独立于模型选择,必做"——但整份清单都跟着选择题一起等了六天,第二个周一到点又以同一个报错失败,用户在开会前发现"今天的周报没有成功生成"。规矩:① 必做且与待决问题无关的修复当天落地,拍板请求里只留真正需要用户选的那一项;② 修完用最近一次真实体量的 digest 跑一遍
DRY_RUN(不建文档、不推通知),各阶段零自动压缩、产物结构自检通过才算修好;③ 有硬消费时刻(周一开会)的交付物,把失败发现时刻往前挪:正式触发前一晚先跑一次DRY_RUN校验(或把正式触发提前到消费时刻前几小时),脚本支持手动指定窗口补跑,失败通知里直接带补跑命令与诊断入口——两次失败当天都推了 ❌ 通知,但通知到达时用户已经在要用它的那一刻,余量为零。
脱敏红线
- 署名、租户域名、文档 ID 全部外置到 config,仓库里只有占位符。
- 业务领域关键词(gems/coins/内部功能名之类)不进仓库——脚本里只放通用工程词,你在本地 config 化的 digest 里自己加。
- 周报正文由 AI 从你的私有 session 生成、发到你自己的云文档,不经过这个公开仓库;仓库里只有生成它的脚本骨架。
需要你自备/替换的东西
- 云文档 CLI(
$DOC_CLI):创建/更新文档、按 block 插入内容。参考实现依赖一个私有 CLI,未随仓库分发——archive-to-index.sh里用伪代码 + TODO 标出了你要补齐的 4 步。 - 通知渠道(
$NOTIFY_CMD):把链接推到你的 IM/邮件。 - 索引文档:一篇带锚点段落的「周报汇总」文档,新链接往锚点后插。
安装与自检
./install.sh init-config # 生成 ~/.config/loop-weekly-report.sh
$EDITOR ~/.config/loop-weekly-report.sh
./install.sh doctor # 自检依赖与配置
./install.sh install-cron # 装 crontab(每周一 11:00)
与其他 skill 的边界
- 本 skill 管「每周归纳」。要按天做「日记 + 自我改进项」复盘,见
loop-daily-retro;要让 skill 库自己进化,见loop-skill-optimizer。三者共享「cron + headless claude + digest 提取 + 去敏配置外置」的同一套范式,但产物和窗口不同。