| name | inbox-dispatch |
| description | 将 Obsidian 00_Inbox 下的 Markdown 笔记按 Robert 当前 10_思考/待处理 队列做语义预分拣,生成 dispatch plan,经大模型慎重验收后按错误阈值自动执行或请求确认。Use when the user asks to dispatch, organize, sort, or clean up their inbox notes, especially phrases like “分拣 inbox”, “整理 inbox”, or “inbox dispatch”. |
inbox-dispatch
将 00_Inbox/ 下的 Markdown 笔记按 Robert 当前工作流做语义预分拣,输出 dispatch plan,并在大模型慎重验收后按阈值执行或请求确认。
核心原则:不使用单个关键词全文匹配直接移动;必须先生成 plan,再由大模型慎重验收并修正。若验收发现错误数 > 5,暂停并请 Robert 确认;若错误数 <= 5,修正后可直接执行移动。
动态队列体系
队列目录不写死在 skill 文档里。每次分拣前必须动态读取当前队列:
cd /Users/robertma/.agents/skills/inbox-dispatch
python3 scripts/list_queues.py --format markdown
配置来源:
- 环境变量
INBOX_DISPATCH_PENDING_ROOT(最高优先级)
scripts/dispatch_rules.json 的 pending_root
- 默认值:
10_思考/待处理
10_思考/待处理 下的第一层子目录是当前可用队列。scripts/dispatch_rules.json 只保存队列说明、include/exclude 锚点、fallback/trash 队列名;它不是队列目录清单。Robert 新增/删除子目录后,list_queues.py 会自动反映。
低置信度默认进入 fallback_queue(通常为 待判定);低价值/营销/重复内容进入 trash_queue(通常为 淘汰候选)。如果这些队列目录不存在,先报告,不要擅自创建或移动。
include / exclude 只是辅助锚点;分类必须以语义判断为准。未配置说明的新目录也可以被使用,但理由里要说明是按目录名和实际语义判断。
强制安全规则
- 未经 plan 生成与大模型验收,不执行实际移动。
- 验收错误数阈值为 5。 错误数
> 5 必须暂停并请 Robert 确认;错误数 <= 5 时,修正 plan 后可 dry-run 校验并直接执行。
- 不要使用单个关键词全文匹配决定分类。 文件名、标题、小标题的权重大于正文偶然关键词。
- 低置信度进入
fallback_queue。 不要强行归入主题队列。
- 疑似重复、浅层、营销进入
trash_queue。 不要直接删除。
- 单批建议不超过 50 篇。 大批量 Inbox 积压要分批处理。
- 跳过附件/素材类目录。 scanner 默认跳过
_dispatch_logs、图片、素材、视频、论文、_assets。
- 移动 Get笔记 Markdown 时必须同步处理图片。
mover.py --execute 会把  引用到的图片复制到笔记同目录的 assets/${noteFileName}/,再把链接改写为 ![[assets/${noteFileName}/xxx.jpg]];确认没有旧引用后才清理 00_Inbox/Get笔记/_assets/Get笔记/ 中的中央图片。
- 必须保留笔记原始时间。
mover.py --execute 移动 Markdown 时要保留原始创建时间和修改时间,避免 Robert 按创建时间从新到旧阅读时被分批移动顺序打乱。实现上优先使用同卷 rename 保留 inode;若发生 copy/delete fallback,则在 macOS 上用 SetFile -d 恢复 birthtime,并用 os.utime 恢复 atime/mtime。Get笔记图片链接改写后也必须恢复原笔记时间。
- 目标已存在时删除 Inbox 重复源。 如果 plan 指向的目标目录下已经存在同名 Markdown,说明这篇 Inbox 笔记已被分拣过;
validate_plan.py 只给 warning,不阻断执行;mover.py --execute 不再跳过,而是直接删除 00_Inbox 中的重复源笔记,并对其旧 Get笔记中央图片引用做安全清理检查。
标准流程
Step 1:读取当前队列与分类说明
cd /Users/robertma/.agents/skills/inbox-dispatch
python3 scripts/list_queues.py --format json
重点读取:
pending_root
fallback_queue
trash_queue
- 每个队列的
name、destination、description、include、exclude
Step 2:只读扫描 Inbox
python3 scripts/scanner.py --since-days 30 --limit 50
常用参数:
python3 scripts/scanner.py --since-days 7 --limit 50
python3 scripts/scanner.py --all --limit 50
python3 scripts/scanner.py --all --oldest-first --limit 50
python3 scripts/scanner.py --since-days 30 --limit 0
scanner 输出 JSON lines,每行一个文件,字段包括:
| 字段 | 含义 |
|---|
path | vault 相对路径,如 00_Inbox/Get笔记/xxx.md |
filename | 文件名 |
mtime_iso | 修改时间 |
source_dir | Inbox 下第一层来源目录 |
title | frontmatter title / H1 / 文件名 |
tags | frontmatter tags 摘要 |
headings | 前几个 H1-H3 标题 |
body_preview | 正文前 800 字 |
Step 3:语义分类
对每个文件综合判断:
filename / title
headings
body_preview
source_dir
tags
- 当前队列说明和目录名
- 必要时读取完整文件再判断
每个文件输出:
category_id:优先用队列配置里的 id;未配置时可用目录名或 slug
category_name:必须等于某个当前队列名
destination:使用 list_queues.py 返回的目标目录
confidence: high / medium / low
reason: 一句话说明
分类准则:
high:标题和摘要都明确指向同一队列。
medium:大体可判断,但有边界重叠;仍可放入主题队列,但报告里标出。
low:主题不清或多类难分,放入 fallback_queue。
- 低价值/重复/浅层营销:放入
trash_queue,等待 Robert 最终确认。
Step 4:生成 dispatch plan
写到:
00_Inbox/_dispatch_logs/plan_YYYY-MM-DD_HHMM.json
Plan 格式:
{
"created": "2026-05-06T22:00:00+08:00",
"mode": "review_required",
"pending_root": "10_思考/待处理",
"queues_source": "scripts/list_queues.py",
"files_scanned": 50,
"dispatches": [
{
"source": "00_Inbox/Get笔记/example.md",
"destination": "10_思考/待处理/个人第二大脑",
"category_id": "personal-second-brain",
"category_name": "个人第二大脑",
"confidence": "high",
"reason": "标题和摘要都围绕 llm-wiki 与个人知识管理。"
}
],
"unclassified": []
}
说明:
destination 是目录,不含文件名;必须来自当前队列清单。
- 也可用
destination_queue / category_name 让 mover.py 动态解析队列,但推荐仍写入完整 destination,方便审阅。
- 不要删除文件;淘汰只移动到
trash_queue 等待确认。
Step 5:大模型慎重验收 plan(强制)
生成 plan 后,不要立刻移动。必须先进行两层验收:
5.1 机械验收
python3 scripts/validate_plan.py ~/obsidian/00_Inbox/_dispatch_logs/plan_YYYY-MM-DD_HHMM.json --format json
机械错误包括:
- source 缺失或不存在
- destination 不在当前动态队列中
category_name 与 destination 不一致
- 目标文件已存在
- plan 结构错误
这些错误必须修正;无法自动修正时,计入错误数并暂停询问 Robert。
5.2 大模型语义验收
大模型必须对 plan 做第二遍“反向审稿”,而不是直接相信第一遍分类:
- 重新读取当前队列清单。
- 对每条 dispatch 重新看
title、headings、body_preview、tags、source_dir。
- 对以下条目读取完整笔记再判断:
confidence=medium/low
- 目标目录是新增目录或无明确 metadata
- 标题同时命中多个队列
- 进入
trash_queue 的内容
- 高考、个人记录、待判定等容易误分的内容
- 检查
category_name、destination、confidence、reason 是否一致。
- 修正错误分类、错误置信度、错误理由、错误目标目录。
错误计数规则:
- 一条笔记目标队列错误 = 1 个错误
- 一条笔记应进入
fallback_queue / trash_queue 但没有进入 = 1 个错误
- 一条笔记被误判为
trash_queue = 1 个错误
- 一条笔记的 destination/category 不一致 = 1 个错误
- source 缺失、目标冲突等机械错误 = 1 个错误
- 只改措辞、不影响分类和执行的 reason 优化不计错误
验收后在 plan 中追加或更新 plan_review:
{
"plan_review": {
"reviewer": "LLM",
"reviewed_at": "2026-05-06T22:10:00+08:00",
"semantic_errors": 2,
"mechanical_errors": 0,
"total_errors": 2,
"corrections": [
{
"source": "00_Inbox/Get笔记/example.md",
"before": "AI工作台",
"after": "Agent Harness",
"reason": "正文重点是 Agent 运行时和 skill 编排,不是工作台产品。"
}
],
"decision": "auto_execute"
}
}
如有修正,推荐另存为:
00_Inbox/_dispatch_logs/plan_YYYY-MM-DD_HHMM_reviewed.json
Step 6:按错误阈值决定是否执行
验收完成后:
total_errors > 5:不要执行移动。向 Robert 报告错误数量、典型错误和修正建议,请 Robert 确认后再继续。
total_errors <= 5:修正 plan 后,先运行 dry-run 做最后机械校验;如果 dry-run 无异常,直接执行移动,无需再次请求 Robert 确认。
- 若用户明确说“只生成 plan / 先别动”,无论错误数多少都不要执行。
最后机械校验:
python3 scripts/mover.py ~/obsidian/00_Inbox/_dispatch_logs/plan_YYYY-MM-DD_HHMM_reviewed.json --dry-run
如果 dry-run 发现源文件消失、目标已存在、目标不明等问题:先修正 plan;无法修正则询问 Robert。
Step 7:执行移动
当 total_errors <= 5 且 dry-run 正常时,直接执行:
python3 scripts/mover.py ~/obsidian/00_Inbox/_dispatch_logs/plan_YYYY-MM-DD_HHMM_reviewed.json --execute
执行后报告:
- 当前
pending_root
- 大模型验收错误数与是否修正
- 已移动多少条
- 跳过多少条(目标已存在 / 源文件消失 / plan 无效)
- 图片迁移/缺失统计
- 是否需要对某个队列做去重、价值判断或编入
60_wiki/<主题>/
常见用户意图映射
| 用户说法 | 动作 |
|---|
| “分拣 inbox” | 读取当前队列,扫描最近 30 天 50 篇,生成 plan,经大模型验收;错误≤5 则修正后自动执行,错误>5 则请求确认 |
| “整理 inbox 最近一周” | scanner.py --since-days 7 --limit 50,之后同样执行 plan 验收阈值流程 |
| “全量看看” | scanner.py --all --limit 50,仍分批;若用户只想看则不自动执行 |
| “从最旧的开始” | scanner.py --all --oldest-first --limit 50,之后同样执行 plan 验收阈值流程 |
| “执行这个 plan” | 先运行 validate_plan.py 和大模型验收;错误≤5 可执行,错误>5 请求确认 |
完成后
报告使用 Obsidian wikilink,例如:
- 目标队列:
[[10_思考/待处理/个人第二大脑]]
- plan 文件:
[[00_Inbox/_dispatch_logs/plan_YYYY-MM-DD_HHMM.json]]
不要在报告中输出大量完整原文,只列标题、分类、理由和置信度。