# Daily Recap

> 将所有机器上的 Pi 和 OMP 会话整理成主题聚合的结构化日报，写入 Obsidian 工作日志或个人日记。

- Skill: `cnife/daily-recap` (Agent Skill, multi-file: 10 files)
- Install (CLI): `npx skillmds@latest add cnife/daily-recap`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cnife/daily-recap/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: cnife (https://skillmd.com/u/cnife)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cnife/daily-recap

---


# Daily Recap - 每日工作整理

将所有机器上的 Agent 会话整理为一份**主题聚合**的日报，写入 Obsidian 工作日志或个人日记。

**nmem 是 source of truth**：多台机器上的会话通过 nmem 同步，覆盖全部机器的全部会话。会话的唯一来源是 nmem，不区分本地/远程。

流程：选日 + 列举候选 → **归类审查（唯一人工门）** → 收集 + 聚合 → 条件核验（静默）→ 写入 + 一行报告。执行期保持安静，只在归类审查和写入报告两处出声。

## 流程

### 1. 选日 + 列举候选

**确定目标工作日**：工作日窗口以 CST 04:00 为界 [工作日 04:00, 次日 04:00)，凌晨 00:00-04:00 的会话归前一工作日。"总结哪个工作日"以 12:00 为界（<12:00 昨天 / ≥12:00 今天），由脚本按 recap 时刻自动选择。

```bash
cd <skill目录> && uv run --script scripts/extract_today.py
```

拿到 `date` 后回显一行：「整理目标工作日：{date}（脚本自动选择，改期用 `--date`）」。整理历史日期才显式传 `--date YYYY-MM-DD`。

**列举候选**（nmem 是唯一来源）：

```bash
nmem threads list --limit 200 --json | uv run --script scripts/extract_today.py --filter
```

脚本按 UUID v7 时间戳（线程 id 前 48 位 = 会话开始时间毫秒戳，见 CONTEXT.md「线程 ID 时间戳」）把线程分成三组：

- `candidates`：窗口内非机器线程——进入归类审查
- `machine`：窗口内机器会话，按标题族分组（`advisor` advisor 镜像 / `subagent` 子代理任务 / `recap` 上一轮 recap 自身及子代）——默认跳过，**跳过必留痕**：归类审查消息里带一行计数备注（如「另跳过 31 条机器会话：advisor×16、子代理×12、上轮 recap×3」）；用户点名可捞回
- `excluded`：窗口外线程——不处理

机器标题族在脚本里维护；新形态的机器会话照常进候选，确认后补进脚本。

**分页**：`nmem threads list` 排序不是严格日期序（按导入批次混杂），`--offset` 递增翻页，每页管道 `--filter`，直到连续多页无窗口内候选才停；翻页范围在归类审查消息里一行带过。

**其余过滤**：消息数 <10 的候选多为测试探针，聚合成一行备注（数量 + 特征），不逐条进表。**留痕原则**：窗口内每个线程要么进候选表、要么在备注里有据可查——包括机器会话与 stub，不允许静默消失。

**空集**：candidates 为空时告知「目标工作日没有会话记录」并终止。不得用「当前会话应在窗口内」反证——12:00 前跑 recap 时目标工作日是昨天，当前会话必然在窗口外，反证前提恒不成立。

**降级**：nmem CLI 连接失败/超时（退出码非 0，stderr 报 connecting/timeout）→ Hard stop，见 `references/recovery-guide.md`。

### 2. 归类审查（HITL · 唯一人工门）

把 `candidates` 整理为候选条目表，**直接按主题域分组**，机器/stub 跳过备注随表附上：

| # | 会话主题 | 主题域 | 去向 | 理由 |
|:-:|----------|--------|:----:|------|
| 1 | HPC 巡检 | genome-assembly | 工作日志 | 之江实验室日常工作 |
| 2 | 双语 HTML 转换 | learn-mattpocock | 不记录 | 个人练习，无产出变化 |

去向：`工作日志` · `个人日记` · `不记录`

呈现给用户确认——**这是全程唯一的人工交互**。用户修正去向或标记跳过后，仅批准的条目进入下一步。

### 3. 收集 + 聚合

#### 3a. 扇出 recap-collector 收集事件

批准后**按主题域**扇出（一个主题域一个 collector，包揽该主题下所有会话；主题域超过 6 个也先全部收集——合并发生在 3b，不预先砍）。collector 读 nmem 线程，蒸馏成**事件**（选骨架、填字段、带来源指针），返回结构化文本证据包。写入由主 agent 独占。

> collector 的角色、统一接口与降级策略见 `agents/recap-collector.md`；task 按 `references/collector-task-template.md` 填充（主题域 / 目标工作日 / 技能目录 / 会话清单 / 重点核实项，**不传去向**）。

**异常处置**（不静默、不硬写、不打断）：

- collector 发现窗口外线程或读取失败：跳过并记入「遗留」清单
- 会话未完成但内容有效（如 CI 修复在结论落地前截断）：标注「未完成」，只写已确认的部分，不把未验证的意图写成既成事实
- 某批准主题域整体无法落地：写入报告里点名，补不补由用户决定

#### 3b. 聚合写作

collector 返回的**事件**（非会话摘要）是输入。对批准条目做**主题聚合**：

1. 语义相近的事件合并到同一主题域
2. 同一主题下的多个事件 → 1 个标题 + 子 bullet 展开
3. 每个子 bullet 1-2 行，只写结论和决策
4. 排序：部署/功能交付在前，基础设施/配置在后，探索/学习最后
5. 不超过 6 个主题域（理想 3-5 个）；无零散单事件段落

事件骨架（collector 已选型填字段，成文时照此展开）：

- **功能**（实现了功能）：功能名称 + 核心特性 + 关键技术决策
- **修复**（修复了问题）：问题 + 根因 + 修复方式
- **决策**（做了决策）：决策内容 + 理由 + 放弃的替代方案
- **调研**（调研了方案）：调研对象 + 结论 + 选型判断（为什么选 A 不选 B）
- **部署**（部署/配置）：环境 + 关键参数 + 验证结果
- **验证**（验证假设/回答问题）：原始问题 + 验证方法 + 结论 + 下一步含义

**学到什么**：事件带可复用结论（根因/选型判断/下一步含义/决策理由）才点出；纯交付（功能/部署）无可复用结论不硬编。

**数据密集判定**：bullet 含可核对的具体数字/参数/验证结果 = 数据密集，触发第 4 步核验；纯定性（决策理由、调研结论）跳过。按 3b 输出 bullet 判定。

**写作规则**：

1. **来源可追溯（硬约束）**：每条 bullet 能追到证据包来源（`thread_id#消息index`）。写不出来源的句子不写——不写「根据习惯」「一般来说」这类无来源内容。
2. **按主题聚合**：按主题域组织而非按时间平铺；证据不足的主题域剔除或补收集，不带病进写入。
3. **去掉流程噪音**：不写 agent 操作日志与内部项目标签——会话全景表、消息量、Git 提交、验证流程、阶段标记、配置路径，以及内部项目标签（map/ticket/issue 编号、里程碑、生命周期阶段）。写「产出了什么结论」，不写「完成了什么任务」。

输出模板（标题层级遵循 `references/diary-rules.md` 变体规则，文件名已含日期，文件内一级标题是主题/子系统，不重复日期标题）：

```markdown
# 主题域（work: 子系统名 / personal: 主题标题）

- 关键事件 bullet...
- 关键事件 bullet...
```

### 4. 条件核验（静默）

对**数据密集 bullet** 扇出核验 subagent：对着证据包原文逐条核对数字、百分比、公式、口径；纯定性 bullet 跳过。

- `agent: reviewer`；task = 证据包原文 + 待核验 bullet 清单（每条含声称的数字和来源出处）
- 核验报告逐条给出结论（一致 / 修正为 X，依据来源 Y）
- 不一致 → **按来源静默修正**（数字、口径以来源为准），修正处数记入写入报告；来源无法裁决的条目从终稿剔除并记入报告。**不打断用户。**

### 5. 写入 + 一行报告

**变体**：按候选表去向定 work/personal（规则见 `references/diary-rules.md`；混合内容拆分分别写入）。

**日记上下文**：

```bash
cd <skill目录> && uv run --script scripts/obsidian-helper.py --vault <work|personal> --date YYYY-MM-DD
```

输出 DIARY_PATH/DATE、RECENT（近期 2-3 篇日记，了解写作风格）、TODAY（今日日记全文；不存在时自动从模板创建）。**始终传 `--date`**（用第 1 步的目标工作日）。首次配置：`CONFIG_MISSING=true` 时按打印的示例创建 `~/.config/cnife-skills/obsidian-diary.json`，询问用户 vault 根目录后填入，重新运行脚本。

**补全式整合写入**：先读后写，基于 TODAY 全文补全不覆盖——已有章节末尾追加 bullet，不重写已有内容；新章节插到已有章节之后，按重要性排序；用 Edit（patch）工具写入。

**一行报告**（就此收尾，不再请用户读终稿）：「已写入 {变体} 日记（{date}）」；有核验修正或遗留项时追加一句（如「核验修正 2 处」「遗留：1 条读取失败未纳入」）。准确性兜底 = 来源可追溯 + 静默核验 + 用户日常浏览时顺手改。

## 参考

- 收集任务模板 -> `references/collector-task-template.md`
- 日记格式规则 -> `references/diary-rules.md`
- 故障恢复 -> `references/recovery-guide.md`

