开源项目› 知识库整备台› 手册
手册 · 03

规则 DSL

约 5 分钟阅读 Apache-2.0 本文基于 v0.1.0(2026-11-01)

规则是 KBFold 的正文。工具本身只做三件事:读规则、判文件、记账。所以「它能不能用在我的资料上」几乎等价于「我这份 kbfold.yml 写得对不对」。

下文的 kbfold 命令=克隆仓库后的 python hosts/cli/kbfold_cli.py。改完规则先用 kbfold validate(或宿主里的 kb.validate 工具)校验结构,不认识的版本会直接报错退出。

01一份规则文件长什么样

yaml
version: 1
root: ~/Projects
basis: kbfold:generic/v1        # L0 通用基底,永远兜底,不可删除

kbs:
  - name: 星海项目
    id: XH-2024
    template: kbfold:trade/v1   # 行业模板:贸易
    detect:
      markers: [".xhproject"]   # 有这个文件即认定,置信 0.95
      keywords: ["星海", "XH-2024"]  # 置信 0.80
    paths:
      - match: "**/合同/**"
        to: "02-合同"
      - match: "**/会议记录/**"
        to: "03-会议"
      - match: "**/过程稿/**"
        to: "@exclude"          # 永不入投影,但仍登记指纹

一段话读完:version 是格式版本;root 是扫描根;basis 是兜底模板;kbs 下面每个知识库有名字、编号、模板,以及两组「怎么认出我」的探测器(detect)和一组「认出来之后往哪放」的路径规则(paths)。

02字段说明

字段必填说明
version是目前只有 1。不认识的版本直接报错退出,不做猜测性兼容
root是扫描根目录。相对路径按规则文件所在目录解析
basis是L0 通用基底模板,任何项目都没认出来时用它兜底。不可删除、不可改名
kbs[].name是人类可读名字,出现在报告的标签里
kbs[].id是短编号(如 XH-2024),用于投影目录前缀与检索时的库过滤
kbs[].template否行业/场景模板。不写则继承 basis
kbs[].detect.markers否标记文件名列表,命中即认定,置信 0.95(最高级)
kbs[].detect.keywords否名称/路径中的关键词,置信 0.80
kbs[].paths[].match是glob 写法,如 /合同/
kbs[].paths[].to是目标目录(相对投影根)、@exclude 或 @inbox

03三个特殊去向

  • 普通目录名:如 02-合同,投影里就放这儿。
  • @exclude:这个匹配永远不进投影。常用于过程稿、缓存、临时导出。注意它仍然进指纹台账——这样将来你把它从 @exclude 里拿掉,不必重新扫全盘。
  • @inbox:显式承认「我不知道该放哪」。判断链自己走不通时会自动落到这里,你也可以手动指定。

@inbox 不是垃圾桶,它是一个待办队列:每份带候选与理由,你处理完一批再跑一次 plan 就会看到它变短。

04冲突怎么裁

同一份文件被多条规则命中,按下面四条依次裁决:

情形裁决理由
多条路径规则命中最具体的胜:路径段更多者胜;同样多则书写顺序后者覆盖前者越具体越像人为表态
具体程度打平不猜,进 _inbox/ 并附两条候选平手时任何选择都是抛硬币,抛硬币的错误率 50%
S1 显式声明与路径规则冲突S1 胜用户明确写过 .xhproject,比路径暗示更可信
一条都没命中落 basis 通用基底;仍无解 ⇒ _inbox/有兜底但不硬塞

05什么名字不许写进规则

data、config、cache、app、docs 这类全行业同名的通用目录名,写进 to: 会在启动时直接报错:

text
✗ 规则错误:目标目录 "data" 属于通用名黑名单(GENERIC_NAMES,共 40+ 项)
  这类目录名不携带任何场景信息,放进规则等于把判定权交给猜测。
  换成场景名,例如 "01-原始资料/data"。

黑名单沿用主产品 dir_classify.py 里的同一份 GENERIC_NAMES,不在 KBFold 里另抄一份。

06模板是怎么选的

优先级从高到低,上一级命中就不往下走:

级依据说明
A显式声明.kbfold.yaml,或目录已成体系(用户当年就按某套结构建的)
B行业模板软件 / 贸易 / 制造 / 咨询 / 工程项目 / 医疗,共六套
C通用-项目阶段八段子项(立项 → 交付 → 复盘)
D通用-文件类型十二类子项(合同、报告、图纸、影音 …)

D 是最后一道,也是最通用的:它保证任何一坨文件都能得到「至少按类型分开」的结果,而不是原封不动。

只有 A–D 里 A 和 D 的通用部分随开源版一起发布;B 的六套行业模板属于我们自己的场景积累,不在开源仓库里,需要的话可以自己写——格式完全一样。

07目录规模要跟着文件量伸缩

模板不是固定深度。同一个模板,文件少时只长出几段:

文件量建议段数建议目录数
< 50≤ 3 段≤ 12 个
50 – 5004 – 6 段20 – 40 个
> 5008 段全集40 – 60 个

少于 50 个文件却建出 60 个空目录,是最典型的「工具比资料还重」。这三个阈值是工程判断,没有用真实样本校准过——如果你觉得不对,改模板就行,不用改代码。

08adopt 优先于 mkdir

如果目录里已经有一个 合同/,它不会另建一个 02-合同 然后让你挑。它会把既有的 合同/ 认作同类容器纳入体系(adopt),不改名、不移动,只在真正的缺口处 mkdir。

所以一次 plan 的产物是两张清单:adopt 了什么、要新建什么,而不是一句「重建为 X」。

09为什么必须记一份 rules.lock.yaml

因为规则是会变的。半年后你想知道「这份合同当初是按什么规则归到 02-合同 的」,只能靠当时的规则快照。rules.lock.yaml 就是这个快照,内容 = 那一批实际生效的规则 + 它的 sha256,与 manifest 里的 rules_locked 字段互相印证。

删了它不影响运行,但会让历史判定变成「无法复现」。