frontmatter-guard について
frontmatter-guardは、gbrainの脳ページのメタデータを検証するスキルです。ページを保守するエージェント向けに、監査とバックアップ付き修復を行い、gbrain doctorと検証ロジックを共有します。
主な機能
- 018種類のfrontmatter問題を検出
- 02ソース別の監査レポート
- 03ファイルまたはディレクトリの検証
- 04修復をプレビューしてバックアップ
- 05コミット前検証フックの導入
活用シーン
- 01複数ソースのページ形式を確認
- 02CIやコミット前のMarkdown検証
- 03同期保留ファイルのfrontmatter修復
- 04無効なYAMLの書き込みを予防
MCP 対応
MCP経由でgbrainを使う方法を説明し、監査、検証、ユーザー承認後のファイル修復をエージェントに案内します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ garrytan/ gbrain --skill frontmatter-guardインストール後、Claude Code で/frontmatter-guardを入力して読み込まれたか確認します。
同梱ファイルrouting-eval.jsonl
詳細
フロントマターガードスキル
規約: 引用ルールについては
skills/conventions/quality.mdを参照してください。このスキルは構造検証を行うものであり、引用監査は行いません。
契約
このスキルは、次のことを保証します。
- すべての brain ページが、フロントマターの8つの標準検証クラスに照らしてスキャンされます
- ネストした引用符、閉じる
---の欠落、ヌルバイト、スラッグの不一致などの機械的なエラーは、要求に応じて.bakバックアップを作成したうえで自動修復できます - 検証ロジックは
gbrain doctorのfrontmatter_integrityサブチェックと共有され、信頼できる情報源が一本化されています - ソースごとにレポートされます(gbrain は v0.18.0 以降、複数のソースに対応)。誤ったルートを黙って監査することはありません
- ファイル同期の保留は、保留レコード(コード、理由、キー、行、修正方法)に基づいて説明され、プレビューを確認したうえでユーザーが承認した、ハッシュに紐づく修復でのみ解消されます
これが必要な理由
brain ページは数か月にわたって蓄積されます。エージェントは、形式が不正なフロントマターを含むページを書き込むことがあります。
- 閉じる
---の欠落(エンティティ検出器のバグ) - 会議ページ内の構造化されていない YAML(取り込み処理のバグ)
- スラッグの不一致(パス名変更が反映されていない)
- ヌルバイト(コピー&ペースト時の事故によるバイナリ破損)
- タイトル内の二重引用符のネスト(
title: "Alice "Ace" Example")
ガードがなければ、これらは gbrain sync が失敗したり、検索結果が役に立たなくなったりするまで、気づかれずに蓄積されます。このガードにより、監査時に問題が明らかになり、簡単に修正できます。
brain ファイルを安全に書き込む(最初に実施)
-
put_page/capture(MCP またはgbrain put)を通してページを書き込みます。gbrain がフロントマターをシリアライズするため、ディスク上のファイルは常に有効な YAML になります。 -
Markdown ファイルを直接書き込むスクリプトやエージェントは、文字列補間ではなく、YAML シリアライザー(
yaml.dump、js-yaml のdump)を使ってフロントマターを作成する必要があります。タイトルに:、#、引用符、改行が含まれると、title: ${title}は正しく機能しません。 -
ディスクに触れずに、書き込む前に生成した内容を確認します。
printf '%s' "$content" | gbrain frontmatter validate --stdin --path notes/2026-10-04-digest.md終了コードが1の場合は、まず修正してください。デフォルトは、厳格な作成ルールです。gbrain が値を引用符で囲めばインポートできる YAML でも、ほかのツールが拒否するため失敗とみなされます。
--importableは、より限定的な「同期で保留されるか」という問いに答えます。 -
信頼できないテキストから、gbrain がアクセスや識別に使うキー(
visibility、derived_from、slug、type、id、source_id)を書き込まないでください。
保留されたファイル:読み込んでから修復する
推測なしではインポートできないファイル同期は保留されます。ソースの残りの部分は引き続き同期され、新しいファイルにはまだページが作成されず、既存のページは最後に正常だったリビジョンを保持し、ファイルが修復されるまで put_page を拒否します(書き込みを再試行しないでください)。保留の確認場所:同期の出力(Held <path>: <code> … Next: <command>)、gbrain sources status <id>(--json の場合は git_holds.items[])、doctor の git_held_files、get_page の file_held、および stale とマークされた検索結果。
各保留レコードには、code、reason、key、line、message(場所のみで、値は含まれません)、fix(正確な argv)、docs が含まれます。reason に応じて対処してください。
| 保留 | 対処方法 |
|---|---|
invalid_frontmatter / yaml_parse | gbrain repair frontmatter --source <id> をプレビューします。通常は needs_review となり、手動で修正する正確な行が示されます。 |
invalid_frontmatter / needs_interpretation | --include-ambiguous を付けてプレビューし、ファイルごとの差分をユーザーに提示して、承認されたものだけを適用します。 |
invalid_frontmatter / ambiguous_identity_key または ambiguous_protected_key | 決して推測しないでください。該当行をユーザーに示し、値をユーザーに決めてもらいます(visibility によってページを読める人が決まります)。 |
frontmatter_slug_conflict | slug: 行を削除するか、ファイルを移動します。修復では --include-ambiguous を付けると、該当行の削除が提案されます。 |
file_too_large | ファイルが固定ページ上限(Markdown は 24 MiB、コードは 5 MB)を超えています。その配下のすべてのページが検索可能なので、上限内に収まるファイルを分割しないでください。sync.exclude に追加するか、上限未満のファイルに分割するようユーザーに依頼してください。MCP トランスポートが拒否した小さめのページは、ファイル単位で対処します(docs/guides/memory-boundaries.md#large-page-limits)。 |
content_rejected | ユーザーが content_sanity.junk_disposition=reject を選択しています。変更する前にユーザーに確認してください。 |
修復の手順(実際の出力を使った手順:docs/guides/repair.md#held-files):
gbrain sources status <id> # what is held and why
gbrain repair frontmatter --source <id> # pass 1: safe quoting only; writes nothing
gbrain repair frontmatter --source <id> --include-ambiguous --diff # pass 2: every interpretation
gbrain repair frontmatter --source <id> --include-ambiguous --only <path> --apply --expect <hash> --yes
すべての --apply(ユーザーのファイルを書き換えます)と、--include-ambiguous を付けたすべての適用の前にユーザーに確認してください。行をタイトルにまとめる、後の重複を残すといった各解釈は推測であり、確認できるのはユーザーだけです。差分を見せてから、プレビューされたハッシュと完全に一致する内容を適用してください。安全クラスの変更は、gbrain がすでに読み取っている値をそのまま引用符で囲むだけですが、それでもファイルを書き換えるため、同じ確認が必要です。
アップグレード前にファイルの破損でブロックされていたソースは、次回の同期で復旧します。今すぐ復旧するには、gbrain sync --source <id> --no-pull を実行します。
検証クラス
| コード | 意味 | 自動修復可能か |
|---|---|---|
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 | 開始と終了はあるが、その間に何もない | いいえ(人による対応が必要) |
フェーズ
フェーズ 1:監査
登録済みのすべてのソース(または --source <id> を指定して1つのソース)を読み取り専用でスキャンします。
gbrain frontmatter audit --json
レポートの内容:
- エラーコード別に集計したソースごとの件数
- ソースごとに最大20件の該当ページのサンプル
- 合計件数
- スキャンのタイムスタンプ
出力は JSON です。エージェントは errors_by_code と per_source を解析し、次の手順を決定します。
フェーズ 2:1つのパスを検証
単一のファイルまたはディレクトリを検証します(ソースの登録は不要です)。
gbrain frontmatter validate <path> --json
終了コード 0 は問題なし、1 はエラーありです。CI パイプラインや pre-commit フックで使用してください。
Phase 3: 修正
問題が見つかった場合:
gbrain frontmatter validate <path> --fix
--fix は変更するすべてのファイルを変更前に ~/.gbrain/backups/frontmatter/ にバックアップし、gbrain が読み取る YAML に引用符を追加して引用符付きにします(変更されるのは該当行のみ)。その後、再検証を行い、エラーが残っている場合は終了コード 1 で終了します。修正したファイルは git に再ステージしてください(git add)。--include-ambiguous は解釈候補を追加します。まず --dry-run でプレビューしてください。
--dry-run は書き込みを行わずにプレビューします。一括で修正を適用する前に使用してください。
管理対象の brain では、--fix による直接修正は拒否されます。代わりに gbrain repair frontmatter --source <id>(上記)を使用してください。各修正済みファイルは、調整済みのライターを通じて公開されます。
Phase 4: pre-commit フック(任意)
brain リポジトリが git リポジトリでもある場合は、pre-commit フックをインストールし、不正なページがコミットされる前にブロックしてください。
gbrain frontmatter install-hook [--source <id>]
このフックは、ステージされた .md/.mdx ファイルの内容(作業コピーではなく、コミットされる内容)に対して gbrain frontmatter validate --staged を 1 回実行します。git commit --no-verify で回避できます。インストールするとユーザーのリポジトリに書き込むため、事前に確認してください。doctor の frontmatter_hook が古いフックを報告した場合は、gbrain frontmatter install-hook --force で更新してください。
トリガーワード
ユーザーが次のいずれかを言った場合は、ここに誘導します。
- 「frontmatter を検証」
- 「frontmatter をチェック」
- 「frontmatter を修正」
- 「frontmatter の監査」
- 「brain の lint」
出力ルール
- 必ず最初に
gbrain frontmatter audit --jsonを実行してください。brain が問題のない状態だと決めつけてはいけません。 - 件数はユーザーにわかりやすい言葉で伝えてください。生の JSON をそのまま出力してはいけません。
--fixを実行する場合は、実行前に変更されるファイル数を伝え、その後に確認を取ってください。SLUG_MISMATCHの修正では frontmatter のslug:フィールドが削除されます。gbrain はパスから slug を導出します。ユーザーが意図的にタイトルを変更した場合は、その点に触れてください。MISSING_OPENまたはEMPTY_FRONTMATTERは、明示的なユーザー入力がない限り自動修正してはいけません。これらは通常、人間の作成者がページの執筆を始めたものの、完了していないことを示します。
連携先
gbrain doctor—frontmatter_integrityサブチェックはauditと同じ件数を報告します。frontmatter_repairableはgbrain repair frontmatterで修正できるファイル数を数え、git_held_filesは保留中のファイルを一覧表示します。skills/maintain/SKILL.md— brain の健全性に関する、より広範な監査です。ほかの種類の問題が疑われる場合は、このスキルの後に実行してください。gbrain lint— スキルファイルの lint に関する重複ルールです(CLI コマンドであり、スキルではありません)。lint の出力に含まれるfrontmatter-*ルール名は、このスキルの検証対象に由来します。
出力形式
監査の概要(簡潔でエージェント向け):
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 --fix
JSON エンベロープ(--json が渡された場合):
{
"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 は、ソースごとではなくファイルごとの結果をキーとする、同様のエンベロープを返します。
防止 — 有効な frontmatter の作成
これは最も重要なセクションです。 壊れた frontmatter を修正するのは大切です。そもそも壊れた frontmatter を作成しないことは、それ以上に大切です。
YAML 配列(過去に最も多かったエラーの原因)
# Correct: single-quoted YAML flow (canonical form gbrain emits)
tags: ['yc', 'w2025', 'ai']
# Correct: unquoted scalars (fine when values have no special chars)
tags: [yc, w2025, ai]
# Correct: block style
tags:
- yc
- w2025
# Tolerated post-v0.37.5.0 but non-canonical: JSON-style double quotes
tags: ["yc", "w2025"]
# Broken: mixed JSON objects and strings (invalid YAML)
tags: [{"name": "sports"}, "posterous"]
以前はなぜ問題が発生していたのか: v0.37.5.0 より前は、バリデーターがエスケープされていない " の文字数を数え、3 個以上ある行にフラグを付けていました。tags: ["yc", "w2025"] のようなフローシーケンスには、仕様上エスケープされていない " が 4 個あります。これは有効な YAML ですが、単純なカウンターは誤ってフラグを付けていました。ある brain では、1 回の doctor 実行でこのようなケースが 6,981 件見つかりました。v0.37.5.0 では、疑わしい値にフラグを付ける前に js-yaml.safeLoad で解析するため、JSON 形式の配列が NESTED_QUOTES を引き起こすことはなくなりました。
それでも標準形式で記述すべき理由: 自動修正エンジン(gbrain frontmatter validate --fix)と推論されたフロントマターのシリアライザーは、どちらも tags: / aliases: に単一引用符の YAML を出力します。新しいコンテンツを標準形式で記述すると、ソースファイルのスタイルが一貫し、--fix の実行による差分がなくなります。
よくある 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 ライブラリを使用してください。
引用符付きスカラー
# Correct: single quotes for values with special chars
title: 'My "Quoted" Title'
# Correct: double quotes when value has apostrophes
title: "Men's Fashion Guide"
# Broken: double quotes wrapping inner double quotes
title: "My "Quoted" Title"
引用符で囲む場合
- 引用符なしでも、単純な値なら問題ありません:
type: person、batch: w2025 - 値に
: " ' # [ ] { } | > & * ! ? ,が含まれる場合、または@で始まる場合は、引用符で囲んでください - 単一引用符が安全なデフォルトです
- 値自体にアポストロフィが含まれる場合に限り、二重引用符を使ってください
エラーが発生した場合
gbrain のエラー code、終了コード、[AGENT] ブロック、または通知ブロックが発生した場合は、エージェントオペレータープロトコルに従ってください。このスキル固有の対応:
gbrain frontmatter validateが 1 で終了する場合:エラーが見つかったことを示します(クラッシュではなく、それが実行結果です)。errors_by_codeを解析し、ソースごとの件数を報告してください。- 修正を実行する前に、変更対象のファイル数を伝え、ユーザーの同意を得てください。修正によって
.bakバックアップが作成されます。また、YAML_PARSE エラーは常に自動修復できるとは限りません。 gbrain syncがファイルを保留する場合(invalid_frontmatter、frontmatter_slug_conflict、file_too_large、content_rejected):同期自体は成功しています。保留内容を確認し(gbrain sources status <id>)、上記の「保留されたファイル」の手順に従ってください。put_pageが新しいファイルが保留されているページへの書き込みを拒否する場合:ファイルを修復してください。再試行しても、書き込みは再び拒否されます。
アンチパターン
ユーザーに確認せず MISSING_OPEN や EMPTY_FRONTMATTER を自動修正しないでください。 これらは通常、人間の作成者がページを書き始めたものの、完成させていないことを意味します。未完成の下書きを囲む --- マーカーを黙って挿入するのは適切ではありません。
監査を読む前に、「doctor を成功状態にする」ために --fix を使わないでください。 SLUG_MISMATCH は、gbrain がパスからスラッグを導出するため、手動確認の対象として明示されます。不一致は通常、ユーザーが意図的にファイル名を変更したことを意味します。スラッグフィールドの自動削除が適切なのは、名前変更が意図的だったと確認できた場合だけです。
.bak バックアップを省略しないでください。 .bak は、git 管理されていない brain リポジトリにおける安全性の保証です。修正の実行後に .bak ファイルが蓄積しても、それはバグではなく機能です。ユーザーは差分を確認し、問題がないと判断したらバックアップを削除できます。
ソースが登録されていない brain に対して audit を実行しないでください。 CLI は「監査対象の登録済みソースがありません」と問題なく返しますが、移行では skipped: no_sources のフェーズ結果が出力されます。手動でパスを走査して補わないでください。ソースを gbrain sources add で登録するのが正しい対処です。
git リポジトリ外の brain ディレクトリには、pre-commit フックをインストールしないでください。 インストールコマンドは、そのようなディレクトリを 1 行のメモとともに自動的にスキップします(ホストリポジトリのサブディレクトリである brain は問題ありません。フックはホストのルートにインストールされ、そのサブディレクトリに対象が限定されます)。「スキップされました。git リポジトリではありません」と表示されても書き込み時に検証したい場合は、cron のスケジュールで audit コマンドを使用してください。