Skip to content

4. Operations

liplus-lin-lay edited this page Oct 12, 2026 · 33 revisions

オペレーションレイヤー仕様書

本文書は Li+ プログラムのオペレーションレイヤー(rules/operations/*.md + skills/operations-on-*/SKILL.md)の仕様を定義する。要求(何を満たすか)と仕様(どう振る舞うか)を一体として記述する。

rules/operations/*.md は .claude/rules/ 経由で常時コンテキストに存在する(compaction を生存)。skills/operations-on-*/SKILL.md はトリガー時に skill auto-invocation で読み込まれ、ブランチ作成、コミット、PR、マージ、リリース等の操作詳細を提供する。

本文書の各セクションは冒頭に (→ ソース) 形式で対応する権威ソースを明示する。docs/4 は日本語の要求仕様記述面であり、英語の rules/skills が literal なソース・オブ・トゥルースである。両者に差異がある場合はソース側が正となる。

L3 タスクレイヤーとの境界:issue Format、Issue Maturity、Sub-issue Rules は L4 の event-driven トリガーから呼ばれるが、語彙(issue 型・成熟度・ラベル辞書)は L3 タスクレイヤー(rules/task/task.md)が正本である。本文書からは L3 を参照する形にする。


イベント駆動トリガー

(→ 各 skill の description + rules/operations/main-agent-procedures.md。トリガーの索引は本表だけが持つ)

トリガー 対象セクション 権威ソース
act_now ブランチとラベルフロー rules/operations/main-agent-procedures.md の ## Branch and label flow(着手意思は対話から読むもので、backlog / deferred は Parent retains。ブランチ作成は worktree 有無でモード依存 —— 検出サインそのもの。skills/operations-on-branch/SKILL.md は repo-first 実行面のみ保持)
on_issue_create Issue Format rules/operations/main-agent-procedures.md の ## Issue format(起票は Parent retains のため常駐面が正本)
on_issue_edit Issue Format 同上
on_issue_view Issue Maturity rules/operations/main-agent-procedures.md の ## Issue maturity(成熟度判定は Parent retains のため常駐面が正本)
on_issue_sub Sub-issue Rules rules/operations/main-agent-procedures.md の ## Sub-issue rules(同時タスクの親子構造と scope-exceed confirm の発火条件。各場面で開く skill を名指す) + skills/task-sub-issue/SKILL.md(分類・リンク・並行分析・confirm の詳細・事後復旧。起票・分類は Parent retains、並列構造の提案と scope-exceed confirm は人間との対話のため、メインの読める L3 skill に置く)。skills/operations-on-sub-issue/SKILL.md は draft PR による CI 可視化のみ保持
on_commit コミットとプッシュ + docs 同期 skills/operations-on-commit/SKILL.md + skills/operations-on-docs-ownership/SKILL.md
on_pr PR 作成 skills/operations-on-pr-creation/SKILL.md
on_ci CI ループ skills/operations-on-ci/SKILL.md
on_review PR レビュー rules/operations/main-agent-procedures.md の ## PR review(セルフレビューの実行主体が auto / semi_auto では親のため常駐面が正本) + skills/task-pr-review-judgment/SKILL.md(判断側、L3) + skills/task-pr-review-judgment/SKILL.md の ## Review approval check(承認待ちの手順。## PR review が名指す)。skills/operations-on-pr-review/SKILL.md は停止条件のみ保持
on_merge マージ rules/operations/main-agent-procedures.md の ## Merge Execution
on_release 人間確認が必要な操作 / リリース rules/operations/main-agent-procedures.md の ## Human confirmation required と ## Release completion report discipline(人間に問う確認と人間向け報告のためメインのみ) + skills/operations-on-release/SKILL.md(go-sign 後の実行手順)
on_release_state release state フラグ(prerelease / latest)の付与・変更・一括正規化 skills/operations-on-release-state/SKILL.md
on_wiki_sync リリース後の docs → wiki ミラー同期 skills/operations-on-wiki-sync/SKILL.md
on_webhook_intake フォアグラウンド webhook 取込 rules/operations/main-agent-procedures.md の ## Foreground webhook notification intake(実行主体がメインのみのため常駐面が正本)
on_long_output 長 output / 出力途切れ rules/operations/main-agent-procedures.md の ## Chat output limit(チャンキングは複数メッセージにまたがる行為であり、実行主体がメインのみのため常駐面が正本)
on_discussions_reference Discussions 経路 rules/operations/main-agent-procedures.md の ## Discussions intake(外部由来 issue の読みは issue management = Parent retains のため常駐面が正本)
on_session_boundary session 境界での引き継ぎ rules/operations/main-agent-procedures.md の ## Handoff continuity(実行主体は両方。skills/operations-handoff-continuity/SKILL.md はポインタとして残る)
on_notifications_api_call notifications API 直接操作 rules/operations/main-agent-procedures.md の ## Notifications API(直接呼ぶ瞬間は前景取込経路 = メイン専有のため常駐面が正本)

rules/operations/operations.md は以前、冒頭に ## Operations Layer(Layer Position、Foregrounds、Reads through、[TRIGGER_INDEX])を持っていた。どれも各手順の置き場所を案内するだけで、場面での行動を変えない。レイヤー所属と常時ロードは frontmatter(layer: L4-operations、alwaysApply: true)が持つ。skill は description 一致で発火し、main-agent-procedures.md は常時ロードなので、索引を経由せずに届く。このため節ごと外し、索引は本表に残した(#2127)。

サブエージェント委任

(→ skills/task-subagent-delegation/SKILL.md(L3、L4 から cross-layer 利用。委任プロンプト作成は skills/task-subagent-prompt/SKILL.md、spawn パラメータは skills/task-subagent-spawn/SKILL.md、subagent 側 lifecycle label は skills/task-subagent-state-labels/SKILL.md))

長時間セッションでの注意劣化対策として、全 operations トリガーの手順実行をサブエージェントに委任できる。サブエージェントは毎回新鮮なコンテキストで rules/operations/*.md と skills/operations-on-*/SKILL.md を読むため、注意の薄まりが発生しない。

サブは手順を実行して結果を報告する。メインは報告を受けて判断する。PR レビュー判断基準はタスクレイヤー(skills/task-pr-review-judgment/SKILL.md)に置き、メインが operations 系 skill を直接読む場面をゼロにする。メイン自身が実行主体になる手続き(セルフレビューの formal record、マージ)は常駐面の rules/operations/main-agent-procedures.md が正本であり、これが禁止と対になる(「メインエージェントの手続き」節)。

サブエージェント機能は最適化であり必須ではない。使えない環境では従来通りメインが実行する。委任の詳細(何を伝え、何をメインに残すか、モード別スコープ)は L3 の権威ソースに従う。


ルール

(→ rules/operations/operations.md の ## Operations Rules)

破ったら壊れる一文一制約。理由・条件なし。

  • issue リンク(gh issue develop)は常に必須。GitHub への初回 push より前に実行する
  • 親 issue = 1ブランチ。sub-issue ごとの個別ブランチは作成しない
  • sub-issue を持つ親 issue = 親 PR 1本。sub-issue ごとの個別 PR は禁止
  • コミット単位の CI 可視化は draft PR を親ブランチ上で早期に open することで実現する(PR を分割しない)
  • コミットタイトル = ASCII 英語のみ、1行
  • コミットボディは省略不可
  • コミットボディに含めるもの:変更要約 + 意図または背景 + issue 参照
  • コミットボディに LI_PLUS_PROJECT_LANGUAGE の文を最低1文含める
  • PR タイトル = ASCII 英語のみ、1行
  • PR ボディ = LI_PLUS_PROJECT_LANGUAGE
  • PR ボディに issue 参照を含める
  • issue 参照の形式 = #<issue番号>。# の前置は形式の一部であり、issue <番号> や裸の <番号> は issue 参照ではない。issue 参照が要求される箇所すべてに適用する
  • 上記2本のタイトル行は body 行とは別の軸に乗る。そこでの ASCII 英語は1行タイトルに対する GitHub 側の慣行であって LI_PLUS_PROJECT_LANGUAGE が解決する値ではなく、project language が他の言語である workspace でもタイトルは ASCII 英語のままである。body 行を契約参照として読みながらタイトル行までパラメータ化してしまうのが、この一文が抑える誤読である
  • body 行が解決するのは host workspace に対してである。Workspace_Language_Contract(adapter/claude/CLAUDE.md / adapter/codex/AGENTS.md)はその到達範囲がどこで止まるかの正本であり、述べているのは止まる位置だけである(They do not change LI_PLUS_REPO governance)。その先で何が governance するかは定めていない。したがって操作対象のリポジトリが LI_PLUS_REPO のリポジトリ自身である場合、LI_PLUS_PROJECT_LANGUAGE はその body 言語へ届かず、届くものは同リポジトリ自身の governance が定める。下の行は、そこで挙げる3つの面について同 governance が要求するものを述べる。そこに挙がっていない面がそれゆえ免除されるわけではない。直上のタイトル行と1組をなす——あちらは固定されているものをパラメータ化する誤読を抑え、こちらはこれらの行が配布されてきた当のリポジトリを操作しながら body を配布先の値で解決してしまう誤読を抑える
  • その governance: 操作対象のリポジトリが LI_PLUS_REPO のリポジトリ自身である場合、その commit body / PR body / issue body はいずれも、同リポジトリ自身の governance 言語による文を少なくとも1つ含む。その言語を定めているのも、それを欠く実行を落とすのも .github/workflows/liplus-ci.yml であり、値はそこで読む。これは LI_PLUS_PROJECT_LANGUAGE が解決した値ではなく、読んでいる workspace への要求でもない。record surface へ移さず、この面に置いたままにする
  • 実装変更を含む PR は、対応する docs/ の更新を同一 PR 内に含める。分割は禁止
  • docs/ を正本とする。Wiki は反映先であり、正本にしない。この行の docs/ は、リポジトリの番号付き要求仕様書とアルファベット付き参考文書を指す。skills/evolution-persistence-tiering/SKILL.md の docs-tier(wiki を含む永続度の階層名)とは同じ語で別の軸である
  • 例外は Decision Structure entry。実体は Decision_Structure_Write_Autonomy により wiki へ直接書かれ、他のどこにも存在しないため、この entry については wiki が正本である。docs/Decision-Structure.md が持つのは運用 index のみ。仕様は docs/Decision-Structure.md を正本とし、ここには写さない
  • リリース後の Wiki 同期は必須。省略は禁止。Wiki 同期はリリースフロー完了の gate
  • 要求仕様書は実装後のフォローアップではない。実装前に作成・更新する
  • PR タイトルには変更の影響範囲を含める
  • リリースの state フラグ(prerelease / latest)とリリース body は、リリース作成時と state 変更時に skills/operations-on-release/SKILL.md の Canonical Release Creation Command と skills/operations-on-release-state/SKILL.md の Release State Rule を読む(内容は下の「リリース state ルール」「リリースルール」。#2141 で常時ロード面の写しを外した)
  • mark_processed は消費した全 webhook イベントに対して必須。省略すると backlog が蓄積する
  • 実行主体がメインエージェントになりうる手続きは、operations-* skill ではなく rules/operations/main-agent-procedures.md を正本とする(下の「メインエージェントの手続き」節)

場面に限られる節を常時ロード面から外した(#2141)

#2138 と同じ方針の、rules/operations/operations.md への適用。特定の場面でしか使わない手順を、その場面で常時ロード面の名指しが届く面へ移した。移すかどうかは、移したあともその場面で手順が確実に読まれるかで決め、場面ごとに常時ロード面の文が移し先を名指す形に限った。手順の中身は変えていない。

  • ## Post-L1-Merge Runtime Observation の手順本体 → 既存の skills/evolution-observation-entry/SKILL.md の # Post-L1-Merge Runtime Observation。移したのは起点(どのセッションで観測し、どこで繰り越すか)、観測セット、繰り越したセッションは判定を書かないこと、任意のスポットチェック、既存の観測軸との分離。場面は L1 基層に触れる PR のマージ後の瞬間だけで、rules/operations/main-agent-procedures.md の ## Merge Execution がその瞬間に operations.md の同名節を名指し、常駐に残した節が skill の節を名指す。移し先は miss 判定のエスカレーション先と繰り越しの記録先を元から持つ skill で、マージ後の瞬間の義務(Auto-entry trigger)で既に開かれている。evolution-* なのでメインが読める。常駐面には、対象(layer: L1-model の変更)と観測を行うこと、呼び出しアンカーの文(docs/L.-Hop-Count-Instrument.md S11 のアンカー)を文面のまま残した。main-agent-procedures.md・execution-mode.md・evolution-l1-update-gating・evolution-full-run からの節名による参照は、常駐に残した節へそのまま解決する。
  • リリースの state フラグとリリース body の 4 行 → 置き場所は skills/operations-on-release-state/SKILL.md の Release State Rule と skills/operations-on-release/SKILL.md の Canonical Release Creation Command。フラグの 3 行は Release State Rule が同じ内容をすでに持っていたので、常駐面の写しを外した。リリース body の行のうち --notes "" で空 body を渡さない禁止だけは skill に無かったので、Canonical Release Creation Command に足した。場面はリリース作成と state 変更だけで、実行するのは go-sign の後に委譲を受けたエージェントである(go-sign の受け取りは常駐の rules/operations/execution-mode.md の human judgment gate と main-agent-procedures.md の ## Human confirmation required が持つので、operations-on-actor-placement の実行主体の基準ではメインにならない)。常駐面には 2 つの skill の節を名指す 1 行を残した。

残した候補:

  • リリース術語の解釈の段と、削除の前に確認で止める成果物の列挙、および人間の指示の「prerelease tag / stable tag」の読み方。人間がどの瞬間に「消して」「stable にして」と言うかは決まっておらず、不可逆な操作の確認点そのもの(li-plus-always-on-footprint-load-bearing 却下理由 3(b))。
  • ## Autonomous Run Stop Condition。冒頭の文は、誰が舵を握っているか、実行モード、production に届くかに関係なく成り立つと自ら述べる判断の点である。残りは、deploy 成功で走完報告を書き始める既定の傾きに逆らう規律で、検出サインは報告を書いている最中の兆候である。人間のいない自走では想起が落ちても捕まえる者がいない。移すには新しい skill が要り(この場面で開かれるメインの読める既存 skill が無い)、その description が移せる約 1 KB の大半を食う。
  • リリース後の Wiki 同期の行。skills/operations-on-release/SKILL.md が「常駐の Operations Rules が正本」として名指しており、リリースフロー完了の gate である。

operations.md = 9,076 B → 7,337 B(-1,739 B)。evolution-observation-entry の description が 93 B 伸びたので、常駐面の正味は約 -1,646 B。docs/L.-Hop-Count-Instrument.md の S11 はツール跳躍が変わらない(観測手順の到達先が、元からツール跳躍 1 だった miss 判定のエスカレーション先と同じ skill になった)。判定の理由は Decision Structure の operations-rule-moment-scoped-sections-move-to-skills が持つ。


メインエージェントの手続き

(→ rules/operations/main-agent-procedures.md)

アダプタの一文「Main never reads operations skills directly when subagent is available.」(adapter/claude/CLAUDE.md / adapter/codex/AGENTS.md)は、単独で置かれた禁止ではない。原型の #881(5333c16)は、この禁止と同時に「メインが必要とするものは常駐で持てる層へ移す」措置を入れている。意図は役割分離(サブが手順を実行し、メインは報告を受けて判断する)であって、コンテキスト節約ではない。

対を明文で置く:この禁止は、実行主体がメインエージェントになりうる手続きのすべてが、メインの読める面に正本を持っているあいだだけ成立する。 メインが読める面 = skills/operations-*/SKILL.md を除く Li+ の全面。サブエージェントは全面を読むので、メインが読める面は両者が届く面でもあり、そこに置いた正本はもう一方のために写しを作る必要がない。

operations-* skill に、実行主体がメインになりうる要求が加わった時点で適用する維持ルール:正本をメインの読める面へ移し、skill 側にはポインタを残す。誤った修復は2つ。

  • 写しをメインの読める面にも置き、skill 側にも残す —— 二つ目のコピーが drift する
  • 「メインが実行主体のときは読んでよい」と禁止の射程を絞る —— 禁止が存在する理由である役割分離を捨てることになり、しかも要求は依然として pull 面にあるため、実行主体はすでに動き始めてからしかそこへ届かない

検出サイン:operations-* skill の中に、実行主体がモード依存で書かれた手続き、あるいは「マージ判断を持つエージェント」と書かれた手続きがある。それは auto / semi_auto では親である(skills/task-subagent-delegation/SKILL.md の Rules)から、要求は実行主体が読めない場所に着地している。本ルール成立以前に3例が実測されている(#1708、いずれも semi_auto):セルフレビューの formal record とマージ手続きはここへ移し、再開プロンプトの停止条件は移さない —— その literal の実行主体はサブエージェントであり親は運び手にすぎないので、親はリテラルではなくポインタを運ぶ形にした(skills/task-subagent-prompt/SKILL.md Resume-phase authority boundary)。

4例目(#1714)は、ルールに先行したのではなく検出サイン自身が捕まえた最初の1件である:承認待ちの確認手順(Review approval check)を「PR レビュー」節の指す常駐面へ移した。#1713 がこのサインを実装している最中に発見され、その PR の射程外に置かれたため、サインは既知の陽性を1件抱えたまま出荷されていた。サインに捕まったことは修復の中身を変えない —— 適用する維持ルールも移設の形も同じである。

修復の分岐は正本側に基準として置いてある:メインが自分で実行しなければならない要求は正本ごと移し、メインが運ぶだけの要求はポインタを残す。 後者は literal の実行主体がサブエージェント側にある形であり、正本は skill 側に留まる。

正本の移設は半分にすぎない(#1762)

skill は description が場面に合致することで起動する。したがって正本が抜けたあとも description がメインの立つ瞬間を名指したままなら、skill はメインを引き込み続ける —— 禁止を破るのはエージェントの選択ではなくファイル自身のトリガーであり、移設は違反を修復したのではなく改名しただけになる。残り半分は、description を その skill に残る読み手 まで絞ること。残る読み手はサブエージェント、およびサブエージェント不在フォールバック時のメイン(skills/task-subagent-delegation/SKILL.md の Autonomy)である。後者はサブエージェントが存在しないときにのみ発火し、それは禁止が適用されない条件そのものなので、そこへ絞った description は禁止に抵触しない。

どちらの読み手も残らない skill は空であり、ポインタとして残さず削除する。ただし読み手以外に1つだけファイルを支えるものがある:編集できないポインタの解決先であること。 削除するとポインタが宙に浮くため load-bearing であり、その場合は「起動条件を持たない」と宣言するリダイレクトスタブとして残す。

編集できないアダプタリテラル(#1762)

adapter/claude/CLAUDE.md / adapter/codex/AGENTS.md の ## Optional Webhook Notification Flow ブロックはバイト単位で凍結されている。Li+update.md が、インストール済みファイルから剥がす legacy trailer をこの同じブロックから導出するため、ここが drift すると移行前インストールに対する migration が黙って壊れる。禁止を満たすためにアダプタを編集することは、ガバナンス上の欠陥を実働の migration 欠陥と交換する取引になる。

rules/model/axis-separation.md は層をまたぐ矛盾を「上位が勝つ」で決着させず境界の修理へ差し戻すので、リダイレクトは rules/operations/main-agent-procedures.md 側が持つ。検出サイン:禁止と同じ sentinel 区画の中に、operations-* skill を方針の所在として名指すアダプタ行がある。

実測3例(#1762)

  • skills/operations-foreground-webhook-intake —— 実行主体はメインのみ(発火の瞬間がユーザー turn の開始であり、サブエージェントは turn を持たない)。2026-08-16 のセッション冒頭、サブエージェント利用可能な状態でメインが実際に起動した。正本を常駐面へ移し、skill はリダイレクトスタブとして残した(凍結アダプタ行の解決先であるため)。
  • skills/operations-on-issue-format —— skills/task-subagent-delegation/SKILL.md の Rules が issue creation / issue management をモード分岐なしで Parent retains に置く。正本を常駐面へ移し、skill はポインタとして残した(サブエージェントは実装中の issue body 更新と失敗報告コメントで到達する)。
  • 本 issue の起票そのもの —— 2例目と同一経路。同じ移設で解消される。

全件棚卸しと確定した対象集合(#1764)

#1762 / #1763 は個別の実測から入ったため、対象は「気づいた分」で閉じていた。#1764 は残りを推測で足すのではなく、全 operations-* skill 17件を実行主体の軸で棚卸しして集合そのものを確定させた。判定に使ったのは既存の literal 2つだけであり、新しい基準は立てていない。

  1. skills/task-subagent-delegation/SKILL.md の Rules にある Parent retains
  2. メインしか持たない面 —— 人間との対話(確認 / go-sign / 提案)、人間向け報告、user turn 境界。サブエージェントはこれらの面を持たない(## Foreground webhook notification intake の移設理由がすでにこの形で書かれている)

どちらにも当たらないものは、サブエージェント不在フォールバック時にメインが実行しうるだけであり、上記のとおり禁止に抵触しない。「メインが選べば実行できる」ことは根拠にならない —— 実装と operations の委任は既定であり、選択の余地は判定軸ではない。判定軸の正本は skills/operations-on-actor-placement/SKILL.md の Actor criterion にある(#2117 までは rules/operations/main-agent-procedures.md の The bar and its pair 本体に置いていた。移した理由は下の「判定基準と維持ルールを常駐面から外した(#2117)」)。本節はその記録である。

発火した10件と修理形:

skill 発火根拠 修理形
operations-on-issue-maturity maturity は Parent retains に明示 正本移設 + 削除
operations-on-pr-review Actor = parent in auto / semi_auto と自ら書いている(検出サインそのもの) フローのみ移設 + 停止条件は残置
operations-on-release 人間確認と完了報告がメイン専有 対話・報告部のみ移設
operations-on-release-state go-sign 到着の瞬間を description が名指していた description のみ修正(本文は手順のみで移設不要)
operations-on-sub-issue 起票・分類は issue creation、並列提案と scope-exceed confirm は対話 判断部のみ移設
operations-on-branch tier 判定が対話の空気読み、backlog / deferred は Parent retains、ブランチ作成は worktree 有無でモード依存 判断とブランチ手順を移設 + repo-first 面は残置
operations-chat-output-limit チャンキングは複数メッセージにまたがる行為で、人間向けチャットだけがその面を持つ 正本移設 + 削除
operations-handoff-continuity issue body は Parent retains、chat memory はメインのみ 正本移設 + ポインタ化
operations-notifications-api 直接呼ぶ瞬間は前景取込経路 = メイン専有 正本移設 + 削除
operations-discussions 軸 (b) のみ。description が親の立つ瞬間を名指し、残る読み手が無かった 正本移設 + 削除

発火しなかった5件:operations-on-ci / operations-on-commit / operations-on-docs-ownership / operations-on-pr-creation(いずれも実行主体がサブエージェントの phase に閉じる)、operations-on-wiki-sync(Parent retains のどれにも当たらない。人間に触れる箇所は2つあり、いずれも発火しない —— STOP して escalate する側は operations-on-ci と同型で、サブエージェントは親への報告で escalate できる。unclassified ページの go-sign 側は、published wiki の削除ゲートが rules/operations/operations.md と rules/operations/execution-mode.md の human judgment gate にすでに常駐しており、この skill は人間向け発話の形を指定していない —— 指定している operations-on-sub-issue の scope-exceed confirm とはそこで分かれる。名指されたページを運ぶだけの親は運搬役であり、維持規則がポインタで解く側にあたる。リリース手順から呼ばれるが、その呼び出し側自体が skill に残るためメイン → operations skill のポインタは生じない)。

既修理2件(operations-foreground-webhook-intake / operations-on-issue-format)に回帰はない。

軸が2本あることを実装で確認した。正本の所在(operations-on-release-state は本文が発火せず description だけが発火した)と、description が名指す瞬間(operations-on-release は本文の一部と description の一部が別々に発火した)は独立に判定する必要がある。

機械的検査は tests/test_skill_reference_resolution.py が CI で担う。維持ルールの両半(正本を移してポインタを残す/読み手が残らない skill を削除する)はいずれも rules/ skills/ adapter/ をまたぐ相互参照を書き換えるため、取りこぼしたポインタは解決先を失う。それは実行時に何も失敗させず、AI が名前を読んでファイルが無いだけで終わるので、他にその喪失を報せる面が無い(rules/model/subtractive-structural-beauty.md の「手順ではなく構造で固定する」側)。検査対象は上記3面に限り、docs/ は除く —— 記録面であり、削除済み skill(skills/operations-on-merge/SKILL.md)を過去の経緯として正当に名指すためである。検査は実行主体の軸を一切見ないので、軸の対象外の skill で落ちることはない。同じテストは同じ3面(adapter/ の .toml エージェント定義を含む)について、rules/<path>.md のパス参照が実在ファイルへ解決すること、github.com/<owner>/<repo>/wiki/<slug> 形式の wiki リンクの slug に .md 拡張子が付いていないこと(#1557 で直した形)も検査する(#1574)。

節頭の配置理由を落とした(#1800)

#1762 / #1763 / #1764 の移設は、移設された各節の節頭に「なぜこの節がここにあるか」の文を伴っていた。判定基準そのものは rules/operations/main-agent-procedures.md の ## The bar and its pair に一度書かれており、各節が持っていたのはその基準を自分の場合に当てはめ直した文である。15 節で合計 8,220 B(当該ファイルの 21%、常時ロード rules/ 全体の 6.7%)を占めていた。rules/model/subtractive-structural-beauty.md Core principle (A) が拒む形であり、rules/model/liplus-coding-rule.md の Body States Behavior が「本文は挙動を述べ、導出は判断記録が持つ」と分けている軸でもある。導出の行き先は本節を含む本ドキュメントであり、上の実測3例・棚卸し表・修理形の記録がすでにその役を果たしている。削除ではなく所在の確定である。

残したもの(適用の瞬間に使われる情報であり、導出ではない):

  • 各節の Actor = 行。誰が実行するのか、モードで変わるのか。## PR review / ## Self-review formal record のモード依存(auto / semi_auto は親、trigger はサブ)と、## Branch and label flow の worktree 有無による分岐は、行そのものに残した。
  • Canonical. と、ポインタ先の skill が何を保持しているか(## Sub-issue rules の draft PR による CI 可視化、## PR review の停止条件、## Branch and label flow の repo-first 実行面)。
  • ## Human confirmation required の、rules/operations/execution-mode.md にゲート列挙があり本節はそれを再掲しないという範囲宣言。統治条項であり、削ると人間判断ゲートの列挙がこの節へ再流入する。

カーブアウトを 15 節すべてについて個別に確認した。他所に無い論証が埋まっていたのは 1 節のみである。

  • ## Merge Execution —— 節頭は基準の再導出ではなく、別形の論証である。## The bar and its pair が持っていた2条件(#2117 以降は skills/operations-on-actor-placement/SKILL.md の Actor criterion)は「実行主体がメインになりうるか」を問うが、この節の論証は「発火の瞬間に、居合わせていて かつ 読むことを許された読者が一人もいない」という第3の形であり、基準側に無い。節頭をそのまま残した。
  • ## PR review —— 起票時にもう1件の候補として名指されていた。モード依存 actor そのものは Actor = 行に残り、その導出(trigger では誰もマージしないため actor が反対側に決まる、という筋)は skills/operations-on-pr-review/SKILL.md の Delegated-subagent stop condition が同じ内容を持つ。二重であり、落とした。

見出しと意味タグは 1 つも変えていない。CI は節名を検証しない(tests/test_skill_reference_resolution.py はパス解決のみを見る。節名検証は #1792 で未実装)ため、節名を変えれば rules/ skills/ adapter/ docs/ に散る 31 箇所の参照が黙って壊れる。節の内側の散文のみを対象とした。

skills/operations-* 側の再導出を落とした(#1922)

上の #1800 は rules/operations/main-agent-procedures.md 側だった。同じ形が skills/operations-*/SKILL.md にも残っていた —— ポインタ(正本の所在+そこが何を保持しているかの列挙)に加えて、「なぜ正本をここに置かないか」を ## The bar and its pair の基準(2条件のいずれかで実行主体が確立するか)に自分の場合を当てはめ直して書いた段落である。build-2026-09-09.3 実測で対象は 7 ファイル / 9 段落、合計 3,468 B(2 段落持つファイルが 2 本)。

file before after delta
operations-foreground-webhook-intake 1,505 B 809 B -696 B
operations-handoff-continuity 1,339 B 896 B -443 B
operations-on-branch 1,913 B 1,425 B -488 B
operations-on-issue-format 1,461 B 926 B -535 B
operations-on-pr-review 3,154 B 2,710 B -444 B
operations-on-release 4,184 B 3,718 B -466 B
operations-on-sub-issue 2,133 B 1,737 B -396 B

9 段落すべてを個別にカーブアウト確認した。他所に無い論証は 1 件も無く、9 件とも落とした。

  • operations-foreground-webhook-intake の 2 段落(起票時にコーディネータが「落とせる候補」と留保していた「なぜファイルを削除しないか」を含む)は、## The bar and its pair 末尾の byte-frozen アダプタ literal の段落(Li+update.md が legacy trailer をそこから導出するくだりを含む)と literal で同旨だった。起票時コメントで確認済み。
  • operations-handoff-continuity / operations-on-branch / operations-on-issue-format / operations-on-sub-issue の各1段落は、いずれも Parent retains の当てはめ直し。main-agent-procedures.md 側の対応する節は #1800 で既に同型の文を落としており、skill 側だけがその論証の写しを残していた。
  • operations-on-pr-review の1段落は ## The bar and its pair の「One shape resolves the other way」がすでに skills/task-subagent-prompt/SKILL.md Resume-phase authority boundary を例示として名指しており、二重だった。ポインタが持っていた「正本が何を保持するか」の列挙(self-review mandate / review basis / self-review procedure / mode-specific human gate / follow-through)は文として残した。
  • operations-on-release の2段落のうち、Human Confirmation Required 側は末尾の一文(「確認はこの手続きに先行する」という実行順序の事実)だけを残し、導出部分のみ落とした。Release Completion Report Discipline 側は導出のみで残す実行順序情報が無く、段落ごと落とした。

見出し・意味タグは変更していない(git diff -U0 -- skills/ | grep -E '^[+-](#|<[a-z])' は空)。description frontmatter は対象外(変更していない)。

tests/test_skill_reference_resolution.py = 2 passed / 158 subtests passed。ローカル全件 python -m pytest tests/ = 237 passed / 776 subtests passed。

判定基準と維持ルールを常駐面から外した(#2117)

rules/operations/main-agent-procedures.md は常時ロードされる面で、#2117 の時点で 33,592 B あった。節ごとに文を読み、識別線(rules/model/liplus-coding-rule.md の Body States Behavior:その文を読む者の行いが変わるか)を当てた。メインが運用の場面で何をするかを決めていない文は 3 か所だった。

  • ## The bar and its pair の判定基準と維持ルール(3,525 B → 864 B)。「実行主体がメインになりうる」の 2 条件、「移設は半分にすぎない」の後半(description の絞り込み、リダイレクトスタブ)、誤った修復 2 つ、検出サイン、運び手にはポインタを残す分岐、編集できないアダプタリテラル。読むのは operations-* skill に新しい要求を書き加えるとき、つまり Li+ の source を編集するエージェントだけで、メインの運用場面(issue、PR、マージ、webhook 取込など)では一度も使われない。実行に使う手順なので、それを使う場面で読まれる面である skills/operations-on-actor-placement/SKILL.md(description が上の場面を名指す)へ、文面のまま移した。常駐面には、禁止と対の文(対は「メインの読める面に正本がある間だけ禁止が成立する」、メインの読める面の定義)、凍結ブロックから正本へ向かう案内、skill への 1 行のポインタだけを残した。rules/operations/operations.md の Operations Rules 末尾の 1 文は、同じ skill を直接名指すようにした。
  • ## Position(256 B)。Layer = と Load timing = は frontmatter(layer: L4-operations、alwaysApply: true)と同じ内容で、「実行主体がメインになりうる手続きを常駐面に置く」は The bar and its pair の対が述べている。読み手の行いを変えず、他に残る所在があるため、節ごと外した。
  • ## Foreground webhook notification intake の Preconditions:(197 B)。github-webhook-mcp >= v0.11.3 と MCP サーバーの登録場所は、webhook 取込の場面でメインが何をするかを決めず、配信を設定する側の前提である。adapter/claude/hooks-settings.md の mcp_tool entry behavior と docs/B.-Configuration.md の LI_PLUS_WEBHOOK_DELIVERY の節が同じ内容を持つので、それらに残した。Codex 側の凍結ブロックは要件の所在として adapter/codex/hooks-config.md を名指すため、同ファイルの mcp_tool webhook entry 節に要件の 1 段落を追記した(#2117 第3ラウンド)。not connected が毎ターン出るときの扱い(実害のないノイズ)は、読み手の行いを決めるので常駐面に残した。

外していないもの。Canonical. と、ポインタ先の skill が何を保持しているかの行は、#1800 が適用の瞬間に使われる情報として残すと判断した行であり、その判断を覆す測定が無いので触っていない。Actor = 行、所有判定 step 2 の残存制限と「step 2 を作成に狭め戻さない」禁止(読みでは捕まらない型の欠落を実測が差し戻した文。measurement-caught-what-read-based-removal-test-missed)も残した。

参照は、skills/operations-foreground-webhook-intake/SKILL.md の非削除の根拠の指し先(skills/operations-on-actor-placement/SKILL.md の Maintenance rule へ)と、tests/test_skill_reference_resolution.py の docstring が指す維持ルールの所在を除いて変えていない。The bar and its pair の節名は残るので、skills/task-pr-review-judgment/SKILL.md / skills/task-subagent-prompt/SKILL.md / skills/operations-foreground-webhook-intake/SKILL.md / tests/test_skill_reference_resolution.py の参照はそのまま解決する。

main-agent-procedures.md = 33,592 B → 30,476 B(-3,116 B)。新しい skill の description(358 B)が skill 一覧に常駐で加わるので、常駐面の正味は約 -2,750 B。判定の理由は Decision Structure の main-agent-procedures-carry-behavior-only が持つ。

場面に限られる手順を skill へ移した(#2138)

#2117 が理由だけの文を外したのに続く二段目。常時ロードの rules/operations/main-agent-procedures.md から、特定の場面でしか使わない手順を、その場面で読まれるメインの読める skill へ移した。移すかどうかは、移したあともその場面で手順が確実に読まれるかで決めた。確実に読まれる条件は、場面ごとに常時ロード面の名指しが skill の節を指していることで、skill の自動起動の想起には頼らない(li-plus-always-on-footprint-load-bearing の却下理由に当たらない形)。

  • ## Sub-issue rules の手順本体 → 新設の skills/task-sub-issue/SKILL.md(L3。親子 issue 構造は rules/task/task.md が L3 の前景に置く語彙)。移したのは、作業単位の定義と sub-issue / sibling の分類リトマス、sub-issue の API、並行競合分析、scope-exceed confirm の閾値・同期集合の carve-out・confirm の形・literal に当たらない発火の禁止・PR レビュー時の発火の却下、per-sub-issue PR の事後復旧。常駐面には、同時タスクの親子構造(複数タスクの場面そのものが発火条件で、名指す面が他に無い)と、scope-exceed confirm の発火条件(サブエージェントが自分の commit 前に検出する。skill の起動に頼ると検出が落ちる)を文面のまま残し、各場面で skill を開くことを 1 文で名指した。
  • ## Review approval check → 既存の skills/task-pr-review-judgment/SKILL.md の ## Review approval check。場面はセルフレビュー pass 後に人間ゲートが立つとき(semi_auto の minor / major、trigger の全 PR)だけで、常駐の ## PR review がその 2 か所で skill の節を名指す。セルフレビュー自体がこの skill を開いており、確認手順が読むレビュー決定を判断するのも同じ skill である。## Merge Execution の Post-merge moment の言及も skill を指すようにした。

残した候補:

  • ## Human confirmation required。停止語、force push、branch 削除はどの瞬間にも来る。リリース部分は 1 行で、不可逆な操作の確認点そのものなので、明示の冗長性の側に置く(li-plus-always-on-footprint-load-bearing 却下理由 3(b))。
  • ## Release completion report discipline。人間向けの完了報告で go-sign の催促に流れる既定の傾きに逆らう規律で、検出サインが示すとおり、書いている最中に自分では気づかない型の逸脱を止める。手順を探しに行く場面ではなく、書きながら効いている必要があるので、skill に移すと想起に依存する。加えて、メインが読める L4 の skill の置き場が無い(operations-* はメインが読めない)。
  • ## Notifications API。直接呼ぶ場面を名指す常時ロードの文が無く、移すと届く経路が description の想起だけになる。450 B 程度で、新しい skill の description が削減分の大半を食う。
  • ## Discussions intake。外部由来の issue を読む場面は issue に着手するたびに来る(その場面での挙動は ## Branch and label flow の担当者確認が持つ)。約 360 B で、移す利得が description の費用を下回る。
  • ## Foreground webhook notification intake。毎ターンの冒頭に使う。

main-agent-procedures.md = 30,446 B → 27,054 B(-3,392 B)。新設 skill の description(317 B)が skill 一覧に常駐で加わり、task-pr-review-judgment の description が 109 B 伸びたので、常駐面の正味は約 -2,966 B。docs/L.-Hop-Count-Instrument.md では S4 の confirm 詳細までの経路がツール跳躍 1 つ増える(理由は同ファイル S4 の追記)。ほかのシナリオは変わらない。判定の理由は Decision Structure の main-agent-procedures-moment-scoped-procedures-move-to-skills が持つ。


自走 (autonomous run) の停止条件

(→ rules/operations/operations.md の ## Autonomous Run Stop Condition)

静的検証(TS check、unit test、CI)は runtime の正しさを立証しない。subrequest 上限、IPC、rate limit、schema migration の副作用などの runtime 経路は静的検証とは別軸に存在し、緑のチェックが報せるのは静的軸を通ったことだけで、runtime 軸については何も報せない。これは CI と実機の対が存在する限り成り立ち、誰が舵を握っているか、実行モードが何か、その走行が production に到達するかどうかには依存しない。runtime 軸を閉じるのは走っている系の観測だけである。

節名になっている停止条件は、この一般則の適用例の一つであって射程ではない。AI が人間の介在なしに走る場合(夜間、semi_auto / auto モードで deploy まで到達するケース)、「deploy 成功」は停止条件にならない。

production に到達する自走では、以下を最終ステップとして必ず実行する:

  • deploy 完了後、production log を最低 5 分観測する
  • cron 駆動のワークでは、「deploy 完了」とは「deploy コマンドが exit 0 で終わった時点」ではなく「deploy 後の最初の cron 周回が log で観測できた時点」を指す
  • ホストの logs surface(ブラウザの dashboard、wrangler tail、同等の CLI)を使う。事前付与済みのブラウザ権限は、人間監視下のセッションのために留保するのではなく、自走中に積極的に活用する

アンチパターン:「human が朝に確認するから、自走の post-deploy 観測は不要」。検出タイミングの利得(夜間検出 vs 朝検出)こそ自走が提供すべき価値であり、観測を省略するとその価値を放棄することになる。

停止条件が誤適用されている兆候:

  • deploy 成功の瞬間に走完サマリを書き始めている
  • 自走自身が verify する前に「人間が見てくれる」を理由にしている
  • dashboard / log アクセス権限が事前付与されているのに自走中に未使用
  • 走完報告が cron interval 1 周分より短い時間で提出されている

L1 マージ後のランタイム観測

(→ 対象と呼び出しアンカーは rules/operations/operations.md の ## Post-L1-Merge Runtime Observation、起点・観測セット・繰り越しは skills/evolution-observation-entry/SKILL.md の # Post-L1-Merge Runtime Observation(#2141 で移した))

L1 基層の変更(layer: L1-model frontmatter を持つファイル。通常は rules/model/*)には、変更された規則が実行時文脈に載った時点で短窓の観測を行う。上の自走停止条件と対をなす観測であり、こちらの観測対象は規則適用の瞬間における AI の内部判断挙動である(上の post-deploy 観測が追うのは外部プロセスの出力)。観測軸は別だが、名目上の予算は同じ 5 分。

呼び出しアンカーは rules/operations/main-agent-procedures.md の ## Merge Execution がマージの瞬間に名指す。その瞬間が各モードで何であるかは同節の Post-merge moment が定める(本書「マージ」の「マージ後の瞬間」)。この手続きの実行主体はどのモードでもメインエージェントであり、operations 系 skill はメインには発火しないので、アンカーをそこに置くと読み手を素通りする。

起点 = 変更された規則を実行時文脈に載せた最初のセッションであり、~5 分の予算はそのセッションの内側で使う。マージ後の瞬間(上記 Post-merge moment)を持つセッションがそれを載せている場合(Li+ ソースを main で走らせている workspace)は、その瞬間に下の観測セットをそのまま走らせる。載せていない場合(タグに同期した workspace)は、そのセッションは観測せず繰り越す —— その PR の memory/self-evolution-observation.md エントリの notes に繰り越しを記録し(エントリが無い PR ではマージ済み PR へのコメントとして記録する。skills/evolution-observation-entry/SKILL.md)、規則を載せた最初のセッションで観測を取って、繰り越しを記録した場所に結果を追記する。

そのセッションの内側で ~5 分以内に実施する観測セット:

  1. トリガーサンプル:変更された規則を読み、その規則が適用の瞬間に発火すべき代表的プロンプトを 1 つ与える。発火を確認する。実行時文脈に規則が載っていなければここで止まり、上の起点に従って繰り越す。
  2. self-eval エントリ:3-5 行の判定(fire / partial / miss)を memory/self-evaluation_log.md に書く。miss 判定は skills/evolution-observation-entry/SKILL.md の 2 週間サイクルへ即座にエスカレートする。

繰り越したセッションは判定を書かない。

任意(best-effort):

  • 5 軸ゲートのスポットチェック:変更が触れたゲート軸で判断形成を 1-2 件通す。特定の軸に触れない変更ではスキップする。

既存の観測軸との分離:

  • skills/evolution-l1-update-gating/SKILL.md の長期観測 = マージ前の閾値ゲート。起票時点で適用する
  • memory/self-evolution-observation.md の 2 週間サイクル = マージ後の長窓。持続的な regression の検出に用いる。上の繰り越し notes はこのエントリに相乗りするだけで、expires / verdict lifecycle は動かさない
  • brake 1(skills/evolution-parallel-agent-eval)= マージ前ゲート。本観測はマージ後であり、別軸

責務

条件→行動。省略不可。AI が条件を判断し、条件に合致したら必ず実行する。

ブランチとラベルフロー

(→ 正本は rules/operations/main-agent-procedures.md の ## Branch and label flow。着手意思は対話の空気から読むもので、サブエージェントは対話面を持たない。backlog / deferred は non-state lifecycle label = Parent retains。ブランチ作成自体も worktree 利用の有無で実行主体が変わる。skills/operations-on-branch/SKILL.md はポインタを持つ)

着手意思は対話の空気から判断する。チェックリストで確認しない。不明瞭な場合は機械的にではなく、感じをもって聞く。

タイミング ラベル ブランチ
NOW(今やる) in-progress 作成する
SOON(近いうち) backlog 作成しない
SOMEDAY(いつか) deferred 作成しない

上表が決めるのはどの tier に当たるかであり、in-progress 遷移が何で構成されるかではない。その遷移はラベル単体であり、skills/task-subagent-state-labels/SKILL.md Work start が正本である(タスクレイヤー仕様書「actor 軸(issue assignee)」)。

ライフサイクルラベルは「いつ着手するか」、成熟度ラベルは「どこまで収束したか」。ライフサイクルラベルを成熟度の代用にしない。

空気読みは timing tier 判定(NOW / SOON / SOMEDAY)にのみ適用する。label 付与は tier 結果からの決定的な写像であり、空気読みの二度目を伴わない。tier が決まればラベルは上表に従って機械的に付与する。

trigger mode でも issue の作成・本文更新とブランチ準備は待たない。人間トリガーの対象は実装開始と PR レビューである。

ブランチ作成

(→ 正本は rules/operations/main-agent-procedures.md の ## Branch and label flow。skills/operations-on-branch/SKILL.md はポインタを持つ)

gh issue develop は親 issue のみに対して実行する。sub-issue(子・孫・…)は親ブランチ上でコミットする。親ブランチは gh issue develop で親 issue にリンクされるため、そのブランチからの PR マージは親を自動クローズする。これは single parent PR flow(後述「sub-issue ルール」参照)の下では意図通りの挙動である。親 PR 1本のマージは全 sub-issue 完了後に行われるため、親の自動クローズもそのタイミングで正しく発火する。

sub-issue ごとに親ブランチ上で個別 PR を作る運用は禁止する。最初の PR が merge された時点で、残りの sub-issue が未完了のまま親が自動クローズされるためである。独立ブランチ・独立 PR が必要な単位は sub-issue ではなく sibling issue として切る。

issue に着手する前(ブランチ作成と委譲の前)に author と Assignees 欄を読む(gh issue view {issue_number} -R {owner}/{repo} --json author,assignees,body,comments)。author の login が github-actions[bot] または app/github-actions(Discussions の bot)の issue は、人間の明示的な go が出るまで着手しない。認証中の gh actor 以外のアカウントが入っていて、そのアカウントから issue を引き継いだことを示す handoff record(現担当を記した本文/交代コメント)が無ければ、その issue は「取られている」と読み、着手しない。進めたいときは先にその相手か人間に確認する。in-progress が付いていなくても同じで、「assigned だが in-progress 無し」も取られている扱いとする。自分のアカウントが入っていることは、自分が現担当である根拠にならない——1つのアカウントを複数のセッションが使いうる。その場合は handoff record とセッション間の調整面で現担当を確かめてから判断する。

ブランチ作成前にローカルとリモートの存在確認を行う。リモートに既存ブランチがある場合、後からリンクは張れない。

# 存在確認
local:  git branch --list {branch-name}
remote: gh api repos/{owner}/{repo}/branches/{branch-name}  # 404 = not exists

# ブランチ作成 + issue リンク
gh issue develop {issue_number} -R {owner}/{repo} --name {session-branch} --base main

ブランチ作成は assignee 手順を持たない。actor 軸が発火するのは親の委譲の瞬間であり、ブランチ作成の時点でも in-progress 遷移の時点でもない(タスクレイヤー仕様書「actor 軸(issue assignee)」/ skills/task-subagent-delegation/SKILL.md ルール、フィールドの読み方は skills/task-subagent-state-labels/SKILL.md Actor axis)。

ローカルエラー時の対処:gh issue develop がローカルで失敗してもGitHub 側では成功する場合がある。リンク済みブランチを確認してから判断する。

gh api graphql -f query='{ repository(owner:"{owner}",name:"{repo}") { issue(number:{number}) { linkedBranches { nodes { ref { name } } } } } }'

リンク済みならそのブランチを使用する。リンクなしならリトライまたは人間にエスカレーションする。

sub-issue ルール

(→ 発火条件(同時タスクの親子構造、scope-exceed confirm の発火)は rules/operations/main-agent-procedures.md の ## Sub-issue rules、手順本体は skills/task-sub-issue/SKILL.md。skills/operations-on-sub-issue/SKILL.md はポインタを持つ。親子 PR 制約は rules/operations/operations.md)

sub-issue は AI が追跡する作業単位。粒度ではなく責務で分ける。

sub-issue か sibling issue かの分類リトマス

問い:「この単位は親の atomic deliverable を壊さず独立に ship できるか?」

答え 分類 運用
Yes(独立 ship 可) sibling issue 親子ではなく独立 issue として立てる。各 issue が自前のブランチと PR を持つ
No(親と一体で初めて意味を持つ) 正当な sub-issue 親ブランチ上でコミットし、親 PR 1本に合流させる

独立に ship できるなら sub-issue にする意味がない。「sub-issue ごとに別 PR で独立に出したい」と感じた時点で、それは元々 sibling issue にすべき単位だったというシグナルである。PR を分割するのではなく、分類を見直す。

single parent PR フロー(本筋、#919 原設計)

sub-issue を持つ親 issue は、以下の構造で運用する:

  • 全 sub-issue のコミットを1本の親ブランチに蓄積する
  • 親ブランチに対する PR は親 issue あたり1本だけ、main へ向けて作成する
  • sub-issue はその1本の PR の中で処理される
  • コミット単位の CI を見たい場合は、最初のコミット push 直後に親 PR を draft で open する。pull_request.synchronize によって以降の push ごとに CI が走り、PR を分割せずに per-commit CI が得られる
  • 親 PR の ready for review(gh pr ready {pr})は全 sub-issue 完了と PR 本文の確定後に行う
  • merge は全 sub-issue 完了後に1回だけ行う
  • parent auto-close はこの構造下では正しく働く:親 PR の merge は最後のイベントであり、その時点で全 sub-issue は既に closed になっている

sub-issue ごとに個別 PR を作る運用は禁止する。親ブランチ上で複数 PR を連続 merge すると、最初の merge で親が自動クローズされ、残りの sub-issue が未完のまま親が閉じる事故が発生する(観測: github-webhook-mcp#198 / PR #203)。

並列性と分類

同一セッション内で複数のタスクを並行で扱う場合は、独立 issue の並列作成ではなく親子構造(親 issue + sub-issue)にする。複数 ready issue のファイル重複分析は target files で判定する。

重複 判断
なし 並列安全。並列 sub-issue 構造を人間に提案
部分重複 共有ファイルへの変更を統合 sub-issue に分離して提案
統合 sub-issue 並列 sub-issue 完了後に直列実行(依存順序あり)

target files が issue body に無い場合は、purpose と premise から推定する。

ドキュメント同期と要求仕様の責務

(→ skills/operations-on-docs-ownership/SKILL.md)

配布向けプロジェクトでは、最低限の docs/ として要求仕様書を持つ。新規・小規模プロジェクトではまず1ファイルの要求仕様書を作ればよい。規模が大きい場合は分割してよい。

実装を始める前に、対応する要求仕様書を先に作成または更新する。挙動変更・バグ修正・仕様変更では、まず要求仕様書の該当箇所を変更し、コードとテストはその仕様差分を実装・検証するために更新する。

Li+ の挙動や運用ルールに効く判断は、番号付き要求仕様書(1–9)と対応するプログラムファイルへ固定する。補助メモや実験ログを残してもよいが、それを正本にしない。要求仕様書は可読性が向上する場合に分割してよい。

spec(Li+*.md)または動作コードを変更するコミットでは、docs/ に対応する更新があるか確認する。未更新であれば push 前に追加する。別 PR への分離は禁止。

Li+ リポジトリの tests/** に書く散文(docstring / コメント)が述べてよいのは、その test が観測したことと、試験している主張の正本の在り処までである。規範はそこで述べず、必要なら正本(rules/** / skills/**)を指す。振る舞いについての記述は観測条件を伴い、条件を越えて読める語(permanently / always / never / any)は落とすか条件を併記する。test の意図説明・再現手順・先例参照は対象外。背景と経緯は進化レイヤー仕様書の Evolution Loop 節にある。

同期が必要な集合のメンバーを 1 つ編集するときは、編集の前後で grep-sweep を pair で実行する。編集前に所属する集合全体を grep して全メンバーを列挙し(記憶ではなく列挙から編集対象を確定)、編集後に同集合を再 grep して旧形のメンバーが残っていないことを確認する。典型的な集合 = docs mirror 同期対象(docs/ とその wiki mirror)/ parity 全 block(claude CLAUDE.md ⇔ codex AGENTS.md 等)/ 同一規範文の全出現箇所。

PR タイトルの良い例・悪い例:

# bad:  fix(config): negative duration handling
# good: fix(config): treat negative durations as below-minimum rather than error

コミットとプッシュ

(→ skills/operations-on-commit/SKILL.md)

プライマリは git push。git が使えない環境では GitHub API フォールバック(blob/tree/commit/ref 作成)を使う。複数ファイル時は tree 作成後にファイル数を検証し、減少していた場合はコミット中止する。

# プライマリ
git push origin {session-branch}:{target-branch}

# フォールバック(単一ファイル)
gh api repos/{owner}/{repo}/contents/{path}  # PUT base64 sha

# フォールバック(複数ファイル)
1. create blobs: gh api .../git/blobs  # per file
2. create tree:  gh api .../git/trees  # verify count after
3. create commit: gh api .../git/commits
4. update ref:   gh api .../git/refs/heads/{branch}

PR 作成

(→ skills/operations-on-pr-creation/SKILL.md)

親 issue あたり PR は1本(上の「single parent PR フロー」参照)。sub-issue を持つ親 issue では、すべての sub-issue と親自身を1つの PR の merge で閉じる。sub-issue ごとの個別 PR は禁止する。

draft PR の早期 open(オプション、per-commit CI 用)

sub-issue を持つ親 issue では、最初のコミットを push した直後に親 PR を draft で open してよい。

gh pr create --draft -R {owner}/{repo} --base main --head {session-branch} ...

以降の push ごとに pull_request.synchronize で CI が走り、PR を分割せずコミット単位の CI 可視化が得られる。全 sub-issue 完了と PR body 確定後に gh pr ready {pr} で ready for review に切り替える。draft PR の早期 open は必須ではなく、長期化する親作業のための利便機能である。

PR body 形式

issue ごとのブロック形式で記述する。クローズさせる issue(sub-issue と親 issue の両方)は Closes #xxx で参照する。各ブロックに2〜3行の要約を書く。詳細は issue を参照。deferred・open のまま残す子 issue は含めない。

single parent PR flow 下では、親 issue も sub-issue と同じく Closes #xxx で参照する。親 PR は最終 merge 1回で親と全 sub-issue を同時に閉じるため、親をクローズしない理由がない。

Part of #xxx は、現在の PR が最終親 PR ではない場合にのみ使う(例:別の親 issue に対して明示的に deferred な残部を先行 merge するケース)。canonical な single parent PR flow では Part of は登場しない。

GitHub の自動クローズキーワード(公式リスト):close / closes / closed / fix / fixes / fixed / resolve / resolves / resolved。Refs はクローズキーワードではなく自動クローズしない。マージ時にクローズさせたい issue には Refs を使わない。

PR 作成後:

  1. 実行中の GitHub CLI 認証 actor を PR の assignee に self-assign する:

    gh pr edit {pr} -R {owner}/{repo} --add-assignee "@me"
    

    目的:issue 側の assignee は PR エンティティに自動継承されないため、PR の Assignees フィールドに実行中の認証 actor を明示し「この PR は AI が owner」という UI 上の trail を残す。 メカニズム注記:GitHub は --add-reviewer の自己指定を silent に拒否するが、--add-assignee による PR author 自身の assignee 追加は許可される(2026-04-20 に PR #1099 で empirical 検証済)。 スコープ:assignee self-assign は UI trail のためであり、正式な self-review 記録(rules/operations/main-agent-procedures.md の ## Self-review formal record、「PR レビュー」節にも日本語での記述がある)を置き換えるものではない。

  2. CI ループへ即座に移行する。人間の指示は不要。

  3. マージの実行者は全モードで AI に統一されている(「マージ」節参照)。GitHub の auto-merge 機能への一般的な委譲は廃止されているが、trigger モードでは例外として PR 作成時点で --auto --squash を有効化する(下記「モード別の PR auto-merge ポリシー」参照)。

モード別の PR auto-merge ポリシー

(→ rules/operations/operations.md の PR auto-merge policy is mode-specific)

PR 作成時の gh pr merge --auto --squash 付与は実行モードで振る舞いが異なる。一律ではない。

モード auto-merge 付与 根拠
trigger PR 作成時点で gh pr merge {pr} --auto --squash を必須で有効化する 承認 gate は人間レビューが担う。auto-merge は承認が入った瞬間に自動でマージするだけで、毎回「merge strategy どれ?」と確認する往復を省く
semi_auto minor / major PR には --auto を付けない(人間レビューが gate)。patch PR はセルフレビュー pass → AI が直接 merge(auto-merge 不要) minor / major は人間レビュー必須のため、auto-merge で承認即マージしても意味がない。patch は即マージで十分
auto repo 設定の "Allow auto-merge" を意図的に無効化する。gh pr merge --auto が enablePullRequestAutoMerge 権限不足で蹴られるのは設計通り repo-level auto-merge が有効だと CI pass 時点で GitHub が自動マージし、parent AI のセルフレビューを飛ばす抜け道になる。Parent AI がセルフレビュー後に手動 gh pr merge {pr} --squash を実行する

auto モードで --auto --squash が拒否された場合、それは設定漏れではなく意図された状態である。「auto-merge を有効化することを提案」してはならない。Li+config.md の対象リポジトリの _EXE_MODE(例: USER_REPO1_EXE_MODE / LI_PLUS_REPO_EXE_MODE)を確認してからモード分岐する。

subagent に PR 作成を delegate する場合、parent は delegation prompt 内に mode 判定結果と auto-merge 指示を literal で注入する(subagent は parent の memory を読まない)。

CI ループ

(→ skills/operations-on-ci/SKILL.md)

CI ループは PR 作成とは独立したタスクである。PR 作成後または修正リコミット後に開始する。

step 1: 最新コミット SHA 取得

gh pr view {pr} -R {owner}/{repo} --json headRefOid --jq '.headRefOid'

step 2: 全チェックランの完了を待機

webhook 経由を優先する。

mcp__github-webhook-mcp が利用可能な場合:

  • get_pending_status を60秒間隔でポーリング
  • check_run または workflow_run の pending があれば list_pending_events → get_event で SHA 一致を確認(workflow_run は head_sha で照合)→ mark_processed
  • 全チェックランと workflow run が完了するまで収集

利用不可の場合:

gh api repos/{owner}/{repo}/commits/{sha}/check-runs --jq '.check_runs[] | {name,status,conclusion}'

全ての status=="completed" になるまで sleep で繰り返す。

step 3: 結論判定

  • CI FAIL = いずれかの conclusion=="failure"
  • CI PASS = 全て conclusion が success / skipped / neutral

CI PASS → PR レビューへ移行。 CI FAIL → 修正してリコミット(CI ループを step 1 から再開)。ループ安全閾値(3回)を超えた場合は issue コメントに外部化し、人間に委ねる。

PR レビュー

(→ 正本は rules/operations/main-agent-procedures.md の ## PR review。実行主体が auto / semi_auto では親、trigger ではサブエージェントというモード依存であり、skills/operations-on-actor-placement/SKILL.md の Maintenance rule が名指す検出サインそのものにあたる。判断基準は skills/task-pr-review-judgment/SKILL.md(L3)、停止条件は skills/operations-on-pr-review/SKILL.md)

AI セルフレビューは全モード(trigger / semi_auto / auto)で必ず実行する。 マージ前のセルフレビュー省略は仕様違反である。セルフレビューが先に走り、必要に応じて人間レビューがその上に重ねられる(置き換えではない)。

レビューの基準は repository state first である。issue 本文、リンク済みブランチの差分、PR 本文、CI 結果を読む。ローカルで動いたことだけではレビュー完了にしない。

セルフレビュー手順(全モード共通)

実行主体は auto / semi_auto では親、trigger ではサブエージェント(skills/task-subagent-delegation/SKILL.md のルール)。前二者ではそれはマージするエージェント自身である。trigger ではマージするエージェントが居ない(「マージ」節参照)ため、実行主体は反対側から固定される——サブエージェントのセルフレビューは自身の停止点より手前に入り、その後に PR 上に立つものは無い。

その主体が PR diff を issue 要件と照合してレビューする(判断基準は L3 の skills/task-pr-review-judgment/SKILL.md)。

  • セルフレビュー pass → formal review record 投稿(下記)→ モード別の人間ゲートへ。
  • セルフレビュー fail → 修正してリコミット(CI ループ再開)。

委譲されたサブエージェントの停止条件(モードで割る)

(→ skills/operations-on-pr-review/SKILL.md の Delegated-subagent stop condition。この literal の実行主体はサブエージェントであり、親は委任時の運搬役にすぎないため、正本は skill 側に残る)

auto / semi_auto:PR open + CI green で停止する。サブエージェントはセルフレビューを実行も投稿もせず、そこで報告して終える。

この停止点には2回以上到達し、上の文言がそのすべての停止条件である。

  • 1回目 = issue の変更を実装し終えた時点。以降、親は rules/evolution/initiator-autonomy.md Merge brake の定める位置で brake 1 を走らせる(PR が L1 Model Layer ソースに触れる場合も同じ 1 本)。
  • 2回目 = brake のあるラウンドの評価者コメントが PR に載った状態でこのサブエージェントを再開し、それが指摘を裁き、受入 / 却下とその理由を同じスレッドへのコメントとして投稿し、受け入れた分をプッシュした時点。再び CI green に到達したところでこのパスが終わる。何も受け入れなかった場合は新しいコミットなしで同じ点に到達するが、裁定コメントは同じく投稿される。
  • 3回目以降 = 親が次のラウンドを開いた各ラウンドの末尾。往復に上限は無く、ラウンドをどこで終えるかは skills/evolution-parallel-agent-eval/SKILL.md Procedure の step 8(Round boundary)が持つ。親は内容を監督せず、ラウンドの開閉と、同じ指摘の再発を人間へ上げることだけを行う。

指摘の裁定は停止と停止のあいだで起き、再開したサブエージェントのものであって親のものではない(rules/evolution/initiator-autonomy.md Merge brake の Adjudication actor)。親は最後の停止の後にセルフレビューしてマージする。brake の位置そのものはここに再掲しない(日本語側の解説は進化レイヤー仕様書「実行モード」節にある)。

trigger:PR open + auto-merge enabled + CI green + self-review posted + awaiting human review で停止する。セルフレビューは全モードで人間ゲートに先行し、このモードではその実行主体がサブエージェント自身であるため、停止点より手前に入る。マージは人間の承認後に GitHub auto-merge が発火するので、サブエージェントのセッションはその前に終わる。

停止条件の正本は上記の skill 側であり、他の面もそこを指している。周囲のフロー(セルフレビュー必須・レビュー基準・手順・モード別人間ゲート・持ち越し項目の follow-through)の正本は常駐面にある。本節はその日本語での要求記述であって二つ目の正本ではない(本書冒頭のとおり、差異があれば英語のソース側が正)。

セルフレビューの formal record 投稿(全モード、必須)

(→ 正本は rules/operations/main-agent-procedures.md の ## Self-review formal record。実行主体は auto / semi_auto では親であり、親は operations 系 skill を読まないため、正本は常駐面に置かれている。#1764 で周囲のセルフレビューフロー自体も同じ常駐面へ移り、両者は隣接する)

内部のセルフレビューが pass した後、AI は結果を GitHub 上の正式な PR review として必ず投稿する:

gh pr review {pr} -R {owner}/{repo} --comment --body "<セルフレビュー結果の要約>"

目的は PR の Reviews タブに audit trail を残し、AI レビュー記録を PR 作者属性から分離すること。 実装メカニズムの注記:GitHub は --add-reviewer による self-assignment を silent に拒否する。PR author が自己レビュー記録を残す唯一の手段は gh pr review --comment(2026-04-20 に PR #1095 で empirical 検証済)。 body には以下を含める:受け入れ条件の照合結果、scope deviation(ある場合)、workspace 側の deferred 項目(ある場合。「マージ」の Post-merge moment はここから読む)、次ステップ想定(例:trigger / semi_auto の minor-major では「人間レビュー待ち」)。

モード別の人間ゲート(セルフレビュー pass 後)

execution_mode == auto:人間ゲートなし。セルフレビュー pass → マージへ移行。

execution_mode == semi_auto:タイプ連動の人間ゲート。

  • patch → 人間ゲートなし。セルフレビュー pass → マージへ移行。
  • minor / major → セルフレビュー pass 後に人間確認が必要(手順は下記「承認待ちの確認手順」)。

バージョン種別の判断軸はリリース時と同じ(「バージョン種別」節参照)。AI は PR 作成時点でタイプを提案し、判断が曖昧な場合は安全側(minor)に寄せて人間に確認する。

Per-PR exception(content-based axis) は rules/operations/execution-mode.md の semi_auto mode: が正本である。人間ゲートを waive する前にそちらを読むこと。ここには再掲しない——過去に写しを置いた結果、後から正本にだけ入った修正が写しに届かず、waive の読みがマージゲートの面で正本より広いまま残った。二つ目のコピーが drift する。

execution_mode == trigger:全 PR で人間確認が必要。セルフレビュー pass 後に下記「承認待ちの確認手順」を実施する。

承認待ちの確認手順(Review approval check)

(→ 正本は skills/task-pr-review-judgment/SKILL.md の ## Review approval check(#2138 で常駐面から移した。上記「メインエージェントの手続き」の #2138 の項)。この待ちに立つ実行主体は、ゲートを持つどのモードでも親である —— semi_auto ではゲートそのものが親のもの(skills/task-subagent-delegation/SKILL.md Rules の Parent retains: ... review judgment、および「実行モード」の Mode matrix が人間チェックを minor / major に置く)であり、trigger では委譲サブエージェントが awaiting human review で既に停止している(#1715 で確定)ため承認はそのセッションが終わった後に来る。どのモードでもここにサブエージェントは立たないので、メインの読める面に置いた正本ひとつで両方を賄える。親は operations 系 skill を読まないため、正本はメインの読める面にある(#1714 では常駐面、#2138 以降は task-* skill)。#1708 が名指しした3経路と同一クラスの4件目であり、検出サインが先行ではなく自分で捕まえた最初の1件(#1714))

semi_auto の minor / major と trigger の全 PR で、セルフレビュー pass の後に走る。auto は人間ゲートを持たないためここには到達しない。

webhook 経由を優先する。

mcp__github-webhook-mcp が利用可能な場合:

  • get_pending_status を60秒間隔でポーリング
  • pull_request_review の pending があれば list_pending_events → get_event で当該 PR を確認 → mark_processed

利用不可の場合:

  • 人間がレビュー完了を通知するまで待機(ポーリングしない)
  • 通知を受けたら確認:
gh pr view {pr} -R {owner}/{repo} --json reviewDecision --jq '.reviewDecision'

ここで読むのはレビュー判断の入力であって判断そのものではない。APPROVED と CHANGES_REQUESTED が何を解放するかは L3 の skills/task-pr-review-judgment/SKILL.md が正本である(タスクレイヤー仕様書「PR レビュー判断」節)。APPROVED の先のマージ経路はモード別で「マージ」節にある。

deferred 項目の follow-through

セルフレビュー記録は項目を「PR scope 外」として正当に deferred 化することがある(例:workspace memory のクリーンアップ、フォローアップ issue 起票、docs-only フォローアップ)。deferred は ignore と同義ではない:

  • workspace 側の deferral(memory 編集、ローカル設定変更)は、どのモードでもメインエージェントが、マージ後の瞬間(下記「マージ」の Post-merge moment)に実行する。その瞬間より後へ先送りしない
  • repo 側の deferral(フォローアップ issue、関係ない掃除の別 PR)は merge 前に file しておく。merge してから後追いで作ると流れる
  • 人間の APPROVED コメントに「〜したんだよね?」「did you also do X?」のような確認文が埋め込まれている場合、それは承認条件の一部であり small talk ではない。追加 gate として扱い、同一セッション内で応答する

merge は閉じ括弧ではない。deferred 項目の handoff まで完了して初めて閉じる。

マージ

(→ rules/operations/main-agent-procedures.md の ## Merge Execution。#1708 以前は skills/operations-on-merge/SKILL.md が正本だったが、その skill が発火すべき瞬間に、居合わせていて かつ 読むことを許された読者が一人もいなかった。auto / semi_auto でそこに立つのは親であり、親は operations 系 skill を読まない。trigger ではゲートが開くのは委譲サブエージェントのセッションが終わった後であり(skills/operations-on-pr-review/SKILL.md Delegated-subagent stop condition)、invoke する主体がそもそも居ない。ポインタ化ではなく削除して常駐面へ移した。trigger の merge 実行主体がどちらであるかを確定させる必要はない——そこに立つのがどのエージェントであれ、rules/** は invoke を要さずロードされるため、置き換えた skill より到達性は高い。その後 #1715 がこの問いを確定させた——マージは GitHub への handoff であり、そこに立つエージェントは居ない(下記「マージ」)。削除の根拠はそれに影響されず、それが「確定に依存しない」ということである)

マージの実行者は全モード(trigger / semi_auto / auto)で AI に統一されている。 ただしこれは actor 軸の話であり、その「AI の行為」が何であるかはモードで異なる。行為を actor から読み取ったことが #1715 まで続いたソースの割れであり、trigger で誰がマージするかの読みで4面が2対2に割れていた。

  • semi_auto / auto = 直接マージ。すべての前提条件(セルフレビュー、モード別の人間ゲート、下記のマージ可能状態チェック)が揃った時点で、AI が gh pr merge(--auto なし)を実行する。
  • trigger = handoff。AI の行為は PR 作成時点で GitHub auto-merge(gh pr merge --auto)を有効化することであり、マージ自体は人間の承認を受けて GitHub が発火させる。承認の瞬間にマージコマンドを実行する主体は居ないし、そこに立っている主体もそもそも居ない(「委譲されたサブエージェントの停止条件」節参照)。

モード分岐の authoritative は operations.md PR auto-merge policy。

マージ前のマージ可能状態確認(直接マージ経路のみ)

trigger では auto-merge を armed のまま GitHub がマージ可能になるのを待つ状態で PR が置かれ、確認に立つ主体が居ないため、この節は直接マージ経路の手続きである。

gh pr view {pr} -R {owner}/{repo} --json mergeStateStatus --jq '.mergeStateStatus'
  • CLEAN → そのままマージへ進む。
  • BEHIND → gh pr update-branch {pr} -R {owner}/{repo} で解消し、CI ループを step 1 から再開。
  • CONFLICTING → 非破壊的な取り込み gh pr update-branch {pr} -R {owner}/{repo} を試行。成功なら CI ループを step 1 から再開。マージ競合で失敗した場合は issue コメント → 人間にエスカレーション。rebase + force push にフォールバックしない。force push は無条件の human 判断ゲート項目(後述の「人間確認が必要な操作」)であり、AI 側で進められる経路が残らない。
  • BLOCKED / UNKNOWN → 待機して再確認(GitHub が計算中の可能性)。

マージ戦略(全モード共通)

既定のマージ戦略は squash(リポジトリの慣例に従う)。直接マージ経路では AI が以下を実行する。

gh pr merge {pr} -R {owner}/{repo} --squash

trigger の handoff 経路では、同じ戦略が PR 作成時点の --auto --squash 有効化で固定される。

AI が squash 以外を選ぶ必要があると判断した場合のみ人間に確認する(pause して確認)。

PR 本文に Closes #xxx が含まれていると、マージ時にプラットフォームが issue を自動クローズする(Refs はクローズキーワードではないため自動クローズしない)。

マージ後の瞬間(Post-merge moment)

マージ直後に置かれた義務 —— 下記の issue reopen、L1 マージ後のランタイム観測、「PR レビュー」の deferred 項目の follow-through のうち workspace 側の deferral、自己進化 PR の observation エントリの自動記入(skills/evolution-observation-entry/SKILL.md の Auto-entry trigger) —— が発火する瞬間を、モードごとに1つに定める。実行主体はどのモードでもメインエージェントである。

  • auto / semi_auto = 親自身のマージの直後、マージしたセッションの中。
  • trigger = マージの瞬間に立つエージェントが居ないため、メインエージェントがマージを最初に観測したターンをその瞬間とする。そのターンがどのセッションに来てもよい。観測の経路は、承認待ちの確認手順、フォアグラウンド webhook 取込の項目、その他 PR がマージ済みであることを示す読み取りのいずれか。義務はそのターンで実行する。

trigger では、そのセッションが PR を委任したセッションと同じとは限らない。そのため各義務は委任時の文脈からではなく、残る面から読む —— reopen はクローズされた issue の本文から、L1 観測は PR の変更ファイルから、workspace 側の deferral はセルフレビューの formal record から、observation エントリは PR にリンクされた issue と変更ファイルから。

#1642 以前、この瞬間は trigger の issue reopen にだけ定められていた。L1 マージ後の観測と workspace 側の deferral は「マージの瞬間」「マージ直後の同一セッション」を起点に書かれており、trigger ではその瞬間にセッションが存在しないため発火経路が無かった。委譲サブエージェントのセッションをマージまで引き延ばす解は、人間のレビュー待ちを無期限のセッション保持に変えるため採らず、reopen が既に使っていた「最初に観測したターン」を3つの義務の共通アンカーに広げた。#2089 で、同じ穴を持っていた observation エントリの自動記入を4つ目の義務としてこの瞬間に加えた。それまでの記入主体は「親 AI またはマージサブエージェント」と書かれていたが、マージサブエージェントは現行の構成に存在せず、trigger ではマージの瞬間に親も立たない。

クローズされた issue の本文に PR 単体では満たせない完了条件(rules/operations/main-agent-procedures.md の ## Issue format)があり、その条件が未達のときは、マージ後の瞬間に issue を reopen し、条件が満たされるまで開いたままにする。

実機テストはマージ後に main 上で行う。マージゲートにはしない。

人間確認が必要な操作

(→ 正本は rules/operations/main-agent-procedures.md の ## Human confirmation required。いずれも人間に問う確認であり、サブエージェントは問う面を持たない。skills/operations-on-release/SKILL.md はポインタを持つ)

「待って」「止めて」「まって」と言われたら即座に停止する。

確認が必要な操作:

  • リリース作成(バージョン種別とターゲットタグ)— 実行前に CD チェックが必要
  • ブランチ削除(リンクされた issue がクローズされる可能性がある場合)
  • force push
  • trigger mode のみ:issue 選択、issue 実行開始

リリースチェック

(→ skills/operations-on-release/SKILL.md の ## Release checks (pre-create))

リリース作成前に以下を確認する。

CD チェック: CD PASS なら次へ。CD FAIL なら人間にエスカレートし、リリースは作成しない。

mcp__github-webhook-mcp が利用可能な場合:

  • get_pending_status を60秒間隔でポーリング
  • workflow_run の pending があれば list_pending_events → get_event で conclusion を確認 → mark_processed

利用不可の場合:

  • gh api で全 CD チェックが完了するまでポーリングする。

バージョン種別

(→ rules/operations/release-version-rule.md 権威ソース(判定基準、always-on rules 層に移設 #1484)。Version Base Rule は skills/operations-on-release/SKILL.md。本節はその日本語ミラー)

v0.x.x は初期開発版。何でも変わりうる。v1.0.0 以降が正式版(semver 準拠)。

判断軸は「変更の規模」と「user/system から観測できるか」の2つ。

バージョン 適用条件 判断者
patch それ以外すべて(docs / 小 fix / 小 spec / config / 内部ルール変更 / user/system から観測できない governance 構造変更) AI が提案
minor 大きな refactor または大きな構造変更であり、かつ user/system から観測できる AI が提案、人間が承認
major 大規模変更または大きな目標達成(フェーズ移行、プロジェクト節目) 人間が判断

重要な注記: 「構造変更 → minor」ではない。「構造変更かつ user/system observable → minor」。governance や spec rule の変更は、構造的には大きくても観測できなければ patch で扱う。本 issue (#1087) 自身がその典型で、release rule の再設計は governance 構造の変更だが Li+ ユーザーの surface から見えないため patch で ship する。

AI は patch または minor を提案する。minor / major の採用は人間が確認し、AI が実行する。バージョン番号はプレリリースを含む直近のリリースを基準にする。

Application-moment trigger(判断形成の瞬間で発動): バージョン分類(patch / minor / major)を任意の artifact に書く直前に、本 rule(rules/operations/release-version-rule.md)を literal 再読する。再発失敗は minor の "large" 修飾子省略 — observable な変更を minor と誤分類するが scope は incremental(つまり patch)というケース。詳細は skills/model-trigger-check-gate-actions/SKILL.md の Trigger moments を参照。

リリース術語の解釈優先順位

(→ rules/operations/operations.md の Release terminology interpretation ladder)

「プレリリースタグ」「stable タグ」等の人間発話は、GitHub Release の prerelease フラグ(boolean 属性) を指すものとして第一解釈する。git tag オブジェクトや release entry そのものの削除を指すとは解釈しない。

「〜を削除で」「〜外して」等の曖昧な発話は、release 属性変更 vs release 削除 vs git tag 削除で挙動が全く異なる。より保存的な解釈を先に試し、literal delete は最後に置く。

順位 解釈 例
1 属性・フラグ変更(最も保存的) prerelease → stable 昇格、draft → published、latest flip
2 可視性変更 archive、hide、unlist
3 新 release で置換 supersede、後継 release で deprecate
4 明示確認(停止して人間に問う) 上記で解釈不能な場合、destructive 操作の前に確認
5 文字通りの削除 人間が明示的に「削除」「消す」「unpublish」「tag 削除」と言った場合のみ

「削除」指示に対して step 4(明示確認)で必ず停止する対象成果物: GitHub Release、git tag、npm / PyPI / crates.io のバージョン、merge 済み PR(close は削除ではない)、main ブランチ(revert は削除ではない)、公開済み docs、公開済み wiki。これらは公開済みかつ不可逆性の高い成果物であり、確認前の literal delete は禁止する。

復元手順(git tag を誤って削除した場合の参考):

git for-each-ref refs/tags/...                       # ローカル保持 SHA 確認
git push origin refs/tags/{tag}                      # tag 復元
gh release create {tag} --generate-notes --latest=false  # release 復元

リリース state ルール(バージョン種別とは独立した軸)

(→ skills/operations-on-release-state/SKILL.md の # Release State Rule 節)

state は version type(patch / minor / major)に依存しない独立 axis として扱う。

state 既定値と意味 操作者
default(state フラグなし) gh release create の既定。prerelease=false、latest=false。version type に関係なく AI はこの default で出す AI
prerelease AI が明示的にテスト期間を取りたい時のみ付与する裁量フラグ。タグ名は最終形のまま(alpha.N / rc.N / -pre などの suffix は付けない)。昇格時はフラグを外すだけでタグは作り直さない AI
latest 実機検証済みを示す。version type(patch / minor / major)に関係なく実機テストが gate。gh release edit {tag} --latest=true で flip 人間のみ(判断主体)

判断 ↔ 実行軸:上表の「人間のみ」は判断主体を指す。CLI(gh release edit ... --latest=true)を打つのは AI で、human が明示的な go-sign を出してから AI が実行する。詳細は本ドキュメント「human 判断ゲート」節を参照。

AI の canonical release 作成コマンド

AI が release を作成する際は、以下の形を canonical とする。

gh release create {tag} \
  --target main \
  --title {version} \
  --generate-notes \
  --latest=false

--latest=false は明示必須。省略すると gh CLI の default は legacy(semver + date の auto-pick)に fallback し、新 release が Latest に昇格してしまい、既存の Latest anchor を黙って降格させる。

Latest anchor 要件

repo には常に1つ以上、explicit Latest な release(make_latest=true)が存在している必要がある。この release を Latest anchor と呼ぶ。

anchor が不在の状態で新 release に --latest=false を渡しても、legacy default に巻き込まれて無効化され、新 release が Latest 化してしまう。anchor は「各 release の属性」ではなく「repo 全体の persistent な state」として扱う。

Anchor flip 手順(人間、実機検証後)
gh release edit {new_tag} --repo {owner}/{repo} --latest=true

GitHub の one-Latest-only 制約により、旧 anchor は自動で Latest badge を失い、default(state なし)に遷移する。新 release が Latest anchor に昇格する。タグ名は flip 前後で不変で、state のみが移動する。

Bootstrap / transient state

repo の初回非 prerelease release、または anchor 消失時は、GitHub が legacy auto-pick によって一時的に最新 release を Latest 化する。この transient Latest state は、人間が explicit Latest anchor を設定した時点で one-Latest-only 制約によって自然に解消される。

この transient Latest は AI が意図的に付けた state ではなく、プラットフォーム側の default 挙動であり、governance 上の判断ではない。

一括 state 正常化

既存の複数 release を一括で default(state なし)に正常化する場合、先に1つを anchor(--latest=true)に固定してから、他を --latest=false で PATCH する。順序を逆にすると anchor 不在の状態で --latest=false が無効化され、ターゲットのいずれかが再び Latest 化してしまう。

リリースルール

  • リリースタグ・タイトルはプロジェクト固有の規約に従う
  • リリース body は GitHub generated release notes を使う(--generate-notes を渡す。--notes "" で空 body を渡さない)

バージョン番号はプレリリースを含む直近のリリースを基準にする(latest stable のみではない)。

gh release list --limit 1  # プレリリースを含む

リリースタグ・タイトル規約

(→ skills/operations-on-release/SKILL.md の # Release Tag and Title Rule 節)

プロジェクトの docs/ または CI/CD 設定を確認してから作成する。

プロジェクト種別 タグ形式 タイトル形式
Li+ language(デフォルト) build-YYYY-MM-DD.N {version}(例: v1.9.0)
npm パッケージ v{semver} v{semver}

CD workflow がタグを作成するプロジェクトでは、既存の CD 作成タグを使い、新規タグを作らない。npm version を使うプロジェクトでは、npm version コマンドがタグを作成する。

リリース後の Wiki 同期

(→ skills/operations-on-wiki-sync/SKILL.md)

リリース公開後、docs/ を GitHub Wiki にミラーする。同期はリリースフロー完了の gate であり、省略は禁止。

所有境界

  • docs/ 所有 = docs/ 直下のすべての *.md。配置場所が決め、ファイル名は参照しない。docs/ が正本で、同期後は Wiki 側と byte 単位で一致する。docs/D.-Installation.md は docs/4.-Operations.md と同様に docs/ 所有である。docs/Decision-Structure.md は index する entry がすべて Wiki 専属であっても docs/ 所有側に置く。adapter/claude/hooks/on-session-start.sh が cold-start 素材として docs/ 側を読むため、Wiki 側に寄せて docs/ 側を畳むことはできない。直下のみ — Wiki の名前空間はフラットであり、入れ子の docs/**/x.md は Wiki 側に counterpart を持たず、ページとしてミラーされることはない。同期が読む入れ子のファイルは下記のサイドバー先頭部の source 1 つだけであり、それもページとしてではなく _Sidebar.md の一部として読む
  • Wiki 専属 = 明示リストであり、以下で閉じる。同名の counterpart を docs/ に持たない。同期はこれらを delete せず、下記の _Sidebar.md 先頭部を除いて copy もしない
    • _Sidebar.md。**判断構造** 行で二分する。その行からファイル末尾までが判断構造節であり、Wiki オーサリングで同期は書かない。skills/evolution-decision-structure-write/SKILL.md が entry の slug を足すのはこの節である。その行より上がナビの先頭部で、source は source ref 上の docs/wiki/_Sidebar-head.md。手順 4 がこれから先頭部を組み直し、手順 5 が結果を書き込む。これは docs/ 所有ページと同じ source からの copy であって修復ではない。docs/ 直下のページを追加・rename・削除する PR は同じ PR でこのファイルを更新し、更新しない PR は tests/test_wiki_sidebar_head.py が落とす。source を 1 階層下げて置くのは、配置場所がそのまま所有を決めてしまうため。docs/_Sidebar.md として直下に置けば docs/ 所有になり、判断構造節ごと丸ごとミラーで上書きする。source ref にこのファイルが無いリポジトリでは、_Sidebar.md 全体が Wiki オーサリングのまま。リストに載るナビはこれだけである。Home.md と _Footer.md は docs/ にあるため、配置場所によってすでに docs/ 所有になっている。どちら側にも属さない Wiki ナビは unclassified として人間に上がり、その escalation がこのリストの増やし方である(リポジトリごとの慣習ではなく skills/operations-on-wiki-sync/SKILL.md の変更として行う)
    • docs/Decision-Structure.md が index する判断構造 entry すべて。本文は Decision_Structure_Write_Autonomy のもとで Wiki 側に直接書かれるため、これらについては Wiki が source である(docs/ 正本原則に対するこの例外は rules/operations/operations.md が規定する)。entry は順序 prefix を持たないので、順序はファイル名ではなく当該 index と _Sidebar.md で明示する
  • それ以外の Wiki ページは unclassified である(Wiki に存在し、docs/ に無く、上記リストにも無い)。削除候補ではない。該当ページを名指しして STOP しエスカレートする(手順 4)。所有は Wiki 側からは観測できない — unclassified なページは、docs/ 側 rename の残骸(削除が正しい)か、リストが追いついていない Wiki 正本ページ(削除は正本の破壊)かのどちらかである。後者の再発形は、index 行が merge される前に Wiki へ push された判断構造 entry である。skills/evolution-decision-structure-write/SKILL.md は手順 5 で entry を Wiki へ直接 push し、docs/Decision-Structure.md の更新は手順 6 で main repo の PR flow に載せるため、この窓は異常状態ではなく通常運用である。二つの誤りのうち一方はこちら側から回復できないため、上記の所有境界の拡張は削除を決める権限を持たない。どちらであるかは人間が名指しする

所有の軸と削除の軸は別軸であり、本節が動かすのは前者だけである。どちらが source かは配置場所と明示リストで決まり、孤児を削除するかは human judgment gate に留まる(rules/operations/execution-mode.md human judgment gate — 人間が判断し、AI が実行する)。拡張された所有規則を拡張された削除規則として読むことが、Wiki 正本 entry を消す経路である

push 前検証

以下 4 つのアサーションは手順 5 の後、手順 6/7 のコミット前に実行する。いずれも失敗時は該当ファイルを名指しで人間にエスカレートして STOP し、push しない。この層で Wiki を修復もしない。sidebar drift も、実体の無い索引行も、broken cross-reference も、いずれも先行 PR が自分の変更したものを保守しなかったということであり、release sync は再帰チェックポイントであって修復層ではない。

  • git -C {tmpdir} status --short の D / M が docs/ に存在する名前のみであることを確認する。 それ以外の名前に D / M が出ていれば、手順 5 のファイル集合が所有境界から逸脱している。この逸脱が本手順の再発する故障モード。例外は 2 つ。手順 4 で人間が削除を承認したページは D が出るのが期待動作であり、手順 4 が先頭部を組み直した場合の _Sidebar.md には M が出る。後者のときは git -C {tmpdir} diff -- _Sidebar.md で **判断構造** 行以降の行が 1 行も変わっていないことを確認する

  • Sidebar 整合性:{tmpdir}/_Sidebar.md が navigable entry を網羅参照しているか検証する。 期待 slug 集合は docs/ ローカルでも index 文書でもなく {tmpdir} ファイルシステムから構築する(両所有系統が Wiki 上に存在する形で数えるため):{tmpdir}/*.md のすべて(slug は拡張子を除いたファイル名)。この 1 つの glob が docs/ 所有ファイルと Wiki 専属 entry の双方に届き、どちらであるかを問わない

    期待集合から除外:_Sidebar.md、_Footer.md(ナビ基盤であって被参照 entry ではない)。下記アルゴリズムで {tmpdir}/_Sidebar.md からコード記法を除去する。コード除去後の本文から、Markdown inline link の ](<slug>) target と GitHub Wiki native link の [[target]] / [[label|target]] target の和集合を参照 slug 集合として抽出する。label 付き native link は | の右側を target とし、各抽出 target の #section fragment は resolution 前に除去する。期待 − 参照 が空でなければ STOP。

    手順 4 が組み直した先頭部は source そのものの内容であるため、source の先頭部にページが欠けていればここで従来どおり落ちる。組み直しはこのアサーションの代わりにならない。それをリリースまで到達させないのは、ページを追加した PR 上の tests/test_wiki_sidebar_head.py である

  • 索引整合性:docs/Decision-Structure.md が名指す判断構造 entry がすべて Wiki に実在するか検証する。 index は source ref から読み(git show origin/main:docs/Decision-Structure.md)、下記アルゴリズムでコード記法を除去したうえで、その wiki link target から期待 slug 集合を構築する。抽出は手順 4 が Wiki 専属リストを組むのに使うものと同じ。期待 slug のいずれかに対応する {tmpdir}/<slug>.md が無ければ STOP。

    下の Cross-reference 整合性はここに届かない。index は target を絶対 URL(https://{host}/{owner}/{repo}/wiki/<slug>)で書き、当該アサーションは :// を含む target をすべて除外するため、push されなかった slug を名指す索引行も、Wiki 側 rename が置き去りにした索引行も、どこにも解決せず誰も読まない。

    逆向き(index が名指していない Wiki entry)はここでアサートしない。手順 4 は同じ index から Wiki 専属リストを組むため、その entry はすでに手順 4 の unclassified 集合に入っており、本アサーションに到達する前に走行は停止している。ここに二枚目の検出器を置かない。手順 4 が代わりに持つのは修復の向きであり、それは同手順に書く。

    どちらの向きも、判断構造 entry と要求仕様書・参考文書をファイル名規則で見分ける必要はない。こちらの期待集合は index 自身の target であり、手順 4 の所有は配置場所(source ref 上の docs/<name> counterpart の有無)と Wiki 専属リストで決まる。1.-Model.md / A.-Concept.md / Home.md / _Footer.md / DiDD.md / Decision-Structure.md を docs/ 所有側に置いているのはこの 2 つであり、どれ 1 つも名前で挙げていない。ファイル名のパターン(先頭が数字、先頭が英字+ドット)を足すことは、既存の 2 つと並ぶ 3 つ目の所有系統を作ることであり、2 つですべてのページが決まっている

  • Cross-reference 整合性:{tmpdir}/*.md 内のすべての Wiki 内部リンクが実在 entry を指すか検証する。 解決集合を構築する:

    • 実在 target = {tmpdir}/*.md の各実在ファイルについて、拡張子なし slug と .md 付き完全ファイル名の両方(Home と Home.md を含む)。.md 付き target は、この列挙で対応する Markdown ファイルが実在する場合だけ解決集合へ入る。所有ごとの集合ではなく 1 つの glob で列挙するのは、このアサーションが問うのは target が実在ファイルに解決するかどうかだけであり、それは所有に依存しないため
    • 抽出 target = コード除去後の本文中の ](<x>) 出現のうち、<x> が :// を含まず、# で始まらず、/ を含まないもの。#section フラグメントがあれば剥がしてから resolution する。.md は一律に剥がさず、抽出表記のまま解決集合と照合する

    抽出 target に解決集合外のものが 1 件でもあれば STOP。両表記が有効なのは、これらの本文がリポジトリ docs/ にも mirror され、そちら側では .md 付きだけが解決するため(#1608)。

コード記法の除去(リンクを読む 3 アサーション共通)

コード内、または HTML コメント内のリンク風記法は、記法そのものの説明か描画されない markup であり、実リンクではない。この除去を飛ばすのは稀な取りこぼしのリスクではなく、全リリースで確実に偽陽性 STOP を出す。アサーションの仕様文自体(本ファイル、skills/operations-on-wiki-sync/SKILL.md、wiki entry wiki-sync-sidebar-integrity-check)がその記法でパターンを説明しているため。次の順序で除去し、各パスは本文全体に適用してから次のパスに進む:HTML コメント、次に HTML 要素、次にフェンスドコードブロック、次にインデントコードブロック、最後にインラインコードスパン。

  • HTML コメント:<!-- で開始し、次に現れる --> で閉じる。閉じる --> が無ければ、コメントはファイル末尾まで及ぶ
  • HTML 要素:<pre>...</pre>(block-level)または <code>...</code>(inline-level)。閉じタグとの対応は大文字小文字を区別せずに判定する。開始タグに対応する閉じタグが無ければ、要素はファイル末尾まで及ぶ
  • フェンスドコードブロック:開始行はバッククォート 3 個以上、またはチルダ 3 個以上の run のみで構成される行(同じ行に info string が続くのは許容)。ブロックは、同様に同じ文字の run のみで構成され長さが開始側以上である次の行まで及ぶ。該当する行が無ければ、フェンスはファイル末尾まで及ぶ
  • インデントコードブロック:4 スペースまたはタブでインデントされた行が連続する最大の範囲。インデントされていない最初の行の手前で終わる
  • インラインコードスパン:バッククォート N 個の run を、次に現れるちょうど N 個の run で閉じた範囲。ちょうど N 個で閉じる run が無ければ、開始側の run はコードスパンとみなさず literal text として残す

この順序は二つの軸で load-bearing である。HTML コメントをインデント判定より先に除去するのは、コメント除去が行の先頭空白を変化させ、その行がインデントコードブロックに該当するかどうかを左右しうるため。すべての囲い込み形式をインラインコードスパンより先に除去するのは、フェンスやタグ自身のバッククォート run がインラインスパンの区切りと誤認され、無関係なテキストを飲み込むのを防ぐため。

新規 repo セットアップ(初回 sync 前のワンショット)

  • 初期 docs/ に Home.md、_Footer.md、当該リポジトリの要件仕様・リファレンス文書を配置する。docs/Decision-Structure.md も含める。ファイル名の形は自由であり、docs/ 直下に置くことが docs/ 所有にする条件である
  • _Sidebar.md は wiki repo 側に直接 push する。これを作成する同期手順は無い。判断構造節の見出しとして **判断構造** 行を置き、ナビの先頭部は docs/wiki/_Sidebar-head.md に置いて以後の同期が source から copy するようにする。このファイルが無ければサイドバー全体が Wiki オーサリングのまま
  • 判断構造 entry(<topic>.md、小文字 kebab-case、順序 prefix なし)は作成時点から Wiki 側に作る。docs/ に置くと docs/ 所有のミラー対象ファイルになってしまう

手順

source 側は呼び出し元の作業ツリーではなく ref で名指す。以下の docs/ 読み取りはすべて origin/main を経由する(git show origin/main:docs/<name> / git ls-tree origin/main docs/)。origin/main から遅れたクローン —— 古いチェックアウト、tag ベースの Li+ 同期が残す detached HEAD —— は通常運用で到達する状態であり、そこからミラーすると merge 済みの docs/ 変更が Wiki 上で静かに巻き戻る。しかも push 前検証の 3 アサーションはいずれも通ってしまう(測っているのは所有と参照解決であって source の鮮度ではない)。ref で名指すことは、鮮度を測る 4 本目のアサーションを足すのではなく、鮮度という問いそのものを消す(rules/model/subtractive-structural-beauty.md の binary —— 実行が保証されない手続きは構造へ置き換える)。リリースは同期の発火条件であって内容の選択ではないため、ref はリリース tag ではなく origin/main である。したがって Wiki は最新のリリース tag より先へ進みうる。

1. source ref を取得し、以下の `origin/main` 読み取りが現在の upstream ツリーに解決するようにする:
   git fetch origin
   失敗した場合は STOP してエスカレートする。呼び出し元の作業ツリーへフォールバックしない。ref が
   解決しない状態ではミラーすべき source が無い。鮮度側の検査はこの 1 点のみである。
2. 行末正規化を無効にして Wiki リポジトリを clone し、作業ツリーを raw blob と byte 一致させる:
   git -c core.autocrlf=false clone https://github.com/{owner}/{repo}.wiki.git {tmpdir}
   Windows ホストの既定 clone は autocrlf=true が効き、blob が LF でも作業ツリーを CRLF で
   チェックアウトするため、docs/ 所有ファイルが軒並み drift 判定になり純粋な行末 churn を push する。
   docs/ 側に対応する設定は不要である。`git show` は blob の生バイトを返し、作業ツリーのフィルタを
   経由しない。
3. identity を設定する。clone-and-throw-away パターンは identity を継承せず、未設定だと手順 7 の
   コミットが失敗する:
   git -C {tmpdir} config user.name  "{commit-author-name}"
   git -C {tmpdir} config user.email "{commit-author-email}"
4. drift set を計算する。`origin/main` の docs/ ツリーと wiki 作業ツリーで内容が異なるファイルだけを
   列挙し、その集合のみを操作する。Wiki 作業ツリーへの unbounded な破壊的 glob は代替にならない。
   blast radius が Wiki 全体になり、`rules/evolution/memory-entry-format.md` の Artifact deletion
   calibration の軸で誤った側に落ちる。auto-mode classifier が拒否するのも一過性ではなく構造的な理由による。
   - to_copy = wiki 側と `origin/main` 側の内容が異なる docs/ 所有ファイル(新規 + 内容変更。解決は
     `git ls-tree origin/main docs/`)
   - unclassified = `{tmpdir}/` に存在し、docs/ 所有でも Wiki 専属リストでもない名前。空でなければ
     該当を名指しして STOP しエスカレートする。参照実装はこの地点で非ゼロ終了する。このガードが塞ぐ
     のは削除ではなく**沈黙の素通り**である。手順 5 は copy のみで delete を持たないため、STOP を
     見落としても Wiki からは何も消えず、古いページが残ったまま同期完了として報告される。削除せず
     手順 5 へも進まない。docs/ 側の rename / 削除もここに出るが、リストが追いついていない Wiki
     正本ページも同じくここに出る。エスカレーションは各名前を、source ref 上の
     `docs/` に履歴を持つかどうかで分類する(`git log --diff-filter=AD -- docs/<name>`)。履歴あり =
     docs/ 側の rename / 削除の残骸である公算が高い。履歴なし = Wiki 正本ページである公算が高く、
     削除すれば source が消える。判断構造 entry —— 履歴なしのページは通常これである —— であれば、
     欠けているのは `docs/Decision-Structure.md` の索引行であり、そのページを削除の可否として
     残すのではなく当該行を修復先として名指す。これは判定であって決定ではない。どちらの枝でも機械は削除せず、
     どちらであるかを名指すのは人間である(`rules/operations/operations.md` の published wiki 削除
     ゲート)。名指ししたページに人間の明示 go-sign が出た場合のみ `rm -f` して継続し、出なければ
     そのページは残す。
   - sidebar_new = source ref の `docs/wiki/_Sidebar-head.md`、空行 1 つ、Wiki 側 `_Sidebar.md` の
     最初の `**判断構造**` 行からファイル末尾まで(byte 単位でそのまま)をこの順に連結して組み直した
     `_Sidebar.md`。現在の `_Sidebar.md` と一致する場合、または ref に先頭部ファイルが無い場合は空。
     Wiki 側 `_Sidebar.md` に `**判断構造**` 行が無ければ STOP してエスカレートする。Wiki オーサリング部の
     開始位置が決まらず、それを保つ組み直しができないため。この層でその行を足さない。置くのは人間である。
   Wiki 専属リストの構築は、`_Sidebar.md` に加えて `docs/Decision-Structure.md` が持つ wiki link
   target から slug を抽出する(ファイル名パターンではなく index を追う)。この index も同じ ref から
   読む。片方だけ作業ツリーに残すと、索引と本文の食い違いという形で同じ巻き戻りが再発する。過剰抽出は
   ページを削除から守るだけ、抽出漏れは人間に上げるだけなので、この抽出の精度はどちらの向きにも
   load-bearing でない。
   内容比較は CR 除去後に行い、行末差だけでは drift 扱いしない(LF のみのホストでは no-op。手順 2 より
   後で CR が再混入しても行末が drift にならないようにする防御)。
   drift 計算自体が失敗した場合(`cmp` / `tr` が無い、process substitution 非対応 — bash 系シェルを
   前提とする、ファイルシステムのエンコーディング不一致)は STOP してエスカレートする。wipe パターンへ
   フォールバックしない。参照実装は `skills/operations-on-wiki-sync/SKILL.md` を source とする。
5. drift set を per-file 操作で適用する。各 blob は同じ ref から読む:
   for name in "${to_copy[@]}"; do git show "origin/main:docs/$name" > "{tmpdir}/$name"; done
   if [ -n "$sidebar_new" ]; then mv "$sidebar_new" "{tmpdir}/_Sidebar.md"; fi
   to_copy と sidebar_new がともに空 = drift なし。commit / push を skip して手順 9(後片付け)へ進み、no-op を報告する。
   条件は unclassified の項を持たない。非空なら手順 4 で終了しているため、この行に到達した時点で
   unclassified は常に空である。
6. 追加・削除を全てステージング: git -C {tmpdir} add -A
7. コミット: git -C {tmpdir} commit -m "sync: docs -> wiki ({release_tag})"
8. push: git -C {tmpdir} push
9. 後片付け: rm -rf {tmpdir}

push が権限等で失敗した場合は人間にエスカレートする。省略は禁止。

Windows 固有(case-only rename ハザード)

Windows ホストの wiki repo ファイルシステムは case-insensitive。Installation.md → installation.md のような rename は 1 回の git mv では適用できず、index に旧 case が残る。2 段 rename を使う:

git mv Installation.md __tmp_inst.md
git mv __tmp_inst.md installation.md

検出: git -C {tmpdir} status --short に同名で case 違いの D と ?? のペアが現れる。Linux/Mac はこのハザードを起こさないが、ホスト間で手順を同一に保つため 2 段 rename は同様に適用する。


責務(追加)

条件→行動。省略不可。

実行モード

(→ rules/operations/execution-mode.md)

リポジトリごとの _EXE_MODE(USER_REPO1_EXE_MODE / LI_PLUS_REPO_EXE_MODE 等、対象リポジトリ key 名 + _EXE_MODE)によって AI の自律度を切り替える。未設定の場合、セッション開始時に AI が対話で設定する。有効値は trigger / semi_auto / auto の3種。デフォルトは trigger。

ルール本文は旧スキーマ(単一リポジトリ時代の key)を受け付けない。旧スキーマの検出と移行は Li+update.md の自動移行ステップだけが担うため、モードを読む側は新スキーマだけを読めばよい。

#2134 で、常時ロード面の rules/operations/execution-mode.md から、読む者の行いを変えない文を外した(4,529 B → 3,471 B)。外したのは、モードマトリクスの行を各モード節で言い直していた文(着手タイミング・PR レビュー・リリース確認)、「共通事項」の3行(下記のとおり、いずれも他の常時ロード面が同じことを言っている)、auto mode: 節(2行とも表の再掲で、空になった)、human 判断ゲートの見出し文と末尾の言い直し、Per-PR exception の理由句である。各モードの手順、人間ゲート、マージの行為は変えていない。判断記録は wiki の execution-mode-rule-carries-behavior-only にある。

モードマトリクス

軸 trigger semi_auto auto
着手タイミング 人間が判断 AI が判断 AI が判断
AI セルフレビュー 必須 必須 必須
人間による PR レビュー 全 PR minor / major のみ なし
マージ実行者 AI(--auto handoff) AI(直接マージ) AI(直接マージ)
リリース承認 人間 人間 人間

AI セルフレビューは全モードで必ず実行する(「PR レビュー」節参照)。 マージは全モードで AI が実行する(「マージ」節参照)。マトリクスの「マージ実行者」行は actor 軸で読む——AI の行為が何であるかはモードで異なる。trigger ではその行為は PR 作成時点での GitHub auto-merge(--auto)有効化であり、マージ自体は人間の承認で GitHub が発火させる(承認の瞬間にマージコマンドを実行する主体は居ない)。semi_auto / auto は AI 直接 merge。

各モードの運用

  • trigger モード:実装開始のタイミングを人間が決める。PR は AI のセルフレビューの上に、全 PR で人間レビューが必要。実装開始の合図が出たら、ローカル専用の作業空間ではなく issue にリンクした個人ブランチを主作業面として使う。
  • semi_auto モード:着手タイミングは AI が決める。PR レビューはタイプ連動。
    • patch → セルフレビュー pass で AI が即マージ(人間レビューなし)
    • minor / major → セルフレビュー pass 後に人間確認 → 承認で AI マージ
    • 狙い:自己進化ループの回転が設計目標であり、低リスク変更(patch)の人間ボトルネックを外す。minor / major には人間の目を残す。
    • 多層防御(意図的に2層):Layer 1 = AI セルフレビュー + Li+ 仕様規律(日常的なミスを吸収)、Layer 2 = リリース時の人間ゲート(latest flip、致命的な user 露出を防止)。
  • auto モード:着手タイミングも PR レビューも AI が完結。人間レビューなし。

共通事項

次の3点はモードに依らない。ルール側では rules/operations/execution-mode.md には置かず、それぞれ下記の常時ロード面が持つ。

  • issue 作成・クローズ・修正はアサイニー(AI)の責任(rules/task/task.md の Issue is internal TODO = assignee manages without waiting for instruction.)
  • 情報不足時は人間に確認する(rules/task/task.md の Ask human when required information is missing.)
  • リリースは全モードで人間の確認が必要(モードマトリクスのリリース承認行と、下記 human 判断ゲートの release create)

human 判断ゲート(判断 ↔ 実行軸の分離)

(→ rules/operations/execution-mode.md の human judgment gate 節)

以下の操作は human 判断ゲートの対象。release create / Latest flip / force push / tag delete / マージ済み PR delete / main ブランチへの破壊的変更 / 公開済み artifact への破壊的変更。これらのゲートは判断権限に対するものであって、実行権限に対するものではない。

  • human が yes / no を判断する。
  • 明示的な go-sign(例:「yes」「latest にして」「両方で」)を受けてから AI が gh CLI を実行する。
  • 仕様文中の「human-only」「human flips via ...」「人間専用」「人間が flip する」等の表記は判断主体を指し、実行主体ではない。
  • AI の返答内で human に gh CLI を打つように指示しない。CLI は AI が打ち、human は go-sign を出す。

ゲート対象操作に対する human の発話が曖昧な場合は、最も保存的な解釈をデフォルトとして採る。先行する go-sign を別ゲートに自動拡張しない(release create の go-sign は Latest flip の go-sign ではない)。


自律

AIが自律的に判断して動く領域。

repo-first の作業面

(→ skills/operations-on-branch/SKILL.md の # Repo-first Execution Surface 節。実装面の判断であり実行主体はサブエージェント側に残る)

高注意で扱うのは、main のような保護された共有ブランチである。issue にリンクした個人ブランチは通常の実装面として扱う。リポジトリ全体を過度に「間違えてはいけない場所」とみなさない。

ローカル確認はブランチ作業と両立する。push の前でも後でも実行してよい。ただし、作業継続性の正本は issue にリンクしたブランチ側に置く。ローカルで動いたことだけを完了条件にしない。

引き継ぎ

(→ 正本は rules/operations/main-agent-procedures.md の ## Handoff continuity。実行主体は両方 —— サブは push すべきコミットを持ち、メインは issue body / findings コメント / 実装サブエージェントの resume target を境界越しに持つ。下記の「会話だけに閉じ込めない」はメインにしか当てはまらない。skills/operations-handoff-continuity/SKILL.md はポインタとして残る)

トークン上限、セッション切断、モデル切り替えなどで作業が中断されそうな時は、issue にリンクした個人ブランチへ中間状態を push してよい。引き継ぎ時の正本は、会話ログではなく issue body + linked branch + commit / PR state である。

意味のある進捗をローカルワークスペースや一時的な会話だけに閉じ込めない。

チャット出力制限

(→ 正本は rules/operations/main-agent-procedures.md の ## Chat output limit。チャンキングは複数メッセージにまたがる行為であり、2通目以降を持つ面は人間向けチャットだけである。サブエージェントは報告を1通出して終わるため分割する先を持たない。読み手が残らないので skill は削除した)

長い出力は途中で止まることがある。物理的な制限であり、破損ではない。必要に応じてチャンキングする。


ラベル運用

(→ ラベル辞書の正本は L3 タスクレイヤー rules/task/task.md の ## Task Label Definitions。本節は運用ルールと廃止履歴のみ保持。辞書は rules/task/task.md だけが持つ)

ルール

(→ rules/operations/operations.md の ## Operations Label)

  • すべての issue に作成時点でタイプラベルを1つ以上付与する
  • すべての issue に作成時点で成熟度ラベルを1つ付与する

責務

  • ライフサイクルラベルは状態変化時に適用する
  • ラベルは AI の可読性とフィルタリングのためにある

廃止・改名されたラベル

ラベル 理由
done review-pending へ改名(#1681)。close 操作と同じ「完了」を名乗り、実装フェーズ終了という意味を単体で運べていなかった

ラベルの追加・変更・廃止は、正本の rules/task/task.md の Label Definitions セクションを直す。本節と docs/3.-Task.md の写しは、skills/operations-on-docs-ownership/SKILL.md の grep-sweep で追随させる。

rules/operations/operations.md の ## Operations Label は以前 ### Marker と ### Sync を持っていた。### Marker(promotion)は rules/task/task.md の Marker と同じ定義の写しだった。### Sync(「ここで label の集合を変えたら task.md も直す」)は、Marker を外すと同期する相手の辞書が operations.md に残らない。どちらも #2127 で外した。「ラベルは AI の可読性とフィルタリングのためにある」も rules/task/task.md の Autonomy と重なるので、rules からは外し、本節の責務に説明として残した。rules/task/task.md の Autonomy も #2136 で外したので、この説明を持つのは本節と docs/3.-Task.md のラベル定義である。


通知 API

(→ 正本は rules/operations/main-agent-procedures.md の ## Notifications API。直接呼ぶ瞬間は下記のフォアグラウンド取込経路であり、そこに立つのはメインのみ。サブが webhook に触れるのは CI ループだが、そちらは MCP 面を読むためこれらのエンドポイントには届かない。読み手が残らないので skill は削除した)

GET    /notifications?all=false                -> 200  inbox 確認
PATCH  /notifications/threads/{id}             -> 205  既読(Inbox に残る)
PUT    /notifications {"read":true}            -> 205  全既読
DELETE /notifications/threads/{id}             -> 204  完了(Inbox から除去)

scope = notifications(classic PAT)

通知 API の生操作はオペレーションレイヤーから参照してよい。ただし、前景関連性判定、claim、ack/read、consume/done、mention、cleanup の意味論は 5. Notifications を正本とする。

フォアグラウンド webhook 取込

(→ rules/operations/main-agent-procedures.md の ## Foreground webhook notification intake。skills/operations-foreground-webhook-intake/SKILL.md はリダイレクトスタブとして残る)

各ユーザー turn の開始時に webhook イベントを検査し、前景関連または特記すべき項目、および下記「保留の出口」が名指すイベントのみ言及する。前景関連性が安価に判定できない場合は保持して沈黙する。ただし所有判定の手順 4 で保留したイベントは、保留の出口で一度名指されるまでこの沈黙の対象にならない。別 AI プロセスの起動は本フローでは禁止。

local webhook store の state dir 解決は、当たったディレクトリが state dir の体裁を持つかを検査する。体裁 = ヘルパが読む名前(events.json / notification-claims.json / trigger-events/ / codex-runs/)のいずれかを持つこと。持たなければ未解決として次の候補へ進み、全候補が外れたら未解決とする。名前の一致だけでは決まらない —— ツール自身のソースを {workspace_root}/github-webhook-mcp にクローンしている構成では、候補 b が state を持たないディレクトリに当たり、解決に成功したうえで全カウントが 0 になる。名前の正本は scripts/check_webhook_notifications.py。

未解決による silent skip は、滞留についての観測ではない。未解決とは何も読んでいないということであり、滞留は不明であって 0 ではない。「滞留なし」として報告しない。

自操作の到達確認

webhook 通知には自分の操作結果(push、PR、issue、リリースなど)も含まれる。これらは GitHub への到達確認として機能する。自操作イベントはフォアグラウンドチェック時に速やかに mark_processed する。一括クリアのために溜め込まない。外部からのイベント(他ユーザー、bot)は保持し、フォアグラウンド報告または明示的な処理フローに委ねる。

自操作かどうかは手順で判定する(勘で決めない)。

  1. head_branch が自セッションの作業ブランチ → 自分のもの
  2. イベントを自セッションが書き込みを行った対象(write set)と照合する。「書き込みを行った」は起票に限らず書き込み全体を指す。issue body を編集しただけのセッションも、起票したセッションと同様に一致する。この手順が問うているのは、そのイベントが自セッションの行った操作の到達確認かどうかであり、issue の起票者ではない。write set には、書き込みコマンドの戻り値(作成した issue / PR / コメントの URL・番号)を含む
    • workflow_run → head_branch を問わず、gh run view <id> --json displayTitle を読んで write set と照合する(event=issues は issue タイトル、push は commit タイトル、pull_request は PR タイトルを運ぶ)。以前は head_branch が main のときだけこの照合に入れたため、他セッションのブランチの run は照合材料が手元に在っても手順 4 に落ちていた
    • issue_comment / pull_request_review / issues / pull_request で、sender が自セッションの書き込みに使うアカウント → そのイベントの issue / PR 番号が write set に在れば自分のもの。これらの種別は head_branch を構造的に持たないため、ブランチ軸の照合では決着しない。sender の条件は、別アカウント(人間のレビューやコメント)を番号の一致だけで自分のものとして消化しないためにある
  3. sender が別アカウント → external、保持
  4. いずれでも決まらない → 保留し、未処理のまま残す。sender が自セッションの書き込みに使うアカウントで、手順 1・2 のどちらにも一致しないイベント(共用アカウント経由の操作など)はここに来る。手順 3 の「別アカウント」には当たらない

保留の出口: 保留したイベントは、次の前景チェックで判定をもう一度走らせる(その間に write set が増えているため)。それでも決着しないイベントは、その回の返答で一度だけ「持ち主不明で保留」と名指す。以後は手順 3 と同じく保持に移り、再び名指さない。出口が無いと、保留したイベントは報告も消化もされずに黙って残り続ける。

手順 2 に残す限界(意図的に残す): 題名が指すのは issue であって書き手ではない。二セッションが同じ issue に書き込むと run は 2 本立ち、題名は同じで、双方が両方を own と判定する。ただし飢餓は起きない —— 各セッションが実際に 1 本ぶんの到達確認を持っており、mark_processed は冪等なので過剰消化は一度目と同じ状態を書くだけである。書き手の識別は閉じるのではなく諦める形であり、同一アカウントで認証するセッションを分ける識別子が GitHub 側に存在しない以上避けられない。これを手順 2 の起票限定に戻して直してはならない。起票者でない書き込みがすべて手順 4 に戻り、消化できる主体がどこにも居ない状態に戻る。


Discussions

(→ 正本は rules/operations/main-agent-procedures.md の ## Discussions intake。外部由来 issue をどう読むかの制約であり、issue management はモード分岐なしで Parent retains にある。サブは issue の出自が仕事に届かないため読み手が残らず、skill は削除した)

Discussions は外部ユーザーの入口。bot が常駐し、issue 作成と issue 読込が可能。コミット・コード変更はできない。

外部ユーザーが Discussions に投稿 → bot が issue を作成 → AI が issue から実装する。


進化

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

要求仕様書 (1-6)

参考文書 (A-L)

判断構造

Clone this wiki locally