Skill: wanli6/organize-vault (version 1.1.0)

--- name: organize-vault description: 扫描 Markdown vault 中的笔记，按语义主题生成目录层级，将笔记移动到 对应目录，并在根目录和每个主题目录下创建 MOC.md。增量维护模式下检测 git 新增笔记， 移动归类并更新对应 MOC.md。笔记内容始终不变，git 是唯一回退机制。 origin: OrganizeVault version: "1.1.0" license: MIT homepage: https://github.com/wanli6/OrganizeVault metadata: openclaw: emoji: "🗂️" os: ["darwin", "linux", "win32"] --- # organize-vault 知识库目录结构生成与 MOC 维护助手。 ## When to Use 当用户说以下内容时激活： - "整理一下 vault"、"把新笔记归类"、"更新 MOC" - "帮我初始化 vault 结构"、"生成目录层级" - "哪些笔记还没归类" - "organize my vault"、"update MOC" ## Core Constraints 在整个执行过程中，以下约束不可违反： 1. **永不修改笔记内容**：笔记的 body 文本不可改动。可移动文件位置、创建 MOC.md、在 MOC.md 中追加 wikilink。 2. **变更必须经用户确认**：所有文件移动和写入在执行前展示完整清单，等待明确确认。 3. **模糊性是正常状态**：无法归类的笔记归入 `misc/`，标注"待整理"，不强制归入不合适的主题。 4. **git 是唯一回退**：所有变更受 git 追踪，执行前告知用户可通过 `git revert` 撤销。 --- ## 目标结构 初始化完成后，vault 应呈现如下层级： ``` vault/ ├── MOC.md # 根目录索引，链接所有主题目录 ├── programming/ │ ├── MOC.md # 本主题笔记列表（含描述） │ ├── python-async.md │ └── docker-compose.md ├── tools/ │ ├── MOC.md │ └── vim-config.md ├── reading/ │ ├── MOC.md │ └── deep-work.md └── misc/ ├── MOC.md # 标注"待整理" └── random-idea.md ``` --- ## 入口：检测场景 ``` 1. 若 vault_root 未知，询问用户 vault 的根目录路径 2. 检测 git 状态： git -C <vault_root> status --porcelain 2>&1 - 若返回 "not a git repository"：提示用户执行 git init，停止 3. 检测是否存在 MOC 文件（见 MOC 识别规则）： - 若无 MOC 文件 → 走【场景 B：初次初始化】 - 若有 MOC 文件 → 走【场景 A：增量维护】 ``` ### MOC 识别规则 以下任一条件满足，则该文件被识别为 MOC，不参与归类： - 文件名为 `MOC.md`（大小写不敏感） - 文件顶部 frontmatter 中含 `type: moc` 或 `moc: true` --- ## 笔记描述提取规则 在读取笔记全文时，同步提取一句简短描述，用于写入 MOC.md。提取优先级： 1. frontmatter 的 `description` 字段（直接使用） 2. H1 标题后第一个非空段落的首句（截断到 50 字以内） 3. 以上均无：不写描述，只写 `- [[note-stem]]` 描述**只写入 MOC.md**，不触碰原笔记文件。 --- ## 场景 A：增量维护（已有 MOC） ### Step 1 — 识别新增笔记 ```bash # 未提交的新增文件 git -C <vault_root> status --porcelain | grep '^?' | awk '{print $2}' | grep '\.md$' # 或：相对上次 commit 新增的文件 git -C <vault_root> diff --name-only --diff-filter=A HEAD ``` 过滤规则： - 只保留 `.md` 文件 - 排除 `MOC.md`（按 MOC 识别规则） - 若结果为空：告知用户"未发现新笔记（相对 git 状态）"，结束 ### Step 2 — 读取现有目录结构 用 find 找到所有 `MOC.md` 文件，逐一读取，理解各主题目录的内容范围。 在内存中构建映射： ``` { "programming/MOC.md": "涵盖编程语言和框架，已有：[[python-async]], [[docker-compose]]...", "tools/MOC.md": "开发工具配置，已有：[[vim-config]], [[git-tips]]..." } ``` ### Step 3 — 归类决策 对每个新笔记，Read 其全文，然后： 1. 按【笔记描述提取规则】提取一句描述 2. 对比各主题目录，判断归属： - **高置信度**：直接给出目标目录 - **低置信度**：列出候选目录，给出理由，让用户选择 - **无法归类**：归入 `misc/`，标注"待整理" 3. 每篇笔记只移动到一个目录（主要主题）；若同时匹配多个主题，在多个 `MOC.md` 中均追加 wikilink 4. 检查目标 `MOC.md` 是否已含该笔记链接：若已含，跳过 ### Step 4 — 展示变更预览 ``` 待执行的操作： ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 移动：python-async.md → programming/python-async.md 更新：programming/MOC.md ← 追加 [[python-async]] — Python asyncio 事件循环机制详解 理由：笔记讨论 Python asyncio，归入 programming 移动：vim-config.md → tools/vim-config.md 更新：tools/MOC.md ← 追加 [[vim-config]] — Vim 配置文件与插件管理 理由：编辑器配置，归入 tools 无法归类（共 1 篇）： random-idea.md → misc/random-idea.md（标注"待整理"） ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 所有变更受 git 追踪，可通过 git revert 撤销。 确认执行？（可指定"全部"或逐条接受/拒绝） ``` ### Step 5 — 执行变更 对每个用户确认的归类： 1. `mv <vault_root>/<note>.md <vault_root>/<topic>/<note>.md` 2. Edit `<topic>/MOC.md`，在笔记列表末尾追加： - 有描述：`- [[note-stem]] — {描述}` - 无描述：`- [[note-stem]]` 若目标目录不存在，先 `mkdir -p` 创建，再在其中创建 `MOC.md`（格式见下文）。 --- ## 场景 B：初次初始化（无 MOC） > 分四步执行，避免一次读取大量笔记导致上下文过长。 ### Step 1 — 标题扫描 ```bash find <vault_root> -name "*.md" -not -path "*/.git/*" -not -name "MOC.md" ``` 对每个文件，只提取： - 文件相对路径 - H1 标题（首行 `# ...`）或文件名 stem（若无 H1） **不读取笔记 body。** ### Step 2 — 分组提案 基于文件路径（目录结构）+ 标题，推断主题分组，向用户提出候选结构： ``` 建议生成以下目录结构（基于 47 篇笔记的标题和路径）： programming/ — 约 18 篇（Python, TypeScript, 算法...） tools/ — 约 12 篇（Docker, Vim, Git...） reading/ — 约 9 篇（读书笔记, 摘录...） projects/ — 约 5 篇（项目记录...） misc/ — 约 3 篇（暂无明显归属） 是否采用这个结构？可以调整目录名、合并或拆分分组。 ``` 等待用户确认或修改。**不执行任何文件操作。** ### Step 3 — 逐组细化 用户确认结构后，按分组**逐批**读取笔记全文（每批 10-15 篇），对每篇笔记： 1. 按【笔记描述提取规则】提取一句描述 2. 确认归属哪个目录： - 归属明确的：记录目标目录 + 描述 - 跨主题的：移动到主要目录，在次要目录的 `MOC.md` 中也追加链接 - 完全不匹配的：归入 `misc/`，标注"待整理" 记录所有归属决策（含描述），**不写文件**。 ### Step 4 — 目录重组 汇总所有归属决策，展示完整预览： ``` 即将执行以下操作（共 47 个笔记）： 新建目录： programming/ tools/ reading/ projects/ misc/ 移动文件（共 47 个）： python-async.md → programming/python-async.md docker-compose.md → programming/docker-compose.md vim-config.md → tools/vim-config.md ...（共 47 条，全部展示） 新建 MOC 文件（共 6 个）： MOC.md （根目录索引，5 个主题） programming/MOC.md （18 个笔记，含描述） tools/MOC.md （12 个笔记，含描述） reading/MOC.md （9 个笔记，含描述） projects/MOC.md （5 个笔记，含描述） misc/MOC.md （3 个笔记，标注"待整理"） 清理空目录（若有）：移走笔记后变空的原目录将被删除 所有变更受 git 追踪，可通过 git revert 撤销。 确认执行？ ``` 用户确认后，按以下顺序执行： 1. `mkdir -p` 创建所有主题目录 2. `mv` 移动所有笔记文件 3. Write 创建每个 `<topic>/MOC.md`（含描述） 4. Write 创建根目录 `MOC.md` 5. `rmdir` 清理空目录（失败则静默跳过） --- ## MOC 文件格式 **主题目录 `<topic>/MOC.md`**： ```markdown # {主题名称} ## 笔记 - [[python-async]] — Python asyncio 事件循环机制详解 - [[docker-compose]] — 多容器应用编排配置示例 - [[algorithm-notes]] ``` （无描述的笔记直接写 `- [[note-stem]]`，不强制加破折号） **根目录 `MOC.md`**： ```markdown # Vault Index ## 主题 - [[programming/MOC|Programming]] - [[tools/MOC|Tools]] - [[reading/MOC|Reading]] - [[projects/MOC|Projects]] - [[misc/MOC|Misc]] ``` --- ## 边界情况处理 | 情况 | 处理方式 | |------|---------| | vault 未初始化 git | 提示执行 `git init && git add -A && git commit -m "init"`，停止 | | vault 无任何 .md 文件 | 告知 vault 为空，结束 | | 无法确定 vault 根目录 | 询问用户，不猜测 | | 根目录已有 MOC.md | 询问用户是覆盖还是追加，不默认覆盖 | | 笔记同时匹配多个主题 | 移动到主要目录，在次要目录 MOC.md 中追加跨目录 wikilink | | 移走笔记后原目录变空 | `rmdir` 删除，失败则静默跳过（可能含其他文件） | | MOC.md 已含该笔记链接 | 跳过，不重复添加 | | 新笔记本身是 MOC.md | 跳过归类，告知用户 | | 笔记无可提取描述 | 只写 `- [[note-stem]]`，不加破折号，不报错 | | 大型 vault（> 100 篇笔记）初始化 | 严格执行分步策略，每批不超过 15 篇全文读取 |


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)