v1.29.0 — 原文存档、检索元数据过滤与连通性信号
1.28.0 之后累积的四项新增和两项修复。
新增里最大的一件是原文存档:剪藏的原文不再堆在笔记里,单独存放、双向挂钩、检索默认不碰。另一件是审计终于能分辨「没人读的笔记」和「找不到的笔记」。
Added
-
原文单独存档。
archive-source把原文写进95-Sources/<YYYY-MM>/,按源字节(不含 frontmatter)记 SHA-256,笔记和存档双向挂钩 —— 笔记多一个source_archive字段和一行可点击的入口,存档的 frontmatter 反向指回笔记。检索默认跳过95-Sources/,用户问「原文到底怎么说的」时用--scope才进去;审计不拿笔记契约约束存档 —— 存档是证据,它的标题、标签和占位符属于原作者。Skill 此前对这件事没有任何概念,于是用户要一篇文章的原文时,Agent 自己编了个标题、把 35 KB 原文追加在 7.6 KB 的沉淀后面,占了文件的 82%。那篇笔记四分之一的检索引用因此落在作者的行文里而不是读者自己的知识上,BM25 的长度归一化又让沉淀部分掉了 20–30% 的分。归档之后,同样十二个查询没有一个再引用原文,笔记自己的章节排名持平或更好。
逐字保真是被强制的而不是被期望的:存档按字节读写,所以换行符原样保留;哈希不含 frontmatter;非 UTF-8 的原文直接以
undecodable-source-content拒绝而不是替你转码 —— 猜出来的编码不算证据。存档文件名在整棵树内唯一(不是只在当月目录内),因为笔记按裸 stem 链接而 Obsidian 是全库解析的。--replace是追加第二份而不是替换:source_archive一份时是字符串、多份时变列表,旧存档不会和它支撑的笔记失联。 -
检索能按元数据过滤。
search-vault新增--type、--tag(都可重复,flag 内 OR、flag 间 AND)和闭区间的--after/--before,每条结果都带上type和date。词法排序回答不了「什么时候」和「哪一类」,而 CJK 分词会把
7月切成互不相干的 token —— 参考 Vault 上「7 月的日报」把一篇 6 月写的笔记排在了 7 月日报前面,「最近的周报」把一份设计文档排在了周报前面。真正麻烦的不是返回空,是返回了错的东西却没有任何信号说明它错了。过滤是排序之前的硬约束,所以
score的含义没有变。相对时间留给调用方:helper 只收 ISO 日历日,其他一律以invalid-date拒绝 —— 与其把一套双语日期文法加上「一周从哪天开始」的政策塞进一个靠确定性立身的 helper,不如让它就只做确定的事。笔记自己的date现在和过滤参数一样按真实日历日解析,不再是「长得像 ISO」就算数,所以第 13 个月不会被当成日期来排序。--tag走审计同一套归一化,--tag springboot能找到spring-boot。新增拒绝码:invalid-date、invalid-date-range、invalid-type、invalid-tag。 -
过滤后的检索会说明自己过滤掉了什么。 响应新增
filters,含applied、candidates、matched和按维度拆分的excluded,「压根没有 date 字段」和「date 落在范围外」分开计。没有它,过窄的过滤和空 Vault 长得一模一样,「这个条件没匹配到」会被当成「你没有关于这个主题的笔记」报给用户。 -
审计能分辨「没人读的笔记」和「找不到的笔记」。
orphan-note测的是可达性,它在索引齐全的 Vault 上接近于 0 是正确的:Folder Index 插件按目录内容生成列表,目录有索引就确实让目录内每篇笔记都翻得到。但这和知识有没有连起来是两回事。disconnected-note报的是零入链且零出链 —— 只报交集,因为任何单边都太吵且含义模糊,一篇被三处引用的概念笔记本来就不该有出链。周期性日志直接豁免:参考 Vault 上完全没有链接的 57 篇里,daily-report和weekly-report占 36 篇,报它们会把真正值得看的 21 篇埋掉 —— 那 21 篇里有 14 篇是剪进来之后再没接上任何东西的剪藏。可达性是前置条件而不是假设:索引覆盖不到的笔记报
orphan-note,两个 finding 不会对同一篇笔记给出两套说法。链到95-Sources/也不算数 —— 存档是笔记自己捕获的证据,归档一份原文不能把这条 finding 悄悄消掉。严重度是informational,reference 里写明不要为了消掉它去编一条链接 —— 不相干的链接比没有更糟。
Fixed
-
没有候选时 Agent 会编一个 wikilink。 deep-capture 契约要求 web-clip 必须带
## 关联笔记标题,而note-creation.md却说链接可以「skip them」—— 必填的段落没法 skip;同一句话还承诺 helper 会「列出目标目录的文件名」,等于把一份原始目录清单当作候选集递过去。结果是四篇毫不相干的笔记(Fluss 存储、SQL 优化器、RAG 流式、Zig Coding Agent)全都链到同一个文件,理由仅仅是它在20-Learning/Backend/里排序第一 —— 而suggest-links对它们一个都没推荐过,其中一篇还明确返回了「没有建议」。现在:零候选是答案,不是待填的空缺;没有可信关联时用一行明确说明写满该段落;并且把「邻近」点名为不该链接的理由 —— 同目录、同类型、同大方向,每一条单独都足以否决。
-
检索把脚手架当知识排。
EXEMPT_NAMES一直声明README.md、AGENTS.md、CLAUDE.md是治理文件而不是笔记,但只有写入 Skill 知道这件事 —— 而 Vault 的 README 又长又提到每一个主题,是天然的词法磁铁。参考 Vault 上十二个真实问题、60 个 top-5 名额里有 11 个(18%)被非知识文件占据,光README.md就在其中一半里出现;问「洞察」时前三名是README.md、AGENTS.md和INDEX.md,而30-Insights里 13 篇笔记全被挤出去。这个判断现在只有一份定义、两个 Skill 共享,实测噪音降到 4 个名额(7%),剩下的是INDEX.md—— 它是导航性知识,本来就该在。被排除的文件计入scanned.excluded,绝不报成issues:脚手架不是格式有问题的笔记。