- name
- auto-diary
- description
- 自动化日记生成和四层聚合(日/周/月/年)。cron 定时触发:每日日记(23:00)、每周周报(Mon 09:00)、
每月月报(1号 09:30)、每年年报(1/1 10:00)。采集天气(Open-Meteo)、日历(icalBuddy)、
AI 对话(Hermes state.db + CC JSONL)、知识库变更(Obsidian vault + jz-skills git commits)、钉钉班级群消息(dingwave 解密本地 DB),经校验闭环交付。
支持日历事件回填和日记清理。详见知识库 [[日记系统-三机架构与路线图]]。
Use when: cron triggers or user manually requests
生成日记 / 生成周报 / 生成月报 / 生成年报 / diary / weekly / monthly / 补日程 / 整理日记.
DO NOT use for: general note-taking, non-diary content generation, one-off research.
- type
- routine
- version
- 3.8.2
- author
- Hermes Agent — v3.8.2 跨运行时架构 + Codex v2.1 富提取 · v3.8.1 JSONL 双源修复 · v3.8.0 新增 Codex 会话采集 + 去重 cron ID + 文档漂移修复 · v3.7.0 git diff 扫 vault 删除 + git log 扫 jz-skills 提交 · v3.6.3 pwd.getpwuid() 绕过 cron HOME 污染
# Auto-Diary v3.8.0
自动化日记生成 + 四层聚合(日/周/月/年)。Cron 定时触发或手动调用。
> ⚠️ **真实调度状态**(2026-06-04 核实):**4 个 auto-diary cron 全部存活**。
>
> | job_id | 任务 | schedule | scheduler | 聚合源 | 状态 |
> |--------|------|----------|-----------|--------|------|
> | `a68f4f81b3ee` | 每日日记草稿 | `0 23 * * *` | cron-worker | 当日 Hermes+CC+Codex+vault+cal | ✅ |
> | `4f5b5607912d` | 每周周报 | `0 9 * * 1` | cron-worker | 上周 7 篇日记 | ✅ |
> | `59a992daaa55` | 每月月报 | `30 9 1 * *` | cron-worker | 当月日记 | ✅ |
> | `b6659cd1c94c` | 每年年报 | `0 10 1 1 * *` | cron-worker | 去年 12 篇月报 | ✅ |
>
> **聚合金字塔**:日←采集 · 周←日 · 月←日(避开 ISO 周跨月)· 年←月。每个 cron 内置校验闭环。
>
> **v3.6.0 关键修复**:
> - 🔴 **HERMES_HOME 污染**:`_get_state_dbs()` 改用 `Path.home()/.hermes` 硬编码,不再依赖 `HERMES_HOME` 环境变量。修复 cron-worker profile 下只扫到 cron-worker 自己 state.db、漏掉 regent/default 会话的问题
> - 🔴 **校验脚本假阳性**:新增三问答案深度检查——Q1/Q2/Q3 答案不足 20 字或仅占位符 `(无)` `(待补充)` 即判 FAIL
> - 🔴 **Cron prompt 精简**:去掉内联指令,改为引用 skill,使用绝对路径
>
> **v3.6.1 修复**:
> - 🔴 **dingwave 超时**:DingTalk 班级群 cron (458bec58ee72) 报 120s timeout。改用 `-export-only -merged-out`,解密完即退出
>
> **v3.6.2 修复 (2026-06-07)**:
> - 🔴 **管线 stdout 混合文本崩溃**:`dingtalk-media-pipeline.py` 的状态日志和 JSON 数据混在 stdout,monitor 脚本用 `json.loads()` 解析混合文本炸了。`set -euo pipefail` 把非零退出放大成脚本级崩溃。修复:(1) 管线所有状态输出切到 stderr,stdout 只留纯 JSON;(2) monitor 脚本增加 `|| true` 防护 + 从混合文本里智能提取 JSON 数组
>
> **v3.6.3 修复 (2026-06-07)**:
> - 🔴 **Path.home() 被 cron HOME 环境变量污染**:v3.6.0 声称用 `Path.home()` 绕过 HERMES_HOME 污染,但 cron-worker profile 启动时 **同时覆盖 HOME 到 chroot**,`Path.home()` 返回 chroot 路径而非真实 HOME。chroot 内无 state.db、.claude、Documents,导致 Hermes/CC/Vault 三项数据全为 0。这是静默故障——cron status 'ok',日记文件存在且格式完整,但数据全是空的。修复:`extract_hermes_conversations.py` 和 `collect_data.py` 新增 `_real_home()` 函数,使用 `pwd.getpwuid(os.getuid()).pw_dir` 读系统 passwd 数据库,彻底绕过所有环境变量。验证:6/6 日记从 2920 字节(Hermes=0/CC=0/Vault=0)重写为 7422 字节(Hermes=36/CC=5/Vault=1),校验 PASS。
## 🚨 Red Flags: Don't Skip the Diary Rules
| Excuse | Why it's wrong |
|--------|---------------|
| "I'll just write a quick summary, the user won't notice" | Diary format is strict: 10 sections required. `verify_diary_compliance.py` 强制校验 13 项结构(含三问三条齐全、CC 三组、各体系 info callout、底部 --- 分隔)。Missing = 不合格,必重写。 |
| "The calendar events are empty, I'll skip that section" | Empty calendar ≠ skip. Must write "当日无日历事件" placeholder. |
| "I'll quote the user's exact words, it's more accurate" | 🔴 **Iron rule**: NEVER quote user's raw messages. Summarize. "讨论了视频分析" not "帮我看下这个 bilibili 视频". |
| "Existing content is just a template, I'll overwrite it" | Check existing_content first. If user has written anything, merge — keep user content, fill gaps only. |
| "icalBuddy returned empty, must be a bug" | icalBuddy silently returns empty on calendar name mismatch. Diagnose before assuming no events. |
| "I'll just pick the top 2-3 topics, the rest are noise" | 🔴 **Exhaustive coverage** (v3.0): EVERY topic in `ai_logs.*.topics` must appear in the diary. List all first, cluster by category (📖知识输入/🔍技术调研/📝文档管线 etc.), then write. Cross-check raw session data if overview seems thin. Busy days (10+ streams) → at least 3-4总结项. |
| "🦞 is Claude Code, I'll use that emoji" | 🔴 **🦞 = OpenClaw, NOT Claude Code**. CC has no fixed emoji; diary uses 💻 for CC. Hermes = 🐴. Mixing these up frustrated user. |
| "Callouts look cleaner folded, I'll use `> [!info]-`" | 🔴 **No folding callouts** (v3.0): user rejected `-` suffix. All callouts MUST be expanded — `> [!abstract]`, `> [!info]`, `> [!tip]`, `> [!note]`. Never use `> [!xxx]-`. |
| \"CC sessions are all the same, I'll list them flat\" | 🔴 **CC three-type split** (v3.2): 🤝 Agent Team 协作 / 💻 独立对话 / 🤖 程序调用。Group by type THEN by project, per-project topics. Data in `claude_overview.agent_team`, `.standalone`, `.program_call`. Classification uses CC native metadata (entrypoint + parentUuid), not text matching. |
| \"Codex sessions are all guardian noise, I'll skip them\" | 🔴 **Codex blind spot** (v3.8.0): Codex sessions were completely absent from diaries before v3.8.0. Data source: `~/.codex/state_5.sqlite` → threads table (Unix timestamps) AND `~/.codex/sessions/YYYY/MM/DD/*.jsonl` (v3.8.1 双源). Three-type split: 💻 独立 (vscode) / 🤝 Guardian (subagent) / 🤖 程序 (exec/cli). Guardian 会话虽多是审批 noise,但也有实质性运维会话(如 skill 中心化治理)。不能整体跳过。v3.8.2: 每条独立对话必须有时间、消息数、轮次数、2-4 行具体描述和 🔗 跨运行时联动标注。 |
| \"I'll group all Codex sessions into one summary line\" | 🔴 **Codex 信息过薄** (v3.8.2): 凭记忆写日记导致 Codex 被压缩为一行(如"Agent Skills 自动化 (7)"),丢失 729 消息 19 轮的深度审查会话、8922 消息 96 轮的需求分析会话。正确做法:`extract_codex_conversations.py` v2.1 提取每条会话的消息数/轮次/用户话题/助手行为摘要,逐条展开写。日记格式见 `diary-format.md` v3.3。 |
| \"The AI sections are independent silos\" | 🔴 **跨运行时盲区** (v3.8.2): Hermes、Codex、CC 在同一任务线上协作,但旧格式把它们写成独立段落。v3.8.2 新增 `🔗 跨运行时协作主线` note callout——从三段数据中提取端到端链路(发起方 → 审计/执行 → 交付物),用 `→` 展示。CC 和 Codex 段落内的项目也需标 `🔗` 联动标注。 |
| "Knowledge base changes are independent" | 🔴 **KB ↔ AI linking** (v3.1): Every vault change was produced by an AI session. Cross-reference `vault_changes` paths/titles with session topics. Group by source system (🐴/🏛️/💻). Unreliable matches → mark `(推断)`. |
| "I'll batch-generate all 31 diaries with a Python loop, it'll be fast" | 🔴 **批量生成 = 垃圾** (v3.2): 用户明确拒绝模板填充式批量生成。正确做法:逐条处理,用 cron 输出摘要的叙事做底子,三问必须有洞察力。详见 `references/batch-generation-pitfall.md`。 |
| "I've written diaries before, I know the format — no need to load diary-format.md" | 🔴 **NEVER write from memory** (v3.3): 凭记忆写日记导致 2026-06-02 全月重写——用户发现缺失 info callout、段落合并、三问缩写、CC 未按三组拆分、底部分段拍扁、tip 格式错误。教训:写或重写任何日记之前,**必须** `skill_view(name='auto-diary', file_path='references/diary-format.md')` 加载格式 spec,逐段对照写。记忆不可信。 |
| "The cron job status says 'ok' and diaries are being produced, so it must be working" | 🔴 **Status 'ok' ≠ skill loaded** (v3.5): cron 即使 `skills: []` 空数组也会以 status 'ok' 运行——用自己的裸 prompt 产出退化日记。日记文件存在≠质量合格。症状:CC=0、知识库变更=0、三问空洞、裸模板。**必须用 `cronjob list` 或 `hermes cron list` 确认 `Skills:` 字段非空**。2026-06-02~04 三日日记崩塌根因即此。 |
## 🔀 Decision Tree
```
Trigger received (cron or manual)?
├── Manual "生成日记" / cron daily (23:00) → Workflow A: Daily Diary
├── Manual "生成周报" / cron weekly (Mon 09:00) → Workflow B: Weekly Report
├── Manual "生成月报" / cron monthly (1号 09:30) → Workflow E: Monthly Report
├── Manual "生成年报" / cron yearly (1/1 10:00) → Workflow F: Yearly Report
├── Manual "补日程" / "日历事件没记" → Workflow C: Calendar Backfill
├── Manual "整理日记" / "清理日记" → Workflow D: Diary Cleanup
└── Ambiguous → Ask user which workflow
```
## Workflow A: Daily Diary
1. Determine target date (default today)
2. Run: `python3 {baseDir}/scripts/collect_data.py diary YYYY-MM-DD`
- Returns: `vault_changes` (find-based), `vault_deletions` (git diff), `jzskills_commits` (git log), plus weather/ai_logs/calendar/dingtalk
3. Check calendar with icalBuddy using calendars `个人1,工作1,Naomi1,Zelda1` (iCloud `<email redacted>`)
4. **🔴 知识库双源** (v3.7.0): 日记的知识库部分必须同时呈现 Obsidian vault 变更(含 `vault_deletions`)和 jz-skills git commits。两者都做 AI 会话关联
5. Read format spec: `{baseDir}/references/diary-format.md`
6. **🔴 Cron health check** (v3.8.0): Run `hermes --profile cron-worker cron list | grep a68f4f81b3ee`. If the daily diary cron job_id is absent from the cron-worker scheduler, note it in the diary's 临时笔记 section and report it in the final response. The config archive at `config/cron-job.json` still holds the correct parameters for reconstruction.
7. Generate diary with 10 sections: 🎯每日总结(三问) → 🌤️概览(weather+mood) → ⏰时间线(calendar) → 🤖AI工作记录(📊全天AI活动概览 callout → 🔗跨运行时协作主线 callout → 🐴助理体系 → 🏛️治理体系 → 🤖Codex → 💻CC) → 📚知识库更新(含 Obsidian vault + jz-skills git commits) → 📅日历事件(detailed table) → 🏠个人生活(placeholder) → ✅待办 → 📝临时笔记 → 💡tip 页脚
- 🔴 **v3.3 必须 callout**(C1 修复):`🤖 AI助手工作记录` 章节开头必须先有 `> [!info] 📊 全天AI活动概览` 和 `> [!note] 🔗 跨运行时协作主线` 两个 callout,再接四体系。漏写会被 `verify_diary_compliance.py` 判 FAIL。
8. **CRITICAL 合并安全**: `collect_data.py` 的 `existing_content` 恒为 `null`(已知限制,脚本不读已有日记)。所以写入前**必须先 `Read` 目标日记文件**;若已存在用户手写内容 → 合并,保留用户文字,只填空缺。不可盲目覆盖。
9. **校验闭环**: 写完后运行 `python3 {baseDir}/scripts/verify_diary_compliance.py <写入的文件>`;若 FAIL,对照 `diary-format.md` 逐项重写,直到 PASS 再交付
10. Write to Obsidian vault
11. **日记入记忆** (v3.6): 校验 PASS 且写入 vault 后,把日记写进 supermemory `hermes` 池,让小黄(default profile)能检索每天的日记。
`~/.hermes/hermes-agent/venv/bin/python {baseDir}/scripts/write_diary_to_supermemory.py <写入的日记文件绝对路径>`
- ⚠️ **必须用 venv python 绝对路径**(系统 `python3` 缺 supermemory SDK 会 skip)。**不要用 `~/.hermes/...`**——cron-worker profile 下 `~` 会解析到 chroot (`~/.hermes/profiles/cron-worker/home/`),venv python 根本不存在。必须用 `~/.hermes/hermes-agent/venv/bin/python` 硬编码全路径。
- 幂等(`custom_id=hermes-diary-<date>`,重跑覆盖不重复)、失败不阻塞交付、走 Surge 代理避开 fake-ip。
- 这是绕过 memory provider 对 cron session 写入限制(`_write_enabled` 排除 cron)的唯一途径——日记 cron 不会自动 capture。
12. Notify user (cron: via final response; manual: via Telegram)
See `references/diary-format.md` for weather codes, calendar table format, and section templates.
## Workflow B: Weekly Report
> cron `4f5b5607912d`(cron-worker profile)每周一 09:00 自动跑。也可手动(`生成周报`)。
> 🔴 `collect_data.py weekly` **未实现**(返回 not implemented)——直接 Read 日记,不依赖采集脚本。
1. 算上周 ISO 周范围: `python3 -c "import datetime as d; t=d.date.today(); mon=t-d.timedelta(days=t.weekday()+7); sun=mon+d.timedelta(days=6); iso=mon.isocalendar(); print(f'{mon} {sun} {iso[0]}-W{iso[1]:02d}')"`
2. Read 这 7 天日记(`01_日记/YYYY-MM-DD.md`,已归档的在 `归档/YYYY-MM/`)
3. Read: `{baseDir}/references/weekly-format.md`
4. 合并安全:先 Read 目标周报,保留用户手写内容
5. 按 5 维分析生成,写 `02_周报/YYYY-Www周报.md`(ISO week,如 `2026-W22周报.md`)
6. 🔴 校验闭环: `python3 {baseDir}/scripts/verify_report.py <文件>` → FAIL 重写到 PASS
## Workflow E: Monthly Report
> cron `59a992daaa55`(cron-worker profile)每月 1 号 09:30 自动跑。聚合源:**当月日记**(月←日,避开 ISO 周跨月)。
1. 算上月: `python3 -c "import datetime as d; t=d.date.today(); print((t.replace(day=1)-d.timedelta(days=1)).strftime('%Y-%m'))"`
2. Read 该月所有日记(根目录 + `归档/YYYY-MM/`),🔴 直接读日记不依赖采集脚本
3. Read: `{baseDir}/references/monthly-format.md`
4. 合并安全 → 生成 `06_月报/YYYY-MM月报.md`(从每日三问提炼跨日主线,不流水账)
5. 🔴 `verify_report.py <文件>` → PASS 才交付
## Workflow F: Yearly Report
> cron `b6659cd1c94c`(cron-worker profile)每年 1/1 10:00 自动跑。聚合源:**去年 12 篇月报**(年←月,非直读 365 篇日记)。
1. 算去年: `python3 -c "import datetime as d; print(d.date.today().year-1)"`
2. Read 该年所有月报(`06_月报/YYYY-*月报.md`);月报缺失则降级读该月日记并标注
3. Read: `{baseDir}/references/yearly-format.md`
4. 合并安全 → 生成 `07_年报/YYYY年报.md`(主线的主线,不复述月度细节)
5. 🔴 `verify_report.py <文件>` → PASS 才交付
## Workflow C: Calendar Backfill
Trigger: User notices persistent "当日无日历事件" on days that had events.
1. **Diagnose root cause**: `icalBuddy calendars` vs `collect_data.py` `-ic` params
2. Fix script if names mismatched
3. Determine backfill range (typically 3-7 days)
4. Backup diaries → `~/.hermes/backups/diary-calendar-backfill-YYYYMMDD_HHMMSS/`
5. For each day: query icalBuddy, patch calendar section (keep all other sections intact)
6. Skip days that genuinely had no events
7. Remind user of upcoming important events (eventsToday+30)
## Workflow D: Diary Cleanup
| 日历事件回填流程 | `references/calendar-backfill.md` |
| 日记清理启发式 | `references/diary-cleanup-heuristics.md` |
| **🆕 钉钉班级群消息采集 (dingwave 解密)** | `references/dingtalk-class-msgs.md` |
- Empty/template: backup → delete
- Sparse: merge by month → `归档/YYYY-MM/碎片日记合并-YYYY-MM.md`
- Normal: keep
3. Write cleanup report: `日记清理报告-YYYYMMDD.md`
4. Run `qmd update` after cleanup
## Tech Stack
| Tool | Purpose |
|------|---------|
| icalBuddy | Calendar queries (`brew install ical-buddy`) |
| Open-Meteo API | Weather (free, no API key) |
| `state.db` SQLite | Hermes session extraction (see `references/hermes-session-extraction.md`) |
| `~/.claude/projects/*/uuid.jsonl` | Claude Code session extraction (see `references/cc-session-extraction.md`) |
| `find` command | Vault change detection |
Key improvements history: see `CHANGELOG.md` (skill 根目录)。
## Common Pitfalls
| Trap | Consequence |
|------|-------------|
| Quoting user's raw messages in diary | Diary becomes chat log, not personal record |
| Overwriting existing user content | User's personal notes lost |
| Trusting icalBuddy silent empty output | Calendar events silently missing for weeks (see config drift below) |
| **Not checking `existing_content` before writing** | Duplicate or conflicting diary entries |
在 GitHub 查看