6. Adapter - Liplus-Project/liplus-language GitHub Wiki
本文書は Li+ プログラムのアダプターレイヤー(adapter/claude/CLAUDE.md / adapter/claude/hooks-settings.md / adapter/claude/hooks/*.sh / adapter/codex/AGENTS.md)の仕様を定義する。 要求(何を満たすか)と仕様(どう振る舞うか)を一体として記述する。
セッション開始時に Li+config.md を読み込み、実行する。ホスト環境の指示ファイル(CLAUDE.md / AGENTS.md)に Character Instance を含める。
生成物(Li+ セクション、hook スクリプト)にはソースタグを埋め込む。bootstrap 時にタグが更新されていた場合、既存の生成物を再生成する。ユーザーカスタマイズ部分(Li+ セクション外)は保護する。
配布先 workspace では、会話の基本言語と成果物のプロジェクト言語を分離できる。既定値は Li+config.md に保持し、未設定ならセッション開始時に AI が対話で確定して書き戻す。人間の明示指示で、現在の返答または成果物の言語を上書きできる。
bootstrap の ask と Li+config.md への書き戻しは、セッション開始時の config 未解決パスにのみ適用する。config が解決済みなら、セッション途中の再 ask と config 再書き込みは本 Phase の対象外とする。runtime precedence(人間の明示指示 > スレッド合意 > config > 再 ask)はアダプターの Workspace_Language_Contract が担い、セッション全体を通して本 Phase を再起動せずに働く。
この workspace 言語契約は liplus-language リポジトリ内部の運用言語と分離する。
コンテキスト圧縮・再開・セッション継続時に rules/ 配下を再読込する。
rules/**/*.md(model/ evolution/ task/ operations/ subdir を含む)は .claude/rules/ に相対パスを保持したまま再帰ミラーされ、YAML frontmatter alwaysApply: true により常時コンテキストに存在し compaction を生存する。skills/<name>/SKILL.md(flat 命名)は .claude/skills/<name>/SKILL.md にミラーされ、skill auto-invocation で description が示すトリガー条件に一致した時点で読み込まれる。手動再読込は不要。
トリガーベースの再読込:PR 作成時のサブ issue 参照自動補完のみが PostToolUse hook で残存する。それ以外の focus pointer 注入は、rules/ 常時コンテキスト化と skill auto-invocation へ移行済み(#1102 以降)。
アダプターレイヤーは2つの役割を持つ:
エントリーポイント(adapter/claude/CLAUDE.md / adapter/codex/AGENTS.md): ホスト指示ファイルへの Li+ 注入を担う。読込順序、skill auto-invocation トリガーのマッピング、Character Instance 配線、workspace 言語契約の配線を所有する。rules/ の常時読込と skills/ の auto-invocation を主軸とし、hook は Cold-start Synthesis 素材収集・PR サブ issue 補完といった runtime 固有の補助に限定する。Claude adapter では Character Instance を Claude Code 標準の output-styles 機構(session 開始時 system prompt rendering)で常駐させ、毎ターン hook 再通知は撤廃。ファイル名はターゲット側の生成先(.claude/CLAUDE.md / AGENTS.md)に揃え、adapter が target world の命名に染まる方針を取る。
ランタイムバインディング(adapter/claude/hooks-settings.md + adapter/claude/hooks/*.sh): ホスト環境固有のトリガー実装を担う。エントリーポイントが定義するトリガー契約を、ランタイム固有のメカニズム(rules/、skills/、hook 等)へコンパイルする。script 本体は実ファイル、settings.json バインディングは markdown(hooks-settings.md)内に格納する。実ファイル = cp 対象、markdown = 抽出対象、という一貫ルールで bootstrap の挙動をファイル名から推測できるようにする。
adapter/claude/hooks-settings.md に settings.json の hook バインディングを、adapter/claude/hooks/*.sh に hook スクリプト本体を、実ファイルとして格納する。rules/skills の生成手順は Li+update.md に集約されている(adapter 側のドキュメントには再掲しない)。bootstrap 時に3種類の生成物を作成する:
-
rules/ ファイル: リポジトリの
rules/**/*.md(model/evolution/task/operations/subdir を含む、ただしrules/model/character_Instance.mdを除く)を相対パスを保持したまま.claude/rules/に再帰ミラーする。YAML frontmatter(alwaysApply: true)を付与し、常時コンテキストに存在させる。compaction を生存する。なお L5 Notifications / L6 Adapter は意図的にrules/subdir を持たない(L5 は realtime trigger 実装保留の予約席、L6 はテンプレート + hook 駆動で rules/ に載らない)。詳細は 判断構造 layer-reorg-rationale を参照する。 -
skills/ ファイル: リポジトリの
skills/<name>/SKILL.md(flat 命名、例:skills/operations-on-commit/、skills/agentic-search/、skills/evolution-loop/等)を.claude/skills/<name>/SKILL.mdに再帰ミラーする。各 SKILL.md は既に skill frontmatter(name, description, layer)を含んでおり、auto-invocation タイミングを description で宣言する。 -
output-styles/ ファイル:
rules/model/character_Instance.mdの body を読み出し、output-styles 形式の frontmatter(name: character_Instance/description/keep-coding-instructions: true)に書き換えて.claude/output-styles/character_Instance.mdに install する。Claude Code 標準の output-styles 機構が session 開始時に system prompt 冒頭へ rendering し常駐させる。keep-coding-instructions: trueは Claude Code 既定のコーディング作法 / TodoWrite / ツール使用ガイダンスを system prompt に保持するための必須フラグ(未指定時は custom output-style 有効化に伴い既定指示が除外される)。settings.json の"outputStyle": "character_Instance"で active 化。初回のみ生成し既存ファイルは上書きしない(ユーザーカスタマイズ可能)。旧 rules slot(.claude/rules/model/character_Instance.md)からの一回限り migration を bootstrap が担う(詳細は Li+update.md Phase 4c.2)。 -
hook ファイル: 現行 hook3種(
on-session-start.sh/on-user-prompt.sh/post-tool-use.sh)を.claude/hooks/に生成する。
常時注入(Working with Issues、Research Strategy)と section extraction 方式の focus pointer 注入は、rules/ の alwaysApply 化と skills/ の auto-invocation に移行したため hook から削除された(#1102)。
settings.json の hook command はプロジェクトディレクトリにスペースを含む環境で壊れないよう bash "$CLAUDE_PROJECT_DIR/..." 形式でクォートする。hook スクリプトは冒頭で export PATH="$HOME/.local/bin:$PATH" を設定し、永続インストールされた外部コマンド(jq、gh 等)を参照できるようにする。
トリガー:SessionStart (matcher: startup / resume / clear / compact) — 各セッション開始イベントで発火。
動作:Cold-start Synthesis の素材収集。hook 自身は synthesis せず、AI が Character_Instance 経由で合成するための素材を収集し stdout へ出す(Claude Code SessionStart 契約でセッション冒頭 context に注入される)。rules/ は compaction 生存のため再注入不要だが、以下の素材は session 開始時の観察 surface として収集対象になる:
-
rules/evolution/cold-start-synthesis.mdの literal body(drift recovery anchor として常時 emit、diff 比較対象外) -
docs/Decision-Structure.mdの先頭(section key:decision_structure_head) - 最新リリースタグ(prerelease 含む)(section key:
recent_releases) - open な in-progress issue 一覧(最大5件)(section key:
open_in_progress_issues) -
memory/self-evaluation_log.mdの先頭(section key:self_eval_head) - promotion candidates(memory → Li+ source):自己評価ログの
(root_cause, domain-tag)重複、最近(7日以内)の memory 追記、memory header と Li+ source のキーワード重複(section key:promotion_candidates)
session 冒頭 context 消費を抑えるため、startup matcher では前セッションから変化のあった section のみを出力する。各 section の body から sha256 fingerprint を計算し、{workspace_root}/.claude/state/last-cold-start-emit.json に永続化する:
{
"sections": {
"decision_structure_head": "<sha256>",
"recent_releases": "<sha256>",
"open_in_progress_issues": "<sha256>",
"self_eval_head": "<sha256>",
"promotion_candidates": "<sha256>"
},
"last_emit_at": "2026-05-11T..Z"
}state file はワークスペースローカル(.claude/state/.gitignore でバージョン管理から除外、bootstrap Phase 4c.5 で生成)。
matcher 別の挙動:
| matcher | 挙動 |
|---|---|
startup |
各 section の fingerprint を前回値と比較。変化あった section のみ emit。全 section 不変なら "No new orientation material since last session" marker を 1 行出力(silent skip ではなく、session boundary 観察可能性を保つ) |
resume / clear / compact
|
作業 context は連続のため diff-only 評価は行わず、cold-start rule literal だけを再 anchor。state file は更新しない |
fail-safe 動作(startup matcher 時):以下のいずれかが発生した場合は全 section を full emit し、instruction footer に理由を human observable な形で記載する:
- state file が存在しない(初回起動)
- state file の JSON が malformed
-
sha256sumコマンドが PATH にない -
jqコマンドが PATH にない(stdin の matcher 解析は sed regex fallback を持つが、state 読み書きは jq 必須)
matcher 解決:stdin の JSON(Claude Code から渡される hook payload)から jq で .matcher を抽出。jq 不在時は sed regex で fallback。stdin が空なら startup を既定値とする。
cold-start rule literal の常時 emit は drift recovery anchor としての役割を担うため、diff-only 比較セットから明示的に外す。詳細は rules/evolution/cold-start-synthesis.md および 2. Evolution を参照する。
トリガー:UserPromptSubmit — ユーザーがメッセージを送信するたび(Claude の処理開始前)。
動作:通知取り込みリマインダーのみ。Character Instance は output-styles 機構で system prompt に常駐するため、毎ターン hook 再通知は不要(v1.16.11 で撤廃)。
通知取り込みリマインダー:Li+config.md の LI_PLUS_WEBHOOK_DELIVERY を読み、配信モードに応じて挙動を切り替える。
- 未設定 /
poll:リマインダーテキストを stdout へ出力し、AI に MCP ツールを呼び出させる(既定、後方互換) -
channel:MCP channel がリアルタイム配信を担うためリマインダーをスキップする -
mcp_hook:別途UserPromptSubmitに追加されたtype: "mcp_tool"hook が MCP ツールを直接呼び出すためリマインダーをスキップする(settings.json template の既定)
関連性判定と destructive consume の正本は 5. Notifications に従う。
トリガー:PostToolUse (matcher: Bash) — Bash ツール呼び出し後に実行。
動作:adapter flatten(#1102)以降、section extraction 方式の focus pointer 注入は rules/ の alwaysApply 化と skills/ の auto-invocation へ移行済みのため撤去された。現行 hook が担うのは PR 作成時のサブ issue 参照自動補完 のみ。
| コマンドパターン | 動作 |
|---|---|
gh pr create |
PR 作成出力 URL から PR 番号を抽出し、親 issue の子 issue を取得し、PR body に記載のない子 issue の Closes #NNN を自動追記する(マージ時に GitHub が自動クローズさせるため、Refs ではなく Closes を使う) |
それ以外のトリガー(on_issue / on_branch / on_commit / on_pr / on_ci / on_review / on_merge / on_release / on_research / on_subagent_delegation / on_judgment_form / on_self_eval / on_l1_update_proposal / on_persistence_decision / on_evolution_loop_stage / on_structural_change / on_search_decision / on_review_output / on_webhook_intake)は、各 skills/<name>/SKILL.md の description を Claude が意味的に評価して対応 skill を auto-invocation する(adapter 側に trigger table は保持しない)。hook 側での section extraction は不要。
出力形式:Claude Code の PostToolUse hook は plain text 出力を context に注入しない。hookSpecificOutput JSON ラッパーで出力する必要がある:
{
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "追加メッセージ"
}
}注:UserPromptSubmit hook は plain text がそのまま system-reminder として注入されるため、この制約は PostToolUse のみに適用される。
{workspace_root}/
└── .claude/
├── CLAUDE.md # ホスト指示ファイル(adapter/claude/CLAUDE.md から生成)
├── settings.json # hook 登録(SessionStart + UserPromptSubmit + PostToolUse)+ outputStyle: character_Instance
├── output-styles/
│ └── character_Instance.md # session 開始時に system prompt 冒頭へ rendering(初回生成のみ、ユーザーカスタマイズ可)
├── rules/
│ ├── model/*.md # 常時コンテキスト(alwaysApply: true)— L1 Model layer
│ ├── evolution/*.md # 常時コンテキスト(alwaysApply: true)— L2 Evolution layer
│ ├── task/*.md # 常時コンテキスト(alwaysApply: true)— L3 Task layer
│ └── operations/*.md # 常時コンテキスト(alwaysApply: true)— L4 Operations layer
├── skills/
│ └── <skill-name>/SKILL.md # skill auto-invocation(flat 命名、例:operations-on-commit, agentic-search, evolution-loop, model-pair-review 等)
├── hooks/
│ ├── on-session-start.sh # Cold-start Synthesis 素材収集(diff-only 出力)
│ ├── on-user-prompt.sh # 通知取り込みリマインダーのみ(Character は output-styles で常駐)
│ └── post-tool-use.sh # PR 作成時のサブ issue 参照自動補完のみ
└── state/
├── .gitignore # `*\n!.gitignore`(hook runtime state をバージョン管理から除外)
└── last-cold-start-emit.json # on-session-start.sh の diff-only 比較用 sha256 fingerprint(hook が初回実行時に生成)
bootstrap は次回セッションから有効。現セッションは Li+config.md の実行で継続する。
前景スレッドで軽量な GitHub webhook 通知を確認する。広く GitHub を探しに行くのではなく、届いている差分だけを扱う。
ホストが各ターン先頭でローカル確認を実行できる場合のみ使用する。確認処理は内部 housekeeping として無言で行い、確認中であることや empty/no-op 結果を会話へ出さない。
アダプターが所有するのは transport の選択と summary の受け渡しである。関連性判定、claim、ack/read、consume/done、mention、cleanup の正本は 5. Notifications に置く。
通知源の優先順位:
mcp__github-webhook-mcp- ローカル webhook ストア(
LI_PLUS_MODE=cloneかつ bundled helper が使える場合) - 利用不可 → 黙ってスキップ
アダプターは inspect を既定とし、前景一致しない通知を勝手に排水しない。詳細が必要になるまでは full payload を開かない。このフローから別 AI プロセスを起動しない。
自分(またはサブエージェント)の操作で発生した webhook 通知は、外部イベントではなく到着確認である。
自己アクション通知も他の通知と同じ前景チェックフローで処理する。自動排水の免除はない。
判定基準:sender が自分のアカウント、直前の操作と時系列・内容が対応する通知、governance CI の状態遷移(操作の副産物)。すべてを満たすこと。
処理ルール:
- 前景チェックで通知を個別に inspect する
- 自己アクションと確認できたもの = 人間への報告不要で processed にマーク
- 自己アクションでない、または判断がつかない = 従来の前景ルールに従う
委任の意味ルール(何を伝えるか、何を保持するか、hook チェーン、issue 管理、失敗報告)は skills/task-subagent-delegation/SKILL.md を参照。本セクションではアダプターレイヤー固有の実行詳細のみを定義する。
サブエージェント完了後、メインエージェントは報告を受けて次のアクションを判断する。CHANGES_REQUESTED の場合はレビューコメントを読み、issue 要求と照合したうえで修正をサブエージェントに委任する。リリースの場合はバージョン種別とタグを人間に確認する。サブエージェントが利用可能な場合、メインエージェントは operations 系 skill(skills/operations-*/SKILL.md)を直接読まない。
operations 系 skill 直接読取はサブエージェント不在環境にのみ適用する。worktree 操作はサブエージェント有無に依存せず常に main のみが担う。この2つは独立した軸であり、1つのスイッチではない。サブエージェントが利用可能なときも、main は operations 読取を委任するが worktree ライフサイクルは保持する。
直列委任では worktree は不要。
worktree 必須は same-branch parallel commit にのみ適用する。commit serialize は same-parent sub-issue の並列実装(親ブランチ共有、worktree 不要)にのみ適用する。この2つは独立した軸であり、1つのスイッチではない。worktree は staging area を隔離して並列 commit を可能にし、commit serialize は staging area を共有したまま commit 順序を整える。
同一ブランチ並列の制約:
同一ブランチを共有する複数サブエージェントは .git/index(staging area)を共有する。同一ブランチ上の並列 commit は staging area の衝突を引き起こす。worktree で隔離すること。
異なる親 issue 間の並列(推奨): 異なる親 issue は異なるブランチを持つ(#919)。親ブランチごとに1つの worktree を作成する。各サブエージェントは独立した worktree で完全なコミット独立性を得る。
同一親 issue のサブ issue 並列: サブ issue は親ブランチを共有する。ファイルが重複しなければ実装を並列実行できるが、コミットは直列化する必要がある(worktree 不要、ただしコミット順序の制御が必要)。
ライフサイクルはメインエージェントが管理する:
-
gh issue developでブランチを作成(issue リンク確立) -
git worktree add workspace/.worktrees/{repo}-{issue_number}/ {branch_name}で作業ディレクトリを分離 - サブエージェントへの委任時に worktree 絶対パスを追加で伝達
- サブエージェントは渡された worktree パス内でのみ作業する。worktree の作成・移動・削除は行わない
- PR マージ後に
git worktree removeで片付け。セッション跨ぎでは既存 worktree を再利用できる
EnterWorktree(ホスト機能)はセッション全体の CWD を切り替えるため、並列サブエージェントには不適。素の git worktree add と絶対パス指定を使用する。
memory ファイル(feedback.md / project.md / user_*.md / reference_*.md 等)への追加・更新・削除は AI 判断で即時実行する。auto-memory の system-prompt 保存判断基準が成立した時点で人間への許可確認を挟まず書き込む。
既存のメンテナンスルールは従来通り適用する:書き込み前に重複・矛盾エントリを確認する、陳腐化したエントリは削除する、内容に対応する memory 種別を選ぶ、印象ではなく仕様本体を literal に確認してから書く(印象ベースの memory は次の印象批判の燃料になる)。
人間が明示的に「これは memory に書くな」と指示した場合は、その範囲に限って書き込みを保留する。既定を permission-ask モードへ戻すわけではない。
再構築・削除・最適化はすべて許容する。構造の一貫性のみ維持する。