本記事に登場する
HUMAN_INPUTマーカーとは、AI 執筆 skill が記事本文に残す「ここは人間が後で確定値を埋めるべき」を示すプレースホルダー(形式例:<!-- HUMAN_INPUT: 数値を記入 -->)。
AI で記事を量産し始めたとき、最初に気づかず踏む地雷がある。弊社・自社・社内 といった法人含意表現が、生成した本文に自然に混入してしまうことだ。個人事業主や法人化前の小規模チームにとって、これは単なる言葉遣いの問題ではない。ブランドの narrative 整合が崩れ、読者が受け取るイメージと実態にズレが生じる。この問題を構造的に防ぐのが、forbiddenWords と文脈近接検出を組み合わせたハイブリッド検出設計だ。
具体的な引き金は 2026-05-22 公開予定の pillar 執筆中に起きた。blog-fact-check を回したところ、「自社で運営」「社内で完結」のような法人含意表現が 複数の pillar / spoke 記事に分散して 検出された。八雲は法人化していない個人事業主なので、これらはすべて narrative 不整合だ(2026-05-20 の retro を参照)。総件数は当時カウントしていなかったが、「複数記事にまたがって出ている」という事実だけで「人間の review では捕まえきれない、機械で先に止める層が必要」という判断に十分だった。
なぜ単純 forbiddenWords だけでは不足か
弊社 / 当社 / 我が社 は単純マッチで検出できる
弊社・当社・我が社 は、文脈に関わらず八雲が使ってはいけない表現だ。これらは単純な文字列マッチで網羅できる。
# brand.ts の forbiddenWords 相当
forbidden_exact:
- "弊社"
- "当社"
- "我が社"
- "弊所"
どんな文脈で使われていても NG だ。allow-list で対応すべきは他社の発言を引用するケースのみ(例: 「A社は弊社と連携して」 という他社の言葉を引用する場合)。
自社 / 社内 は文脈依存:読者組織の一般論なら OK、自分側を指すなら NG
難しいのは 自社・社内 だ。
「自社の技術スタックを棚卸しすることで、エンジニアの採用基準が明確になる」→ OK(読者組織への一般論)「Yakumo では自社のブログ運用に AI エージェントを活用している」→ NG(自分側を指している)
単純な文字列マッチでは、読者組織の一般論として使っている 自社 まで NG 扱いになり、false positive が大量発生する。記事の論旨そのものを否定することになりかねない。
allow-list で他社引用を除外する設計の必要性
検出の精度を保つためには、allow-list が必要だ。
allow_patterns:
- context: "quote" # 他社・他者の発言を引用している場合
example: "「弊社では...」と同氏は述べている"
allow-list の設計は「機械的に正確な除外」を目指すより、false negative(見逃し)を許容して false positive(誤検出)を減らす方向で調整するのが現実的だ。見逃しは human review で拾える。誤検出は記事の論旨を壊す。
近接検出の設計 — 50 文字以内ルール
自社 / 社内 × 八雲 / Yakumo が 50 文字以内に近接する場合のみ検出
2026-05-20 の retro で確立した設計は次の通りだ:
「自社」または「社内」という語が出現した場合:
→ 前後 50 文字以内に「八雲」または「Yakumo」が存在するか確認
→ 存在する場合: NG(八雲を指している可能性が高い)
→ 存在しない場合: スキップ(読者組織の一般論として扱う)
50 文字という閾値は、日本語の 1 文(平均 40〜60 文字)と概ね一致する。同一文節で自分側への言及と 自社 表現が共起する場合を捉える設計だ。
近接距離の根拠と調整方法
50 文字という数値は「日本語の一般的な文長」を根拠にしている。より長い文章が多い記事では閾値を広げ、短文主体のなら狭めるという調整も可能だ。
調整の際は次の観点で判断する:
- false negative(NG だが見逃した)が多い: 閾値を広げる
- false positive(OK だが NG 扱いにした)が多い: 閾値を狭める
false positive / false negative のトレードオフ
完全な検出は存在しない。設計の目的は「人間のレビューでは見逃しやすい違反を機械で先に拾う」ことだ。完全自動化ではなく、人間の最終判断の手前に機械フィルターを挿む設計として位置づける。
false positive(正しい使用を NG 扱い)は記事品質を落とす。false negative(違反を見逃す)は human review で拾える。設計の優先度は false positive の抑制にある。
SSOT と gate による二重防御
brand.ts と BRAND.md で正規語彙を SSOT 化する
法人語彙の禁則は 2 箇所に SSOT 化する:
-
src/config/brand.ts: プログラムが参照する構造化データcompany: { size: "solo", positioning: "個人事業主", forbiddenVocabulary: ["弊社", "当社", "我が社", "弊所"], contextualForbidden: { words: ["自社", "社内"], proximityTargets: ["八雲", "Yakumo"], proximityChars: 50, } } -
src/_docs/BRAND.md: 人間(執筆者・AI skill)が参照する自然言語ガイドライン- Organization Narrative セクションで voice / 禁則 / 推奨語彙を記載
- 「なぜこの禁則があるか」という背景を説明することで、skill が文脈を理解しやすくする
執筆 skill(blog-tech-write / blog-case-write)に narrative を encode
blog-tech-write / blog-case-write の skill 定義に、narrative 禁則を直接 encode する。skill が本文生成時に 「自分側を指す文脈で自社・社内を使っていないか」 を自己チェックする仕組みだ。
ただし、これは一次防御に過ぎない。LLM は文脈を誤読する場合がある。skill 側での encode は「違反を大幅に減らす」ものであって「完全に防ぐ」ものではない。
blog-review の gate G10 で機械検出を最終確認
三段構えの最後が blog-review の gate G10 だ。この gate は執筆 skill からの出力に対して、SSOT(brand.ts)の forbiddenVocabulary と contextualForbidden 設定を参照して機械チェックを実行する。
執筆 skill(一次防御: narrative encode)
↓
blog-fill-ssot(SSOT 由来 HUMAN_INPUT を補完)
↓
blog-review gate G10(二次防御: 機械検出)← ここで法人語彙を最終確認
↓
human review(三次防御: 最終判断)
この設計で、「書く段階で防ぐ」「生成後に機械で拾う」「最後に人間が確認する」という多重防御が成立する。
まとめ — narrative 整合は構造で守る
ad-hoc な review では再発する。SSOT → skill encode → gate の三段構えが必要
「毎回 review のときに注意して確認する」という運用は機能しない。AI で量産する以上、チェックの見逃しは確率の問題であり、記事数が増えれば違反が混入する可能性は上がる。
構造で守るとは、次の 3 層を設けることだ:
- SSOT: 禁則を
brand.tsとBRAND.mdの 2 箇所に正規化 - Skill encode: 執筆時点で AI が禁則を理解して避ける
- Gate: 生成後に機械的に確認する最終チェックポイント
この構造が整っていれば、新しいメンバーが記事を書いても、新しい AI モデルに切り替えても、SSOT を参照する限り同じ基準が適用される。
法人化のタイミングが来たら SSOT を更新するだけで全 gate が追従する
もし将来、八雲が法人化する判断をしたとき、この設計なら更新は 1 箇所だ。brand.ts の company.positioning と forbiddenVocabulary を更新すれば、blog-review の gate G10 が自動的に新しいルールで動作する。
narrative の整合を守る仕組みは、narrative が変化したときにも追従できる。それが SSOT 設計の本質的な価値だ。