- 人工智能
- RAG
- Agent 记忆
- MCP 服务
- 知识管理
【免费下载链接】gbrain
Garry's Opinionated OpenClaw/Hermes Agent Brain
导读:本文围绕 gbrain 仓库中
plugin/skills/frontmatter-guard/SKILL.md技能文档展开,系统讲解大脑(brain)页面 YAML frontmatter 的八类规范化校验、gbrain frontmatterCLI 的 audit / validate / fix / install-hook 四阶段工作流、.bak集中备份机制,以及如何通过编写规范 YAML 从源头杜绝畸形 frontmatter。读完你既能用 CLI 完成全量审计与批量修复,也能在 CI 或 pre-commit 阶段拦截脏数据,并理解校验器在 markdown.ts 中的底层判定逻辑。
技能定位:为什么大脑需要一道 Frontmatter 守卫
gbrain 是一个面向 Agent 的开放式大脑(brain)系统,页面以 Markdown 文件形式落在磁盘上,每篇页面的元数据(类型、标题、slug、标签、日期等)由文件头部的 YAML frontmatter 承载。经年累月之后,由实体检测器、会议摄入、路径改名、复制粘贴事故等各种途径产生的页面,会积累大量畸形 frontmatter:
- 缺少闭合的
---(实体检测器 bug 的典型产物); - 会议页面中非结构化的 YAML(摄入流程 bug);
- slug 与文件路径不一致(路径改名未同步传播);
- 空字节(复制粘贴造成的二进制损坏);
- 标题中嵌套双引号(
title: "Alice "Ace" Example")。
这些脏数据平时不会立刻暴露,直到某一天gbrain sync解析失败、或搜索返回垃圾结果时才集中爆发。frontmatter-guard 技能的价值正在于此:在审计阶段让失败可见,并在需要时一键可修。技能文档在 plugin/skills/frontmatter-guard/SKILL.md 中明确了四项契约承诺:
- 每个大脑页面都会被扫描,覆盖八类规范化校验错误;
- 机械性错误(嵌套引号、缺失闭合
---、空字节、slug 不匹配)可按需自动修复,且修复前写入.bak备份; - 校验逻辑与
gbrain doctor的frontmatter_integrity子检查共享——单一事实来源; - 按 source(源)维度报告;gbrain 自 v0.18.0 起支持多源,绝不静默审计错误的根目录。
技能本身是一个包装层,最终调用 frontmatter.ts 中的gbrain frontmatterCLI 完成实际工作,属于纯结构化校验,不做引用(citation)审计(引用规则见 skills/conventions/quality.md)。
八类校验错误码全景
技能文档给出了一张错误码对照表,校验器在 markdown.ts 中以ParseValidationCode联合类型定义,并与之一一对应:
| 代码 | 含义 | 可自动修复? |
|---|---|---|
MISSING_OPEN | 文件不以---开头 | 否(需要人工) |
MISSING_CLOSE | 首个标题之前缺少闭合--- | 是 |
YAML_PARSE | YAML 解析失败 | 视原因而定 |
SLUG_MISMATCH | frontmatter 中slug:与路径派生 slug 不一致 | 是(移除该字段) |
NULL_BYTES | 二进制损坏(\x00) | 是 |
NESTED_QUOTES | title: "outer "inner" outer"形态的嵌套双引号 | 是 |
NON_STRING_FIELD | title/type/slug为未加引号的非字符串标量(如title: 123、slug: 2024-06-01) | 否(需给值加引号) |
EMPTY_FRONTMATTER | 开闭---齐全但中间为空 | 否(需要人工) |
这些检查并非一次性扫描,而是有顺序的分层判定(见 markdown.ts 的collectValidationErrors):
NULL_BYTES字节级检查最先执行:用content.indexOf('\x00')探测二进制损坏,并计算所在行号——便宜、字节级,且先于后续逐行检查,避免空字节干扰后面的结构判断。MISSING_OPEN:定位首个非空行,必须以---(允许带yaml/yml/json语言标识)开头;空文件或空白文件同样判定为MISSING_OPEN。一旦没有开标记,就无法继续推理闭合、空 frontmatter 与嵌套引号,结构检查就此终止。MISSING_CLOSE:在开标记之后查找下一个---;找不到时,会寻找第一个形似标题的行(^#{1,6}\s)作为出错位置的提示。注意:闭合 fence 之内的#注释行是合法 YAML,不会触发该错误。EMPTY_FRONTMATTER:开闭标记之间 trim 后为空字符串即命中。NESTED_QUOTES:逐行匹配key: value形态,统计未转义的双引号数量;数量 ≥ 3 并不直接判错——因为tags: ["yc", "w2025"]这类合法 flow 序列天然就有 4 个双引号。判错前的最后一步是用js-yaml的safeLoad单独解析该值,只有真正解析失败才判定NESTED_QUOTES。YAML_PARSE:对 fenced 区间内的 YAML 直接做二次解析,避免依赖 gray-matter 宽容的解析路径漏判。SLUG_MISMATCH:仅在提供了expectedSlug且 frontmatter 中存在字符串slug字段时触发;且按 #3772 的约定,声明 slug 经 slugify 后与路径派生 slug 规范化等价(如 export 为保留旧身份而写入的 slug)不算不匹配。NON_STRING_FIELD(#1948):遍历title/type/slug,非字符串标量即报错并提示加引号——这是防止 YAML 类型强转(title: 123变成 number、裸日期变成 Date)导致下游.toLowerCase()崩溃的关键防线。
一个值得注意的细节是 v0.38.2.0 的修复:目录遍历采用pruneDir在下降时剪枝(见 frontmatter.ts 的collectFiles),不再递归进node_modules、.git、.obsidian等子树;同时支持 git 可见文件快路径(collectGitVisibleFiles)。这直接解决了超大脑(如 21.6 万页)上frontmatter validate无限挂起的问题。
Phase 1:全源只读审计
技能约定:永远先执行审计,绝不假设大脑是干净的。审计是一个只读扫描,覆盖全部已注册 source(或用--source <id>限定单个):
gbrain frontmatter audit --json审计报告包含:
- 每个 source 按错误码分组的计数;
- 每个 source 最多 20 个受影响页面的抽样;
- 总数;
- 扫描时间戳。
输出为 JSON 信封,Agent 解析errors_by_code与per_source决定下一步。其底层由 brain-writer.ts 的scanBrainSources实现,并经由 doctor.ts 的frontmatter_integrity子检查复用——即技能文档强调的"单一事实来源"。需要特别说明的是,doctor 侧的扫描受GBRAIN_DOCTOR_FM_TIMEOUT_MS环境变量约束(默认 30000ms),超时后按 source 汇报scanned/partial/skipped三态,避免单个损坏源拖垮整个检查;审计 CLI 本身退出码为 0,计数即信号。
当没有任何已注册 source 时,审计会优雅地输出 "no registered sources to audit"——正确做法是gbrain sources add注册源,而不是用手工路径遍历来掩盖迁移阶段产生的skipped: no_sources结果。
Phase 2:单路径校验与 CI 集成
校验单个文件或目录无需 source 注册:
gbrain frontmatter validate <path> --json- 退出码 0 = 干净;1 = 发现错误(未修复时)。这一约定让它天然适合 CI 流水线与 pre-commit 钩子。
- 仅支持
.md/.mdx文件,传入其他文件会报错拒绝。 - 底层流程(见 frontmatter.ts 的
runValidate):先通过findBrainRoot向上寻找包含.git标记的祖先目录作为大脑根,保证 slug 推导相对大脑根进行——这正是修复 #565(单文件目标时relative()为空导致伪SLUG_MISMATCH,曾让 pre-commit 钩子每次提交都误报)的关键逻辑;然后对每个文件调用parseMarkdown(content, file, { validate: true, expectedSlug }),其中expectedSlug由slugifyPath从相对路径派生。
非--json模式下输出形如:
OK — 42 file(s) scanned, no frontmatter issues或:
Found 3 issue(s) across 2 file(s) (scanned 42) /path/to/people/jane.md [MISSING_CLOSE]:18 No closing --- before heading at line 18Phase 3:--fix自动修复与.bak安全契约
发现错误后执行:
gbrain frontmatter validate <path> --fix修复引擎autoFixFrontmatter(见 brain-writer.ts)只处理可修复子集,且幂等(对已干净输入运行第二次是 no-op):
NULL_BYTES:直接剥离\x00字符;MISSING_CLOSE:在第一个形似标题的行前插入闭合---(best-effort 推断 frontmatter 应结束的位置;先全区间扫描闭合 fence,#注释行不会误判);NESTED_QUOTES:把"... "inner" ..."重写为单引号包裹外层;SLUG_MISMATCH:移除slug:行——gbrain 的 slug 由路径推导;- 附加规范化:对
tags:/aliases:的 JSON 风格 flow 数组(如tags: ["yc", "w2025"])重写为规范的单引号 flow 形态(tags: ['yc', 'w2025']),与 v0.37.9.0 序列化器的输出保持一致;白名单刻意限定这两个 key,避免把scores: ["1", "2"]这类带类型意图的数组改坏。
EMPTY_FRONTMATTER、YAML_PARSE、MISSING_OPEN三类绝不自动修复,留给人工评审。
.bak备份是安全契约:--fix在改动每个文件前,先把原文件拷贝到集中式备份目录(默认~/.gbrain/backups/frontmatter/<runId>/...,见 brain-writer.ts 的createFrontmatterBackup)。备份路径按 source 键分层、按文件相对路径镜像,且支持 git 与非 git 大脑仓库——不污染源树。此外:
--dry-run预览将要执行的修复而不落盘,批量修复前务必先预览;- 技能输出规则要求:执行
--fix前先向用户说明将修改多少个文件并确认;SLUG_MISMATCH修复会删除slug:字段,若用户是刻意改名则需特别提示; - 不要用
--fix单纯"把 doctor 刷绿"而不先读审计报告——slug 不匹配往往意味着用户故意重命名文件,只有确认改名是有意为之,自动删字段才是正确结果; .bak堆积不是 bug 而是特性:非 git 大脑仓库靠它回滚,确认无误后再删除。
Phase 4:pre-commit 钩子——在源头拦截
对于"本身就是 git 仓库"的大脑,可以安装 pre-commit 钩子,让畸形 frontmatter 根本无法被提交:
gbrain frontmatter install-hook [--source <id>]钩子对暂存区(staged)的.md/.mdx文件逐个执行gbrain frontmatter validate,失败即阻断提交;紧急放行用git commit --no-verify。源码级细节见 frontmatter-install-hook.ts:
- 钩子位于
<git root>/.githooks/pre-commit;大脑根由gbrain sync同款逻辑(discoverGitRoot)发现; - 子目录场景:source 注册为宿主仓库子目录(bootstrap 的
<workspace>/brain布局)时,只在宿主根安装一个钩子,并用 pathspec 限定到该子目录;多个嵌套 source 则合并各自 scope;source 注册在根上则渲染全仓库脚本; --force覆盖已有钩子(覆盖前写<hook>.bak);--uninstall卸载并尽量恢复.bak;- 钩子脚本内
gbrain不在 PATH 时只打印一行警告并退出 0——不会因为某人卸载了 gbrain 就阻断所有提交; - 安装时若
core.hooksPath已被全局/企业模板指向别处、或.githooks/存在其他可执行钩子、或.git/hooks有活动钩子,会打印原因并保持未接线(installed_unwired),由用户手工git config core.hooksPath .githooks或迁移后接线; - 对不在任何 git 仓库内的大脑目录,install-hook 自动跳过并给出一行说明;若仍希望写时校验,可用 cron 调度
audit。
触发词与 Agent 路由
技能在前置元数据中声明了 5 个触发词(triggers)——"validate frontmatter"、"check frontmatter"、"fix frontmatter"、"frontmatter audit"、"brain lint"——并在正文中约定:当用户说出其中任何一个时路由到此技能。路由评估样本见 plugin/skills/frontmatter-guard/routing-eval.jsonl,其中正面用例覆盖审计、校验、修复三类意图,负面用例("what's for breakfast")确认不会误路由。
输出规范:Agent 可解析的报告形态
技能文档给出了两套标准输出格式,供 Agent 直接消费。
极简审计摘要(面向人/Agent 的纯文本):
Frontmatter audit — 17 issue(s) across 1 source(s) [default] /Users/me/brain 17 issue(s) MISSING_CLOSE: 8 NESTED_QUOTES: 5 NULL_BYTES: 4 sample: people/jane.md — MISSING_CLOSE companies/acme.md — NESTED_QUOTES (+ 12 more) Fix with: gbrain frontmatter validate /Users/me/brain --fixJSON 信封(--json时输出,与AuditReport形状对应):
{ "ok": false, "total": 17, "errors_by_code": { "MISSING_CLOSE": 8, "NESTED_QUOTES": 5, "NULL_BYTES": 4 }, "per_source": [ { "source_id": "default", "source_path": "/Users/me/brain", "total": 17, "errors_by_code": { "MISSING_CLOSE": 8, "NESTED_QUOTES": 5, "NULL_BYTES": 4 }, "sample": [{ "path": "people/jane.md", "codes": ["MISSING_CLOSE"] }] } ], "scanned_at": "2026-04-25T22:30:00.000Z" }gbrain frontmatter validate <path> --json返回类似的信封,只是按文件而非按 source 组织结果(files_with_errors、total_errors、files_fixed、dry_run等字段,见 frontmatter.ts)。
技能还强制一条输出纪律:向用户用平实语言呈现计数,不要倾倒原始 JSON。
预防:如何从一开始就写出合法 Frontmatter
技能文档明确指出:修复坏 frontmatter 是好的,但一开始就不写坏是更好的——这是全篇最重要的一节。
YAML 数组:历史上的头号错误源
# 正确:单引号 YAML flow(gbrain 输出的规范形态) tags: ['yc', 'w2025', 'ai'] # 正确:不加引号的标量(值无特殊字符时没问题) tags: [yc, w2025, ai] # 正确:block 风格 tags: - yc - w2025 # v0.37.5.0 之后被容忍、但非规范:JSON 风格双引号 tags: ["yc", "w2025"] # 错误:混用 JSON 对象和字符串(非法 YAML) tags: [{"name": "sports"}, "posterous"]为什么这曾经会坏:v0.37.5.0 之前,校验器靠统计未转义的"数量,任何一行 ≥3 个即标记为嵌套引号。而tags: ["yc", "w2025"]这种 flow 序列按设计就有 4 个未转义双引号——它是合法 YAML,却被愚蠢的计数器误伤。曾有大脑在单次 doctor 运行中因此爆出 6981 条误报。v0.37.5.0 起,校验器在标记前先用js-yaml.safeLoad解析可疑值,JSON 风格数组不再触发NESTED_QUOTES(对应实现见 markdown.ts)。
为什么仍应写规范形态:--fix自动修复引擎与推断 frontmatter 序列化器(frontmatter-inference.ts)都会为tags:/aliases:输出单引号 YAML。新内容写规范形态,源文件风格统一,与--fix运行结果的 diff 为空。
经典 LLM 陷阱:形如tags: [${items.map(t => JSON.stringify(t)).join(', ')}]的模板会产出tags: ["yc", "w2025"]。应改用单引号 + 撇号回退方案:
tags: [${items.map(t => t.includes("'") ? JSON.stringify(t) : "'" + t + "'").join(', ')}]或者直接使用会输出规范 YAML 的 YAML 库。
带特殊字符的标量加引号
# 正确:值含特殊字符时用单引号 title: 'My "Quoted" Title' # 正确:值含撇号时用双引号 title: "Men's Fashion Guide" # 错误:双引号包裹内部双引号 title: "My "Quoted" Title"何时加引号
- 不加引号适用于简单值:
type: person、batch: w2025; - 加引号当值包含
: " ' # [ ] { } | > & * ! ? ,或值以@开头; - 单引号是默认的安全选择;
- 双引号仅在值本身含撇号时使用。
反模式清单:这些事不要做
技能文档用五个"不要"收束边界,全部有源码逻辑背书:
- 未经用户输入不要自动修复
MISSING_OPEN或EMPTY_FRONTMATTER——它们通常意味着作者开始写页面却没写完,静默插入---标记包裹未完成草稿是错误行为(对应 brain-writer.ts 中autoFixFrontmatter对这两类保持不动的实现)。 - 不要不看审计就直接
--fix刷绿 doctor——SLUG_MISMATCH之所以需要人工过目,正因为 gbrain 的 slug 来自路径;只有确认改名是有意为之,删除 slug 字段才是正确结果。 - 不要跳过
.bak备份——对非 git 大脑仓库,.bak就是安全契约;修复后.bak堆积是特性不是 bug,用户可核对 diff 满意后再删除。 - 不要在未注册 source 的大脑上跑
audit——CLI 会优雅返回 "no registered sources to audit",迁移阶段还会产出skipped: no_sources阶段结果;不要用手工路径遍历掩盖,正解是gbrain sources add注册源。 - 不要在非 git 目录安装 pre-commit 钩子——install-hook 会自动跳过并给出一行说明;大脑是宿主仓库子目录没问题(钩子装在宿主根并限定子目录)。看到 "skipped, not a git repo" 而又想写时校验,就用 cron 调度
audit。
与周边能力的协作链
技能文档给出了三条协作链:
gbrain doctor:frontmatter_integrity子检查报告与audit相同的计数——同一套scanBrainSources,单一事实来源(见 doctor.ts 的调用与超时/部分结果处理)。- skills/maintain/SKILL.md:更广泛的大脑健康审计;怀疑还有其他类别问题时,在此技能之后接力。
gbrain lint:技能文件 lint 的重叠规则(CLI 命令而非技能);lint 输出中的frontmatter-*规则名即来自本技能的校验面。
此外,与校验面同源的还有gbrain frontmatter generate子命令(见 frontmatter.ts 与 frontmatter-inference.ts 的DIRECTORY_RULES):对完全没有 frontmatter 的文件,按目录感知规则从路径和内容推断type/title/date/source/tags,零 LLM 调用、完全确定性地补齐元数据;未知/兜底路径默认跳过,避免给任意工作区文档盖上无意义的type: note,需要时显式传--include-catch-all启用旧兜底行为。修复、生成两条路径共用同一套集中式备份机制。
结语:从"事后修复"走向"源头不坏"
frontmatter-guard 技能的完整闭环是:audit 让存量问题可见 → validate 提供可脚本化的单路径校验 → fix 以.bak契约安全批量修复 → install-hook 在提交前拦截新增脏数据 → 编写规范 YAML 从源头消灭错误。配合gbrain doctor的frontmatter_integrity共享校验面与generate的确定性补齐能力,无论大脑是单文件草稿、数万页的生产仓库,还是作为宿主仓库子目录的多源布局,都能获得一致的 frontmatter 质量保障。对 Agent 而言,牢记一条铁律即可:先审计、后修复、备份先行、人工兜底。
- 人工智能
- RAG
- Agent 记忆
- MCP 服务
- 知识管理
【免费下载链接】gbrain
Garry's Opinionated OpenClaw/Hermes Agent Brain
相关推荐
PM Skills Marketplace 贡献指南:从 frontmatter 规范到自动化校验的插件开发实战
PM Skills Marketplace 贡献指南:从 frontmatter 规范到自动化校验的插件开发实战 本文以 CONTRIBUTING.md 为骨架
AI 技能AI 插件Agentic Awesome Skills 技能批量导入实录:2026-03-21 上游技能导入、Frontmatter 规范化与校验流水线
Agentic Awesome Skills 技能批量导入实录:2026 03 21 上游技能导入、Frontmatter 规范化与校验流水线 本文基于仓库维护
AI 技能AI 插件终极指南:pre-commit-hooks自动化修复功能详解之end-of-file-fixer实战
终极指南:pre commit hooks自动化修复功能详解之end of file fixer实战 pre commit hooks 是一个强大的Git预提交
开发工具代码质量Lint版本控制
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考