L. Hop Count Instrument - Liplus-Project/liplus-language GitHub Wiki
Hop Count Instrument
常時ロード分(adapter/claude/CLAUDE.md + rules/** + skill description)に対する削減作業の before / after を比較可能にするための計測固定面。#1564 の検証手段の実体であり、以降の削減作業(#1587 / #1588 / #1589 ほか)はすべてこの instrument を前提とする。
計測対象は 規則の適用瞬間に、必要な literal に到達するまでのファイル遷移数。同一タグに対して同じ数値を再現する静的到達性の計数であり、実行時計測ではない。
baseline tag = build-2026-07-28.5(commit 6e616cb)。以下の跳躍数はすべてこのタグ時点の実測。表中の行番号のみ、本 instrument を導入した PR(#1586-#1589)のマージ後の位置に合わせてある — 同 PR はいずれのシナリオでもツール呼び出し跳躍を変えていない。
計数規則
- 起点 = そのシナリオの適用瞬間を名指しする always-on リテラル。固定の実体は trigger 文そのもの(各シナリオに
anchor:として記載)であり、併記のfile:lineはその位置の目安。行番号は当該ファイルを触る PR で更新する(行番号のずれ自体は差し替えではない)。 - 追跡対象 = 起点から、そのシナリオが必要とする literal に到達するために load-bearing な明示ポインタのみ。ソース中に書かれていない連想的な参照は数えない。
- 1跳躍 = ファイル遷移1回。同一ファイル内の節移動は跳躍ではない。
- 分類:
- 文脈内跳躍 = 遷移先が
rules/**またはadapter/claude/CLAUDE.md(常時ロード分。ツール呼び出しを要さない) - ツール呼び出し跳躍 = 遷移先が
skills/*/SKILL.md本体 /docs// hook (adapter/*/hooks/*) /adapter/*/agents/*.md/adapter/*/hooks-settings.md
- 文脈内跳躍 = 遷移先が
- 非計数 =
memory/**(workspace-local、仕様リテラルではない)、git 履歴、外部 URL、MCP ツール呼び出し(ファイル遷移ではない)。
合格条件
各シナリオの ツール呼び出し跳躍が減るか据え置き。増えた場合は、増分の理由を PR 本文で説明できない限り regression として扱う。
文脈内跳躍の増加は合格条件に含めない。常時ロード分の内側の重複を削ると文脈内跳躍が1つ増えるのは設計上の想定挙動であり、これを罰すると重複削除ができなくなる(#1564「主軸の確定」)。
再計測手順
「シナリオ集合」の各行に記録された経路を辿り直し、(1) 記録済みポインタが消えていないか、(2) 起点と目的 literal の間に新しいツール呼び出し跳躍が挿入されていないか、の2点を確認する。
記録された経路は判断の幅を狭めるが、判断を無くしはしない。 残る判断は次の2点に集中する。再計測者ごとにぶれるのはここなので、数値だけでなく「なぜ数えた/数えなかったか」を経路行に書き残す(各シナリオの 非計数 行がその置き場)。
- どのポインタが load-bearing か(計数規則 :14)。目的 literal への到達に本当に必要な参照と、隣接して書かれているだけの連想的参照の線引きは自明ではない。実測: 本 instrument をブレーキ1(
skills/evolution-parallel-agent-eval、N=3)に掛けたところ、3体の評価者がいずれもこの線引きを独自に判断し、うち2体が記録と異なる分割に達した。S2 / S3 の過大計上はこれで発覚した。 - どこまでが当該シナリオの鎖か(シナリオ間の境界)。別シナリオが既に計測している区間は、二重計上を避けるため数えない。境界の位置そのものが判断であり、記録から自動的には出てこない。
シナリオ差し替え規則
アンカーとなる trigger 文がソースから消えた場合のみ差し替えを許す。 それ以外の恣意的な入れ替えは before / after を無効化する。
差し替える場合は本ファイルを同一 PR で更新し、旧アンカーと新アンカーの双方を記載して、どのソース変更で消えたかを明示する。
シナリオ集合(12本、固定)
| ID | 適用瞬間 | 起点 file:line |
ツール | 文脈内 |
|---|---|---|---|---|
| S1 | self-evolution PR が CI green → 次に何を走らせるか | rules/evolution/initiator-autonomy.md:55 |
3 | 0 |
| S2 | subagent 完了 → 親の次の行動 | adapter/claude/CLAUDE.md:47 |
1 | 0 |
| S3 | webhook イベント到着 → 処理と mark_processed |
adapter/claude/CLAUDE.md:153 |
2 | 0 |
| S4 | sub-issue が親の本文範囲を超える | rules/operations/main-agent-procedures.md:121 |
1 | 0 |
| S5 | L1 evaluator の判定基準そのもの | rules/evolution/initiator-autonomy.md:69 |
1 | 0 |
| S6 | patch / minor / major の分類 | rules/operations/release-version-rule.md:25 |
0 | 0 |
| S7 | Li+update 実行要否の判定 | adapter/claude/CLAUDE.md:9 |
0 | 0 |
| S8 | memory 書き込み直前の persistence 判定 | adapter/claude/CLAUDE.md:118 |
1 | 1 |
| S9 | 判断が settle した → Decision Structure entry を書く | adapter/claude/CLAUDE.md:128 |
2 | 1 |
| S10 | drift / pattern を観測 → 昇格の閾値判定 | rules/evolution/promotion-judgment.md:15 |
0 | 0 |
| S11 | merge 完了直後 → L1 変更の短窓観察 | rules/operations/operations.md:85 |
1 | 1 |
| S12 | session 開始 → cold-start synthesis | rules/evolution/cold-start-synthesis.md:11 |
2 | 1 |
| 合計 | 14 | 4 |
S1 / S3 / S4 / S5 / S6 / S7 のツール跳躍は #1564 実測2 の表と一致する(同一タグで再検証済)。S8-S12 は同じタグ・同じ計数規則で本 instrument 固定時に測った。
S2 のみ #1564 実測2 の記録(ツール2 / 文脈内2)と一致しない。同記録は計数規則(:14)に反する連想的参照を含む過大計上であり、本 instrument 側をツール1 / 文脈内0 に訂正した(PR #1592 のブレーキ1 で検出)。訂正は計数の誤りの是正であって、ソース側の変化ではない — 同じ数値が baseline tag でも現在でも成り立つ。S3 も同じ理由で文脈内跳躍を1つ落としたが、ツール跳躍は2のまま変わらない。
各シナリオの経路
各行は 起点 → 遷移先 の順。[tool] / [ctx] は分類。
S1 — anchor: the brakes run after CI green and before the merge gate
- →
skills/operations-on-pr-review/SKILL.mdDelegated-subagent stop condition[tool] - →
skills/task-subagent-delegation/SKILL.mdRules[tool] - →
skills/evolution-parallel-agent-eval/SKILL.mdProcedure[tool] - 追記(#2146)—— 起点の文(
rules/evolution/initiator-autonomy.mdMerge brake の Position)はこの PR で変わらず、表の行番号だけを更新した。条件 2 の除外面と、往復のあいだの親の分担はskills/evolution-parallel-agent-eval/SKILL.mdへ移った。この鎖が既に到達する同じ skill なので、ツール跳躍は増えない。
S2 — anchor: Main agent after subagent completion:
- →
skills/task-subagent-delegation/SKILL.md(CHANGES_REQUESTED の再委譲。同一ファイル内adapter/claude/CLAUDE.md:126の明示ポインタ経由であり、節移動は跳躍に数えない)[tool] - 非計数1 — 自己レビュー〜merge へ続く鎖(
rules/evolution/initiator-autonomy.mdTwo-stage brake →skills/evolution-parallel-agent-eval/SKILL.md): S1 が計測するため二重計上を避ける。加えてアンカー行(:75-78)にこの鎖を名指す明示ポインタがない —initiator-autonomy.mdへの参照はadapter/claude/CLAUDE.md:190/:194/:196、すなわちEvolution_Initiator_Autonomyブロック内にのみ存在する。境界規則と計数規則(:14)の双方から除外。 - 非計数2 —
rules/operations/release-version-rule.md(release の version type 確認):grep -c release-version-rule adapter/claude/CLAUDE.md= 0。アンカーからの明示ポインタが存在しない連想的参照であり、計数規則(:14)により除外。 - 追記(#1808)—— baseline 以降、非計数1 が名指す節
Two-stage brakeはMerge brakeへ改名された。上の節名は baseline タグ時点の literal なので書き換えない。 - 追記(#2145)—— アンカー文と CHANGES_REQUESTED の行は
adapter/claude/CLAUDE.mdに文面のまま残る(アンカーの差し替えではない)。同じブロックのFor release: confirm version type and tag with human.は、常時ロードのrules/operations/main-agent-procedures.mdHuman confirmation required の写しとして外した。release の確認に届くまでの経路は文脈内跳躍が 1 増え、ツール跳躍は変わらない。この行は上の計数でも数えていない。上の経路行と非計数行の中の行番号(:126/:75-78/:190/:194/:196)は本 instrument を固定した時点の literal なので書き換えない。:126が指す明示ポインタは、#2145 以降Delegation semantics are defined in skills/task-subagent-delegation/SKILL.md.(adapter/claude/CLAUDE.md:89)にある。
S3 — anchor: Webhook intake policy and procedures:
- →
skills/operations-foreground-webhook-intake/SKILL.md[tool] - →
adapter/claude/hooks-settings.md[tool] - 非計数 —
rules/operations/operations.md(mark_processedの義務): 鎖のどこにも明示ポインタがない。grep -n "operations\.md"はskills/operations-foreground-webhook-intake/SKILL.md/adapter/claude/hooks-settings.mdとも0件、アンカー(:200)が名指すのは skill のみ。計数規則(:14)により除外。なおmark_processedの実務リテラル自体は baseline 時点の skill 本体(:68)に到達済みで、この参照は追加跳躍を要さない。 - 追記(#1762)—— baseline 以降、この鎖の到達先は
rules/operations/main-agent-procedures.mdの## Foreground webhook notification intakeへ移り、skill 側はリダイレクトスタブになった。上の跳躍数は baseline タグ時点の実測なので書き換えない。
S4 — anchor: Sub-issue work exceeding parent body literal ... requires dialogue confirm
- →
skills/operations-on-sub-issue/SKILL.mdscope-exceed dialogue confirm[tool] - 追記(#1764)—— baseline 以降、この鎖の到達先は
rules/operations/main-agent-procedures.mdの## Sub-issue rulesへ移り、skill 側はポインタになった。上の跳躍数は baseline タグ時点の実測なので書き換えない。 - 差し替え(#2136)—— 旧アンカー
Sub-issue work exceeding parent body literal ... requires dialogue confirm(rules/task/task.md)は、同じ行いを常時ロードで持つrules/operations/main-agent-procedures.mdSub-issue rules の写しとして #2136 で外れた。新アンカーは到達先そのものIssue body literal is the scope boundary. ... fire a dialogue confirm(表のfile:line)。上の跳躍数は baseline タグ時点の実測なので書き換えない。 - 追記(#2138)—— アンカー文は
rules/operations/main-agent-procedures.mdSub-issue rules に文面のまま残る(アンカーの差し替えではない)。閾値、同期集合の carve-out、confirm の形、literal に当たらない発火の禁止、PR レビュー時の発火の却下はskills/task-sub-issue/SKILL.mdScope-exceed dialogue confirm へ移り、アンカーの直後の 1 行がそこを名指す。#2136 以降の到達先は常時ロード面の内側(ツール跳躍 0)だったので、confirm を実際に出すまでの経路はツール跳躍が 1 増える(baseline の値 1 と同じ数に戻る)。表の数値は baseline タグ時点の実測なので書き換えない。増分の理由: 発火条件(どの literal を越えたら、どの時点で)は常時ロードに残るので、発火は skill の自動起動の想起に依存しない。skill を開くのは発火すると決めた後、confirm の形と carve-out を読むときだけで、その 1 行が名指す。これらの詳細が要るのは発火の場面だけで、それ以外のすべてのセッションで約 1.5 KB を文脈に載せていた。跳躍先はtask-*skill なのでメインが開ける。
S5 — anchor: brake 2 (L1 only)
- →
adapter/claude/agents/l1-gate-eval.md[tool] - 追記(#1808)—— baseline 以降、brake 2 は廃止され、アンカーも到達先も存在しない。上の跳躍数は baseline タグ時点の実測なので書き換えない。
S6 — anchor: Application-moment trigger:
- 判定基準は同一ファイル内に完結。跳躍ゼロ。
- 同行が指す
skills/model-trigger-check-gate-actions/SKILL.mdは「読む癖」側の補助であり、分類リテラルへの到達に load-bearing ではないため計数しない。
S7 — anchor: Inspect the LI_PLUS_UPDATE_STATUS= marker
- 判定リテラルが entrypoint 自身に完結。跳躍ゼロ。
S8 — anchor: Before each memory write, apply skills/evolution-persistence-tiering write-time trigger.
- →
skills/evolution-persistence-tiering/SKILL.md[tool] - →
rules/evolution/memory-entry-format.md(entry 形式・維持規律)[ctx]
S9 — anchor: When the trigger fires, invoke skills/evolution-decision-structure-write and write immediately
- →
skills/evolution-decision-structure-write/SKILL.md[tool] - →
docs/Decision-Structure.md(index 更新 = Procedure step 6)[tool] - →
rules/evolution/memory-entry-format.md[ctx]
S10 — anchor: A drift / pattern observation occurring at any moment
- 閾値表(同一ファイル
:78-83)まで同一ファイル内。跳躍ゼロ。
S11 — anchor: Invocation anchor: this procedure is named at the merge moment by rules/operations/main-agent-procedures.md Merge Execution
- →
rules/operations/main-agent-procedures.md## Merge Execution[ctx] - →
skills/evolution-observation-entry/SKILL.md(miss verdict の escalation 先)[tool] - 追記(#2141)—— アンカー文は
rules/operations/operations.mdの## Post-L1-Merge Runtime Observationに文面のまま残る(アンカーの差し替えではない)。起点・観測セット・繰り越し・既存の観測軸との分離はskills/evolution-observation-entry/SKILL.mdの# Post-L1-Merge Runtime Observationへ移り、常駐に残った節の 1 文がそこを名指す。移し先は上の miss verdict の escalation 先と同じファイルなので、ツール跳躍は 1 のまま変わらない(観測手順そのものへの到達は、#2141 までは常駐面の内側だったものが同じ[tool]跳躍の先になる)。跳躍先はevolution-*skill でメインが開ける。
[tool] から [ctx] へ変わっているのは #1708 の移設による。旧アンカーは skills/operations-on-merge/SKILL.md の invoke を指していたが、この手続きの実行主体は auto / semi_auto では親であり、親は operations 系 skill を読まない。跳躍先が実行主体にとって開けない [tool] だったものが、常駐で保持される [ctx] になった。
S12 — anchor: Trigger = session start, after Li+config.md execution completes.
- →
docs/Decision-Structure.md(Action step 1)[tool] - →
adapter/claude/hooks/on-session-start.sh(Hook coordination。baseline 時点の経路。#2118 以降、この段落はdocs/2.-Evolution.mdCold-start Synthesis 節「フックの出力契約」にあり、規則本文からのポインタは無い)[tool] - →
rules/evolution/memory-entry-format.mdSelf-Evolution Observation Format[ctx] - →
skills/evolution-observation-entry/SKILL.md[tool]
S11 / S12 の observation 手順への跳躍は #2131 で [ctx] から [tool] になった。同 PR が observation エントリの書式・作成基準・判定の lifecycle を常時ロード面(rules/evolution/memory-entry-format.md)から skills/evolution-observation-entry/SKILL.md へ移したためで、ツール呼び出し跳躍が各 1 増える。表の数値は baseline tag 時点の実測なので動かさない(上の S12 の据え置きと同じ理由)。増分の理由: この手順が要るのはマージ後の瞬間と cold-start で due / overdue が surface されたときだけで、それ以外のすべてのセッションで約 6 KB を文脈に載せていた。どちらの瞬間にも常時ロード面または hook の出力に名指しのポインタが立ち(S11 は rules/operations/operations.md が skill を直接名指し、S12 は cold-start-synthesis の参照が memory-entry-format.md の同名節を経て skill に届き、hook の due / overdue 出力も skill を名指す)、跳躍先は evolution-* skill なのでメインが開ける。
Hook coordination 段落は #1765 で同一ファイル内の H2 ## Hook Emission Contract(冒頭に「読むのは on demand、step 3 の適用瞬間には適用しない」と明示)へ移した。跳躍数は据え置き — 同一ファイル内の節移動は跳躍ではなく(計数規則 :15)、ポインタは同じファイルから解決するため。その H2 は #2118 で規則本文から外れ、docs/2.-Evolution.md の Cold-start Synthesis 節(フックの出力契約)へ移った。適用瞬間に要る anchor 内の Operational criterion は動いておらず(アンカー行 cold-start-synthesis.md:11 のまま)、この移動も表を動かさない。
据え置きを選んだ判断は記録しておく(再計測手順 :31)。適用瞬間に要るのは anchor 内の Operational criterion だけで、そこが引く emit 状態(full / diff-only / marker)は「状態によらず silent」と言うためのものであり、marker 自体は emit 済みコンテキストに直接見える。この読みではツール跳躍は 1 に落ちる。それでも表を動かさないのは、表の数値が baseline tag 時点の実測だからで、後続 PR が読み替えで数値を動かすと before / after の比較面そのものが失われる。S2 / S3 の訂正は計数規則違反の是正であり、適用ステータスの読み替えとは別軸。
経路ゼロ検査
跳躍数が多いことより悪い状態=たどれる線がない。該当ファイルに触れる変更のたびに以下を再実行し、いずれも非空であることを確認する。
grep -nE "promotion-judgment|promotion_tally|noise.floor" skills/evolution-self-eval/SKILL.md
grep -nE "self-eval|self-evaluation" rules/evolution/promotion-judgment.md
自己評価の記録中に根本原因の反復に気づいた瞬間から、noise floor ゲート(rules/evolution/promotion-judgment.md)への経路が両方向でたどれることを保証する。1本目は #1587 で新設された経路、2本目は既存の trigger 列挙(同 issue で参照を明示化)。
適用範囲外
- 「劣化がないこと」の証明はしない。本 instrument が測るのは跳躍数のみ。品質面の検証はブレーキ1(
skills/evolution-parallel-agent-eval)が各 PR に対して別軸で掛かる。 - バイト削減量は測らない。#1564 実測1 のとおり削り代は約 32 KB であり、バイトは主軸ではない。
- 実行時のトークン消費・レイテンシは測らない。静的到達性のみ。