--- words: 2026-08-25: 1263 --- 这套 tagfeed 工作流梳理成「架构图 + 生命周期图 + 规则细节图」三张图 ,先把绘图模块加载出来,然后逐张给你讲。 我先加载图示模块: 先上第一张:**整体架构图**——这套工作流由两个部件 + 两条触发链组成。 - **生成器** `sync_0inbox.py`:负责"新建" tagfeed 页,扫描全 vault 的 `#tag`,按规则写进 A 收件箱。 - **监视器** `tagfeed.py --watch`:负责"即时响应"——文件一变动(约 15s 内)就触发生成器,同时顺带刷新已有页、日记足迹、目录脑图。 - 两条触发链:实时链(launchd → TagfeedWatch.app → watcher)和定时兜底(WorkBuddy 自动化每天 04:00)。 第二张:**标签生命周期图**——A 与 B 的双文件夹机制,以及你的整理动作如何驱动秩序形成。 - **A = `00index/0inbox`**:所有"还没归类"的标签页自动落在这里。 - **B = `00index/标签聚合`**:你把页面从 A 拖进来,就代表"已整理"。 - 规则 1 让新标签自动进 A;规则 2 让进了 B 的标签永不回 A。随着你不断拖拽,A 渐归 0,B 成为你最终的知识秩序。 第三张:**规则 2 进阶图**——这正是你刚遇到的"顽固再生"问题的根因与修法。 问题在于"一个合并页可以覆盖多个标签"。比如 `UI.md` 在页面里写 `targetTag = ["UI","UI相关"]`,它同时索引这两个标签。旧逻辑只按"文件名是否等于标签名"判断,于是 `UI相关` 永远匹配不上 `UI.md`,被当成未整理反复重建。修复后改为**解析 `targetTag` 声明**:只要被任一聚合页声明覆盖,就判定为"已整理",不再进 A。 三张图讲完了,下面把这套工作流浓缩成一份**速查参考**,方便你以后照着用。 ## 一句话定位 > 新标签自动落进 **A(收件箱)**,你拖进 **B(标签聚合)** 即视为整理完毕,从此永不回 A——A 渐归 0,B 成秩序。 ## 两条核心规则 - **规则 1(自动生成)**:笔记里出现新 `#tag`(且不在排除目录)→ 约 15s 内由 watcher 触发生成器,在 `00index/0inbox` 建页。每日 04:00 的 WorkBuddy 自动化作兜底。 - **规则 2(已整理不重建)**:某标签一旦被 `标签聚合/` 下任一页覆盖——判定方式二选一:**① 该页文件名就是 `<标签>.md`;② 该页 `targetTag` 显式声明了它(支持合并页 `["UI","UI相关"]`)**——就不再出现在 A。 ## 关键文件与位置 | 角色 | 路径 | | ------------------------------------ | -------------------------------------------------------- | | 生成器(建页) | `X2.Archived/scripts/sync_0inbox.py` | | 监视器(即时响应) | `/Users/ar/bin/tagfeed.py`(`--watch`) | | 监视器启动器 | `/Users/ar/Applications/TagfeedWatch.app` | | 登录自启 | `~/Library/LaunchAgents/com.ar.tagfeedwatch-login.plist` | | 定时兜底自动化 | WorkBuddy `automation-1787588745696`(每日 04:00) | | 运行日志 | `~/.tagfeed-watch.log` / `~/.tagfeed-watch.err.log` | | A 收件箱 | `00index/0inbox` | | B 已整理 | `00index/标签聚合`(含任意子目录) | **排除目录**(永不扫描、不会生成页):`X2.Archived` · `00index` · `Knomo` · `X.Attachment` · `P3.bobo`。 ## 日常操作 1. 写笔记时随便打 `#任意标签` → 不用管,一会儿自动出现在 A。 2. 想整理时,在 Obsidian 里把 A 里的页拖进 B 的某个分类子文件夹。 3. 之后该标签(含合并页里声明的其他标签)绝不再回 A。 ## 两个已知特性(沿用原设计,未改) - **只建不删**:某标签从所有笔记彻底消失后,A 里会留孤儿页,需你手动删。 - **合并页要写对 `targetTag`**:想让一个页同时覆盖多个标签,记得在它的 DataviewJS 里用数组写全,例如 `const targetTag = ["UI","UI相关"]`——这样 `UI相关` 才不会被误判为"未整理"而顽固再生(就是你今天踩的坑,已修好)。 下面把两个核心脚本一并附上,方便你随时回看实现: 已为你把这套 tagfeed 工作流整理成 **3 张图 + 一份速查参考**: 1. **整体架构图**——实时链(launchd→TagfeedWatch.app→tagfeed.py)与定时兜底(WorkBuddy 04:00)共同驱动生成器 `sync_0inbox.py`,扫描排除目录 + 标签聚合目录后输出到 A 收件箱。 2. **标签生命周期图**——A(0inbox 收件箱)与 B(标签聚合)的双箱机制,规则 1 让新标签自动进 A、规则 2 让进 B 的永不回 A,最终 A 归 0、B 成秩序。 3. **规则 2 进阶图**——用一个合并页 `UI.md`(`targetTag=["UI","UI相关"]`)说明"一页覆盖多标签"如何被识别,正是你今天踩的"顽固再生"坑的修法可视化。 核心结论:**新 `#tag` → ~15s 自动进 A;拖进 B 即整理完毕、永不回 A**。两个已知特性沿用原设计:同步只建不删(标签删光后 A 留孤儿页需手清)、合并页务必写全 `targetTag` 数组。两个核心脚本已作为附件附上,可随时回看。