Engineering agent-design 9 min read

HUMAN_INPUT 自動補完の設計 — SSOT 由来と経験事実を分類して機械で埋める範囲を定義する

執筆 skill が出す HUMAN_INPUT マーカーは 2 種類に分類できる。SSOT から取れる値は機械補完し、経験事実だけ人手に渡す設計で pipeline をスケールさせる方法を解説。

公開 2026-05-27 森本拓見

30 秒で理解する HUMAN_INPUT マーカー

AI 執筆 skill が記事本文を生成するとき、確定値が分からない箇所(数値・固有名詞・体験事実など)には実値を書かず、<!-- HUMAN_INPUT: 説明 --> のようなプレースホルダーを残す。これが HUMAN_INPUT マーカー だ。人間が後で埋める前提のため、マーカーが残ったまま公開されないよう pre-publish gate(G1)が残存をチェックする。本記事は、このマーカーのうち SSOT から機械的に埋められるものと、人間にしか書けないものを分類する設計を扱う。

執筆 skill が生成した本文に残る HUMAN_INPUT マーカーは、すべてを人間が埋めなければならないわけではない。2026-05-19 の pipeline retro で発見したのは、HUMAN_INPUT には少なくとも 2 種類あるという事実だ。分類できれば、機械で埋められる範囲を先に処理し、本当に人間の判断が必要な値だけを残せる。本記事では、その分類基準と SSOT マッピング表の設計、そして blog-fill-ssot skill の pipeline 上の配置を解説する。


HUMAN_INPUT の 2 分類 — SSOT 由来 vs 経験事実

SSOT 由来の例:メンバー数 / skill 数 / 創業時期 / retro 由来失敗事例

SSOT 由来の HUMAN_INPUT は、repo 内に確定した値が存在する

  • メンバー数: src/config/members.ts の配列 length
  • skill 数: ls .claude/skills/ の出力
  • agent 数: ls .claude/agents/ の出力
  • 創業時期: src/config/brand.tscompany.founded
  • retro 由来の失敗事例: blog-ops/retros/*.md の一覧

26

実際、2026-05-19 の retro では、26 件の HUMAN_INPUT マーカーのうち 4 件が SSOT 由来として自動補完できた。内訳は「skill 数 / agent 数 / 創業情報 / retro 由来の失敗事例 2 件」だった。これらは全て、repo の特定ファイルをグレップするだけで取得できる確定値だ。

経験事実の例:コスト額 / KPI 達成値 / 採用経緯 / Stage 評価

経験事実は SSOT には存在しない。本人(執筆者)の記憶と判断にしか依拠できない

  • コスト額: 月次の外部サービス費用など、財務データ
  • KPI 達成値: 実測したトラフィック数・CV 率
  • 採用経緯: なぜそのアーキテクチャを選んだかという意思決定の背景
  • Stage 評価: MVP/β/本番等の判断根拠

これらを機械補完しようとすると「捏造」になる。確定値の根拠がないまま埋めることは、品質ゲートを潜り抜けた誤情報を本文に混入させることに等しい。

分類の判定ロジック:SSOT に問い合わせて存在すれば機械補完

判定フローは次の通りだ:

  1. HUMAN_INPUT マーカーのキー(id)を SSOT マッピング表に照合する
  2. マッピング表に対応するソースが記載されていれば → SSOT 由来として自動補完
  3. マッピング表に存在しない場合 → 経験事実として HUMAN_INPUT を残す
  4. マッピング表にあるが取得値が空/未定義の場合 → HUMAN_INPUT を残す(あいまいに埋めない)

この判定は決定論的に実行できる。RAG のように意味検索で「それっぽい値」を引いてくるのではなく、明示的なキー-ソースのマッピングで確実な値だけを補完する。


SSOT マッピング表の設計

HUMAN_INPUT KEY → SSOT 場所 の明示マッピングが現状規模では最適

SSOT マッピング表は次のような構造を持つ:

mappings:
  member_count:
    source: src/config/members.ts
    query: "members 配列の length"
    type: integer
  skill_count:
    source: .claude/skills/
    query: "ls でファイル数"
    type: integer
  founded_year:
    source: src/config/brand.ts
    query: "company.founded"
    type: string
  retro_failure_examples:
    source: blog-ops/retros/
    query: "*.md ファイルの title 一覧(最新 N 件)"
    type: list

このマッピング表は blog-ops/config/ssot-mapping.yaml に SSOT 化する。skill が参照する単一の正規ファイルにしておくことで、SSOT ソースが増えたときも 1 箇所だけ更新すれば全 skill に反映される。

brand.ts / members.ts / ls .claude/ / retros/ を参照する 4 ソース

現状の SSOT ソースは下記 4 種だ:

  1. src/config/brand.ts: 会社基本情報(創業時期 / 事業領域 / positioning)
  2. src/config/members.ts: メンバー情報(名前 / 役割 / 参加時期)
  3. ls .claude/skills/ / ls .claude/agents/: 実装済み skill/agent の実数
  4. blog-ops/retros/: 蓄積された retro(失敗事例・学びの一覧)

これら 4 ソースはいずれも「自然言語で問い合わせる必要がない」明示的なスキーマを持っている。RAG を導入するより、決定論的マッピングで十分に高精度かつゼロコストに値を取得できる。

RAG より決定論的マッピングが低コスト・高精度な理由

RAG(Retrieval-Augmented Generation)は「何を聞くべきかがあいまいなとき」に有効だ。しかし「member_count というキーに対して members.ts の配列 length を返す」という処理に、意味検索は不要だ。

決定論的マッピングには次の利点がある:

  • 誤補完ゼロ: キーが一致しない限り補完しないため、誤った値が混入しない
  • コストゼロ: API コールが不要、ファイル読み取りだけ
  • デバッグ容易: マッピング表を見れば「どこから取ったか」が一目瞭然
  • 拡張容易: 新しい SSOT ソースはマッピング表に 1 行追加するだけ

blog-fill-ssot skill の設計

pipeline 上の配置:write 完了後 / review 起動前

blog-fill-ssot skill は pipeline の「write → review」の間に入る:

write(blog-tech-write / blog-case-write)

fill-ssot(blog-fill-ssot)← ここで SSOT 由来を機械補完

review(blog-review)← 経験事実の HUMAN_INPUT が残っている状態でレビュー

review を起動する前に SSOT 由来を機械補完しておくことで、reviewer(または human レビュアー)が「これは機械で埋められたか?」を確認する必要がなくなる。review は経験事実の確認と品質ゲートに専念できる。

自動補完の 3 原則:SSOT 確定 / HUMAN_INPUT 残す / あいまい禁止

blog-fill-ssot skill が守る原則は 3 つだけだ:

  1. SSOT 確定: マッピング表に対応するソースがあり、値が確定できる場合のみ補完する
  2. HUMAN_INPUT 残す: マッピング表に存在しない、または値が取得できない場合は {{HUMAN_INPUT: ...}} をそのまま残す
  3. あいまい禁止: 数名数回数年前 のような誤魔化しは書かない。値が不確かなら HUMAN_INPUT として残す

この 3 原則は、retro の「学び 4」から直接導かれている。捏造リスクをゼロにするための最小防御だ。

{{HUMAN_INPUT: id - hint}} 形式のプレースホルダーとの連携

執筆 skill が出力する HUMAN_INPUT マーカーは次の形式を持つ:

{{HUMAN_INPUT: member_count - Yakumo のメンバー数(members.ts で確認)}}

blog-fill-ssotid フィールド(ここでは member_count)を SSOT マッピング表に照合する。照合が成功すればプレースホルダーを実値で置き換える。照合が失敗すれば(経験事実の場合)プレースホルダーをそのまま残す。


まとめ — 機械で埋める範囲を定義することでスケールする

分類の明示化が Opus main thread の mechanical edit を排除する

2026-05-19 の retro 以前は、main thread(Opus)が毎回手動で SSOT を grep して HUMAN_INPUT を置き換えていた。この運用には 3 つの問題があった:

  1. 「Opus は judgment 専用、量産執筆 / mechanical edit は skill 経由」という原則に反する
  2. 記事数が増えると main thread のコストが線形に増加してスケールしない
  3. 「どの SSOT を見るか」が main thread の context 記憶に依存し、fresh context での再現が効かない

SSOT マッピング表と blog-fill-ssot skill によって、この機械的作業を skill に委譲できる。main thread は「これは SSOT から取れるか?」という判断を毎回しなくてよくなる。

次の実装ステップ:マッピング表の拡張と skill の量産適用

現状の SSOT マッピング表は 4 ソースをカバーしているが、記事テーマが増えれば必要なキーも増える。拡張の手順は単純だ:

  1. 新しい HUMAN_INPUT キーが繰り返し出現するようになったら SSOT マッピング表に追加
  2. 対応するソース(ファイルパス / コマンド)を記載
  3. 次回以降の blog-fill-ssot 実行から自動的に補完対象になる

スケールする仕組みは「完全自動化」ではない。機械で埋められる範囲を明示的に定義し、そこだけ機械に委ねる設計だ。人間が判断すべき経験事実は、最後まで HUMAN_INPUT として残り、執筆者に判断を促す。それが捏造なき品質維持の基本構造だ。

関連記事

SHARE X でシェア B! はてブ