Skip to content

6. Adapter

Claude Lin & Lay edited this page Aug 17, 2026 · 27 revisions

アダプターレイヤー仕様書

本文書は 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/**/*.mdmodel/ 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 の挙動をファイル名から推測できるようにする。


Claude Code バインディング

adapter/claude/hooks-settings.mdsettings.json の hook バインディングを、adapter/claude/hooks/*.sh に hook スクリプト本体を、実ファイルとして格納する。rules/skills の生成手順は Li+update.md に集約されている(adapter 側のドキュメントには再掲しない)。bootstrap 時に3種類の生成物を作成する:

  1. rules/ ファイル: リポジトリの rules/**/*.mdmodel/ 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 を参照する。
  2. skills/ ファイル: リポジトリの skills/<name>/SKILL.md(flat 命名、例:skills/operations-on-commit/skills/model-agentic-search/skills/evolution-loop/ 等)を .claude/skills/<name>/SKILL.md に再帰ミラーする。各 SKILL.md は既に skill frontmatter(name, description, layer)を含んでおり、auto-invocation タイミングを description で宣言する。
  3. 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)。
  4. 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" を設定し、永続インストールされた外部コマンド(gh 等)を参照できるようにする。

on-session-start.sh

トリガー:SessionStart (matcher: startup / resume / clear / compact / fork) — 各セッション開始イベントで発火。一次ソースの matcher 表にある 5 つすべてを settings.json に登録する。未登録の matcher は他の entry にフォールバックせず単に hook が発火しないため、その入口では LI_PLUS_UPDATE_STATUS マーカーも language contract banner も出ない。fork--fork-session + --resume/--continue/fork のバックグラウンドコピー、/branch が該当し、Claude Code v2.1.214 より前はこれらが resume を報告していた。

動作:本 hook はセッション開始時に3つの処理を順に実行する(これは hook 内部の実行順であり、下記「起動時ステータスマーカー」で説明する stdout への emission 順とは別軸なので混同しないこと)。(1) gh CLI 前提条件チェック、(2) 更新同期要否の verify、(3) Cold-start Synthesis の素材収集。(1)(2) は下記「起動時ステータスマーカー」で説明する直接 emit マーカーに対応し、(3) が本節以下で説明する素材収集本体である。hook 自身は synthesis せず、AI が Character_Instance 経由で合成するための素材を収集し stdout へ出す(Claude Code SessionStart 契約でセッション冒頭 context に注入される)。rules/ は compaction 生存のため再注入不要だが、以下の素材は session 開始時の観察 surface として収集対象になる:

  • rules/evolution/cold-start-synthesis.md の anchor(H1 preamble のみ。最初の H2 semantic tag で切る。drift recovery anchor として常時 emit、diff 比較対象外)。H2 節を落とすのは、ルールファイル自体が always-on でロードされるため全文 emit が同一セッションの context への二重載せになるから。H2 節を持たないファイルは全文が anchor になる(切り落としは経済性の措置であり、anchor 消失のほうが重い失敗)。契約の正本は同ファイルの Hook Emission Contract 節 Anchor cut
  • docs/Decision-Structure.md の先頭(section key: decision_structure_head
  • rules/ のパスツリー(cold-start でロードされる rules cache の fetch address table)(section key: rules_tree
  • 最新リリースタグ(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):自己評価ログで同一の観察軸が繰り返し miss と tag されている件、最近(7日以内)に書かれた memory entry、memory entry title と Li+ source のキーワード重複(section key: promotion_candidates
    • 検出対象の3軸は rules/evolution/evolution.md の Pattern Detection Surfacing At Cold-start が定め、しきい値と具体ロジックは adapter 側の裁量(同 rule が明示)。現行値は「同種の観察が THRESHOLD_N=2 件以上」と「一覧の表示上限 SURFACE_CAP=10 件」。上限で切っても総件数は必ず併記するため、省略が隠蔽にならない
    • 検出器1が読む書式:正本は skills/evolution-self-eval/SKILL.md の Axis tag line format 節。1行形(**Axis tags**: <軸>: <判定> / ...)と箇条書き形(**Axis tags (10-axis)**: ヘッダ + - <軸>: <判定>)の2種を読み、軸名は同節の normal form(* 除去 → 括弧修飾の切り落とし → -/_ を空白へ → 空白畳み込み → 小文字化 → 10軸のいずれか1つだけの語境界前方一致なら展開)へ正規化してから集計する。1行形の pair 列は括弧外の または Root cause: / Domain: ラベルで終端する(同節 Inline list end)。ここで言う括弧は ASCII ( ) と全角 を1つの class として扱い、開きと閉じの両方が揃った対だけが「括弧の内側」を作る(対を持たない片方は地の文として読む)。#1651 以前は書式の規定が spec 側に存在せず、表記ゆれで同一軸が別キーに分裂し、行末の自由記述が最後の判定文字列に混入していた。#1653 以前は全角括弧が追跡対象外で、かつ対を持たない ( が行の残り全部を括弧内へ畳んでいた
    • 検出器2・3が読む単位:host auto-memory は 1 memory = 1 file なので、entry の単位はファイルそのもの。title は frontmatter の name:、無ければファイル名 stem。検出器3の token は title 由来で、entry 種別を表す接頭辞(feedback / project / reference / user)は topic を指さないため除外する。pair の報告は同一 source file に別々の token が THRESHOLD_N 個以上落ちた場合に限り、token 数の多い順に並べる(1語だけの一致はこの規模のコーパスでは偶然)
    • 並び順の決定性:3ポートの並び替えはすべてロケール/カルチャ非依存に固定する。bash 版は LC_ALL=C sort、PowerShell 版は [System.StringComparer]::OrdinalSort-Object は現在カルチャ依存のため使わない)。SURFACE_CAP で切り詰める一覧では並び順が「どの項目が残るか」を決めるため、順序の一致は表示上の問題ではない。加えて検出器出力は diff-only emission の sha256 対象なので、順序がぶれると差分が毎回発生する
    • MEMORY_DIR の解決規則:候補ディレクトリは優先順に走査するが、採用条件は「ディレクトリが存在すること」ではなく「消費側が読むファイルを1つ以上持つこと」。marker 集合は MEMORY_DIR 経由で読まれるファイル(self-evolution-observation.md、および検出器が走査する per-topic entry の接頭辞 feedback*.md / project*.md / reference*.md / user*.md)に、2つの解決経路が「何を memory ディレクトリとみなすか」で一致するよう self-evaluation_log.md を加えたもの。ただし最後の1つが実際に判定を左右することはない — self-evaluation_log.md は同じ候補パスを走査する独自の探索で解決されるため、そのファイルが存在する場合は先に primary 経路が採用され、この populated 判定に到達しない。任意の *.md ではなく接頭辞で照合するのは意図的で、無関係なファイル1つでディレクトリが枠を取ってしまうのを防ぐ。存在するだけの空ディレクトリが上位候補にあると、下位候補に実体があっても全消費者がまとめて黙るため。どの候補も marker を持たない場合は未解決のままとし、各消費者が個別のファイル存在チェックで silent skip する(従来と同じ帰結)
  • self-evolution observation surface(memory/self-evolution-observation.md の check window が開いたエントリ):verdict_state: pending のうち next_check <= todayDUEexpires < todayOVERDUE (human judgment needed) として列挙する。ファイル解決は promotion candidates と同じ MEMORY_DIR 経路を再利用し、ファイル不在・該当エントリ無しは silent skip。section key を持たない = diff-only 比較対象外(理由は下記「Diff-only 出力」を参照)。動作契約の正本は rules/evolution/cold-start-synthesis.md の Self-Evolution Observation Surface 節

起動時ステータスマーカー(Li+ update status / Li+ language contract / gh install)

cold-start 素材収集より前に、hook は register_section を経由しない printf 直接出力で3つのマーカーを emit する。いずれも diff-only 比較(sha256 fingerprint 方式)の対象外である。ただし3つのマーカーが matcher(startup/resume/clear/compact/fork)に関わらず毎回再 emit されるのは、liplus-language リポジトリ解決済み(bootstrap 後)の通常セッションに限る(Codex 版の Li+ update status のみ startup 限定。各マーカーの項を参照)。bootstrap 前の経路は挙動が異なるため、下記「pre-bootstrap 早期終了」を参照。

  • ━━━ Li+ update status ━━━LI_PLUS_UPDATE_STATUS=unnecessary tag=<tag> channel=<channel> または LI_PLUS_UPDATE_STATUS=needed reason=<axis1,axis2,...> を出力する。adapter sentinel tag / Li+config schema / workspace 言語契約の3軸 verify 結果であり、意味論(unnecessary/needed の分岐条件と reason 軸)の正本は C. 更新同期手続き を参照する。AI 側の消費契約(Li+update.md walkthrough を skip するか実行するか)は adapter/claude/CLAUDE.md の "Execute the following at startup" ブロックが担い、本書では再掲しない。
  • ━━━ Li+ language contract ━━━LI_PLUS_BASE_LANGUAGE=<値> / LI_PLUS_PROJECT_LANGUAGE=<値> を出力する。値は上記3軸 verify の軸3が Li+config.md から抽出したものをそのまま使う(毎セッション実行時に live な config から取得しており、生成ファイルへの焼き込みではない)。未解決の値は unset として出力し、ブロック自体は(下記 pre-bootstrap 早期終了に到達しない限り)無条件に emit する — bootstrap 済みセッションの内側では「ブロックが無い」状態と「値が無い」状態を AI 側が区別せずに済むため。この marker が在る理由は、契約本文(Workspace_Language_Contract)が常時 context に在るのに対し、そのの解決だけが「Li+config.md を読む」という手続きとして書かれており、同ファイルはどのエージェントの context にも自動ロードされないため(issue #1575)。契約の意味論(base / project の定義と precedence)の正本は adapter/*/CLAUDE.mdAGENTS.mdWorkspace_Language_Contract であり、本 marker は値のみを運ぶ。Codex 版では update status が startup matcher 限定なのに対し、本 marker は Claude 版と同じく全 matcher で emit する(rules 再注入と同じ理由で、非 startup の matcher でも値が context に要る)。
  • ━━━ gh install ━━━gh CLI が PATH 上に無い場合のみ出力する(command -v gh が真を返せばブロック自体が実行されず、マーカーも出ない)。ブートストラップ済み通常セッションに限定すると、ブロックに入った場合の結果は GH_INSTALL_STATUS=installed / failed: <末尾ログ抜粋> / missing: <ホスト別ガイダンス> のいずれかであり、この3値すべてでマーカーは出力される(installed も無言スキップではない)。pre-bootstrap 経路では出力条件がこれと異なる(下記「pre-bootstrap 早期終了」参照。zero-output ケースはそちらにもう1つ存在する)。Linux ホストはアーキテクチャ判定つきで ~/.local/bin/gh へ自動インストールを試み、成否を installed/failed として報告する。macOS と Windows(Git-Bash・MSYS2・Cygwin) はドキュメント化された前提条件として扱い、自動インストールせず具体的な導入コマンド(brew install gh / winget install --id GitHub.cli)を案内する。認識できないホストカーネル(default ブランチ)は、具体的なコマンドは示さず「プラットフォームのパッケージマネージャーで導入せよ」という一般的な案内のみを出す。

pre-bootstrap 早期終了:liplus-language リポジトリが未解決(bootstrap 前)の段階では、hook は gh install チェックの直後、matcher 解決や更新同期 verify に入る前に exit する。このガードは GH_INSTALL_STATUSfailed または missing で始まる場合のみマーカーを出力する。したがって、この経路では gh が既に PATH 上にある場合に加え、Linux 自動インストールが成功した場合(GH_INSTALL_STATUS=installed)も無出力のまま hook が終了する — 「ブートストラップ済み通常セッションでは installed も出力される」の対象外にあたる、もう1つの zero-output ケースである。Li+ update status マーカーと Li+ language contract マーカーはこの経路では一切出力されない。したがって bootstrap 前のセッションでは言語値が context に届かない — この状態の扱い(marker 不在も unset と同じく human へ確認する)は adapter/*/CLAUDE.mdAGENTS.mdWorkspace_Language_Contract が持つ。

出力順序(bootstrap 済みの通常セッション):Li+ update statusLi+ language contractgh install(該当時のみ)→ cold-start 素材(matcher 依存)。

Diff-only 出力(build-2026-05-11 以降)

session 冒頭 context 消費を抑えるため、startup matcher では前セッションから変化のあった section のみを出力する。各 section の body から sha256 fingerprint を計算し、{workspace_root}/.claude/state/last-cold-start-emit.json に永続化する:

{
  "sections": {
    "decision_structure_head": "<sha256>",
    "rules_tree": "<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 観察可能性を保つ)。ただし observation surface が emit された session では marker を出さない — overdue を提示しながら「新規素材なし」と述べるのは自己矛盾のため
resume / clear / compact / fork 作業 context は連続のため diff-only 評価は行わず、cold-start rule anchor だけを再出力。state file は更新しない

fail-safe 動作(startup matcher 時):以下のいずれかが発生した場合は全 section を full emit し、instruction footer に理由を human observable な形で記載する:

  • state file が存在しない(初回起動)
  • state file の JSON が malformed
  • sha256sum コマンドが PATH にない
  • node コマンドが PATH にない(stdin の matcher 解析は sed regex fallback を持つが、state 読み書きは node 必須。#1519 で外部 jq バイナリ依存から node -e に置換済 — node は Claude Code 自身が依存するランタイムのため安全な前提)

matcher 解決:stdin の JSON(Claude Code から渡される hook payload)から node -e.matcher / .source / .session_source を順に見て最初に値のあるものを採る。node 不在時、または JSON parse 失敗時は sed regex で fallback。stdin が空なら startup を既定値とする。実際に host が送るのは .source であり、matcher は settings.json 側のフィルタキーで payload には現れない(.matcher だけを見て .hook_event_name に fallback していた旧実装は、本番形 payload に対して常に SessionStart を返し、既定値 startup に落ちていた。#1632 F1)。

cold-start rule anchor の常時 emit は drift recovery anchor としての役割を担うため、diff-only 比較セットから明示的に外す。詳細は rules/evolution/cold-start-synthesis.md および 2. Evolution を参照する。

self-evolution observation surface も同じく比較セット外だが、外す理由は別軸である。こちらはトリガーが日付駆動なのに body が内容駆動という非対称に由来する。未解決のまま日をまたいだエントリは body が byte 一致のままなので、fingerprint 比較に載せると「最初の 1 セッションだけ表面化し、以後は注意を要する期間ずっと抑制される」という意図と正反対の挙動になる。該当エントリが無ければ body が空になり silent skip されるため、常時 emit にしても通常セッションの context コストはゼロ。expires を過ぎたエントリは OVERDUE としてのみ報告する(next_check も過去であるのが通常だが、同一エントリを両軸で二重に出すのはノイズであり、escalation を担うのは overdue 軸)。

on-user-prompt.sh

トリガー: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 に従う。

post-tool-use.sh

トリガー: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 は不要。

JSON 処理:stdin payload の解析と hookSpecificOutput の組み立ては node -e で行う(on-session-start.sh と同方針、#1519 / #1540)。#1540 以前は外部 jq バイナリに依存しており、jq 未導入ホスト(Windows / macOS / 多くの Linux ディストリビューションで既定では同梱されない)では tool 名の解析が空となり、hook がフォールバックも痕跡も無い無言の no-op に陥っていた。なお本 hook 内の gh api --jq は gh バイナリ内蔵の jq 式エンジンであり、外部依存ではないため置換対象外。

node 不在時の挙動:node は jq より確度の高い前提だが保証ではない(Claude Code は packaged 実行ファイルとして配布され、hook 子プロセスの PATH に node を置くことを契約していない)。そのため command -v node で明示的に分岐し、不在時は「サブ issue 参照を追記できなかったので手動で補完せよ」という静的 JSON を hookSpecificOutput として出力して終了する。無言終了にすると、jq から node へ鍵を差し替えただけで #1540 と同じ不可視の失敗を再現するため。加えて、raw payload に gh pr create が含まれない呼び出しは node 起動前に事前フィルタで抜ける(Bash ツール呼び出しのたびに node を起動しないための高速 path)。ただしこの事前フィルタは生バイトに対する部分文字列一致であり、解析後のガードが照合するのはデコード済みの値なので、両者は一般には等価ではない。コマンド文字列中の空白を unicode escape で書いた payload はデコードすれば一致するが生バイトでは一致せず、取りこぼす。Claude Code の payload serializer が printable ASCII をエスケープしない限り実トラフィックでは到達しない、という前提の上で成立するフィルタである(この前提は Li+ 側で検証できる範囲を超えるため、仮定として明示する)。

出力形式: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, model-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 の実行で継続する。


前景 Webhook 通知取り込み

前景スレッドで軽量な GitHub webhook 通知を確認する。広く GitHub を探しに行くのではなく、届いている差分だけを扱う。

ホストが各ターン先頭でローカル確認を実行できる場合のみ使用する。確認処理は内部 housekeeping として無言で行い、確認中であることや empty/no-op 結果を会話へ出さない。

アダプターが所有するのは transport の選択と summary の受け渡しである。関連性判定、claimack/readconsume/donementioncleanup の正本は 5. Notifications に置く。

通知源の優先順位:

  1. mcp__github-webhook-mcp
  2. ローカル webhook ストア(LI_PLUS_MODE=clone かつ bundled helper が使える場合)
  3. 利用不可 → 黙ってスキップ

アダプターは inspect を既定とし、前景一致しない通知を勝手に排水しない。詳細が必要になるまでは full payload を開かない。このフローから別 AI プロセスを起動しない。

自己アクション通知の処理

自分(またはサブエージェント)の操作で発生した webhook 通知は、外部イベントではなく到着確認である。

自己アクション通知も他の通知と同じ前景チェックフローで処理する。自動排水の免除はない。

判定基準:sender が自分のアカウント、直前の操作と時系列・内容が対応する通知、governance CI の状態遷移(操作の副産物)。すべてを満たすこと。

処理ルール:

  • 前景チェックで通知を個別に inspect する
  • 自己アクションと確認できたもの = 人間への報告不要で processed にマーク
  • 自己アクションでない、または判断がつかない = 従来の前景ルールに従う

サブエージェント委任

委任の意味ルール(何を伝えるか、何を保持するか、hook チェーン、issue 管理、失敗報告)は skills/task-subagent-delegation/SKILL.md を参照。本セクションではアダプターレイヤー固有の実行詳細のみを定義する。

Codex spawn の context 継承

Codex では every subagent spawn の per-call 引数に fork_turns を必ず明示し、省略して既定値に依存することを禁止する。

  • 通常の non-brake spawn は、model を省略して親モデルを継承し、fork_turns="none" を指定する。
  • brake 1 / brake 2 evaluator spawn は既存 evaluator policy に従って model を明示し、fork_turns="none" を指定する。評価材料は self-contained prompt で渡す。
  • dialogue の限定区間そのものが評価材料として必要な場合に限り、fork_turns="3" のような正の10進数字文字列を使用できる。
  • fork_turns="all" による full-history inheritance は通常禁止する。
  • 用途ごとの context 差を保持するため、この拘束は spawn call ごとに行い、adapter/codex/agents/*.toml には固定しない。

これは L3 の context-isolation semantic を Codex の host-specific 引数へ結び付ける規定であり、L3 semantic 自体、独立した model policy、evaluator の model floor / N / M / P / self-contained-prompt 契約は変更しない。

再開機構(brake 裁定フェーズ)

auto / semi_auto では、brake が報告した後に親が実装サブエージェントを再開し、著者に指摘を裁かせる。裁定主体とフェーズ分割そのものの正本は rules/evolution/initiator-autonomy.md Two-stage brake と skills/task-subagent-delegation/SKILL.md にあり、アダプターが持つのはホスト側の結線だけである。再開メッセージに何を入れるかは skills/task-subagent-prompt/SKILL.md Resume-phase authority boundary が持つ。

Claude Code:Agent ツールの SendMessage で、spawn 時に返るエージェント id または名前を宛先にして再開する。新しい Agent 呼び出しは cold start であり再開ではない。フェーズ1の spawn で得た id を保持すること。失えば、再開が保とうとしている実装文脈そのものを失う。id は spawn したセッションの文脈にあるため、それを持たない親には再開先が存在しない。実装より後のセッションで裁定が走る場合は常にこの状態であり、そのとき再構成フォールバックが適用される。条件と形の正本は skills/task-subagent-prompt/SKILL.md Resume-phase authority boundary にあり、アダプターが持つのは「Claude 側は id 喪失の形でこれを生む」という結線だけである。

Codexresume_agent ツールで、保存済み rollout からエージェントを復元する。同じくフェーズ1の id を保持する。fork_turns は spawn call の引数であってここには関係しない——再開は構造上エージェント自身の保存済み context を引き継ぎ、それがこのフェーズの依拠する性質である。resume_agent が使えない場合、またはフェーズ1の id を親が持たない場合(実装より後のセッションで裁定が走るときは常にこうなる)は、再構成フォールバックが適用される。条件と形の正本は同じく skills/task-subagent-prompt/SKILL.md Resume-phase authority boundary にあり、アダプターが持つのは「Codex 側は両方の形でこれを生む」という結線だけである。

メインエージェントの責務

サブエージェント完了後、メインエージェントは報告を受けて次のアクションを判断する。CHANGES_REQUESTED の場合はレビューコメントを読み、issue 要求と照合したうえで修正をサブエージェントに委任する。リリースの場合はバージョン種別とタグを人間に確認する。サブエージェントが利用可能な場合、メインエージェントは operations 系 skill(skills/operations-*/SKILL.md)を直接読まない。この禁止は対の片割れであり、実行主体がメインになりうる手続きのすべてがメインの読める面に正本を持っているあいだだけ成立する。対の明文とそれらの手続きは rules/operations/main-agent-procedures.md が保持する(オペレーションレイヤー仕様書「メインエージェントの手続き」節)。

Main / Subagent の軸分離

operations 系 skill 直接読取はサブエージェント不在環境にのみ適用する。worktree 操作はサブエージェント有無に依存せず常に main のみが担う。この2つは独立した軸であり、1つのスイッチではない。サブエージェントが利用可能なときも、main は operations 読取を委任するが worktree ライフサイクルは保持する。

worktree 並列実行

直列委任では worktree は不要。

worktree 要否と commit serialize の軸分離

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 不要、ただしコミット順序の制御が必要)。

ライフサイクルはメインエージェントが管理する:

  1. gh issue develop でブランチを作成(issue リンク確立)。本ライフサイクルに限定したスコープであり、main がブランチを作るのは worktree を使う場合のみ。直列委任は worktree を使わないため、そこでのブランチ作成はサブエージェント側に残る(skills/task-subagent-delegation/SKILL.md
  2. git worktree add workspace/.worktrees/{repo}-{issue_number}/ {branch_name} で作業ディレクトリを分離
  3. サブエージェントへの委任時に worktree 絶対パスを追加で伝達
  4. サブエージェントは渡された worktree パス内でのみ作業する。worktree の作成・移動・削除は行わない
  5. PR マージ後に git worktree remove で片付け。セッション跨ぎでは既存 worktree を再利用できる

EnterWorktree(ホスト機能)はセッション全体の CWD を切り替えるため、並列サブエージェントには不適。素の git worktree add と絶対パス指定を使用する。


memory 書き込みの自律性

memory ファイル(feedback_*.md / project_*.md / user_*.md / reference_*.md 等、1 memory = 1 file)への追加・更新・削除は AI 判断で即時実行する。auto-memory の system-prompt 保存判断基準が成立した時点で人間への許可確認を挟まず書き込む。

書き込み前の永続化ティアリング判定(hard gate)は adapter/claude/CLAUDE.mdMemory_Write_Autonomy が正本であり、同ブロックが inline で持つ。既存のメンテナンスルール(重複は更新で捌く / 陳腐化は削除 / 矛盾する併存を作らない)は rules/evolution/memory-entry-format.md の Entry Format 節が、明示的な「書くな」指示の scope 限定と literal 確認の原則は rules/evolution/autonomy-block-shape.md の Explicit exclusion scope / Literal verification 節が正本である(後ろ二つは Memory_Write_Autonomy 末尾が委譲する先であり、本文はそちらに在る)。書き込む前に該当する面を読むこと。ここには再掲しない——過去に後ろ二つだけを写した結果、後から Memory_Write_Autonomy にだけ追加された hard gate が写しに届かず、rules/evolution/memory-entry-format.md Trigger point が断とうとしている「memory に永続情報が滞留する」経路がこの面からは素通りに見えていた。二つ目のコピーが drift する。


進化

再構築・削除・最適化はすべて許容する。構造の一貫性のみ維持する。

要求仕様書 (1-6)

参考文書 (A-L)

判断構造

Clone this wiki locally