PlanGate v8.21.0
このファイルは
CHANGELOG.mdの## v8.21.0節からの機械抽出物です(生成: 本 runbook §6 の再生成コマンド。手で書き足さないこと)。
正本はCHANGELOG.md。CHANGELOG を修正したら本ファイルを再生成してください。
リリース概要
fix: 参照解決順の「構造上空振りする段」を配布物から除去し、EH-3 / EH-13 のガード迂回を封鎖。さらに sh 誤起動から gh pr merge へ到達する経路(NO MERGE BY AI の迂回)を配布物ごと塞ぐ
v8.20.0 タグ以降に main へ蓄積した 62 コミット(実測: git rev-list --count v8.20.0..375c791)を反映する。
主題は 「参照はあるが解決されない」「ガードはあるが迂回できる」構造の実測是正。
配布物(plugin/)の変更は 79 ファイル(実測: git diff --name-only v8.20.0..375c791 -- plugin/ | wc -l)で、
内訳は skill の参照解決順・正本参照の是正と、ai-loop-cycle 同梱スクリプト 30 本への sh 誤起動ガードの同期。
schemas/*.json と bin/plangate は変更ゼロ
(実測: git diff --stat v8.20.0..375c791 -- schemas/ bin/ が空)→ Schema / CLI の挙動は不変。
(数値はいずれも 基点 375c791 時点の測定値であり、tag 時点の総数を約束する契約値ではない。基点の考え方は
docs/working/_merge/v8.21.0-release-runbook.md §0 を参照)
PlanGate 本番フロー WF-00〜07 は不変・NO MERGE BY AI/C-4・merge は Human-owned 固定。
⚠️ 更新前に必ずお読みください(block / 停止 挙動が 3 箇所で強化されます)
1. と 2. の対象: 本リポジトリを clone して
scripts/hooks//scripts/check-approval-token-write.shを
.claude/settings.jsonへ配線している利用者。 これらは plugin 配布物に含まれません。
plangateプラグインをplugin marketplace経由で導入しているだけの場合、1. と 2. は影響しません。3. の対象はより広く、
plangateプラグイン経由の導入も含みます(ai-loop-cycleskill 同梱の
scripts/*.pyが配布物に入るため)。NO MERGE BY AI(Iron Law)に直接関わる是正のため、
本リリースで最も重要な告知です。
-
EH-3: Hardening Override の block が TASK 文脈でも発火するようになりました(#1089 / PR #1097)。
v8.20.0 で「既知の未解消ギャップ」として出荷した迂回(PLANGATE_HOOK_TASKを設定していると HO 判定が
一度も評価されず、9 カテゴリすべてでrc=2→rc=0になる)が解消されています。
PLANGATE_HOOK_TASKを設定した状態で HO 対象パス(.claude/rules/*.md/.claude/settings*.json/
.claude/commands/*.md/.claude/agents/*.md/scripts/hooks/*.sh/bin/plangate/
schemas/*.schema.json/.github/workflows/*.yml|yaml/AGENTS.md/CLAUDE.md)を編集していた
フローは block されます(これが本来の期待挙動です)。適用済みのため、gap を受理していた
tests/fixtures/eh3-known-gap-1089.flagは削除されています(scripts/apply-eh3-ho-always.sh
は適用後も repo に残りますが、再実行は不要です)。 -
EH-13: 承認トークン書き込みガードの迂回 2 クラスを封鎖しました(#1115 / PR #1148、#1110 / PR #1121)。
外側ゲートがコマンド文字列をリテラル照合していたため、保護対象のファイル名にワイルドカードを
混ぜると照合が外れ、実測で 21 コマンド(cp/mv/tee/sed -i/git restore/
python・node・ruby の書き込みを含む)がrc=0で素通りしていました。照合方向を反転し、
(A) approvals 配下でファイル名が glob (B) basename が先頭 glob でなく保護 basename にパターン一致、
の 2 条件に絞って block します(無条件 block は日常の glob コマンドまで落とすため)。
この 2 条件で塞がるのは実測 21 件中 18 件で、node -e "…writeFileSync(…)"/
ruby -e "File.write(…)"/python3 -c "open(…,'w')"の 3 件は是正後もrc=0のまま残存します
(実測:docs/working/TASK-1115/evidence/lane-scan.txtのv2列)。残存クラスと follow-up 候補は
docs/working/TASK-1115/plan.md§残存クラス を参照してください。あわせてリダイレクト判定を「先と保護パスの相関」で行うようにし、
コミットメッセージにパス名を書きつつ無関係な出力を/tmpへ流すだけのコマンドが block される
誤検出(#1110)を解消しました。判定不能なケースは従来どおり block 側に倒します(fail-closed 不変)。 -
sh誤起動でgh pr merge/gh pr review --approveが実際に走る経路を封鎖しました(#1169 / PR #1187)。
sh scripts/ai-loop/gh_exec.pyのようにpython3以外のシェルで.pyを起動すると、shが module
docstring 全体を二重引用符文字列として読むため docstring 内のバッククォートがコマンド置換として評価され、
中身のコマンドが実行されていました。scripts/ai-loop/には gh / git を実行する唯一の境界(gh_exec.py)が
含まれるため、隔離した stub サンドボックス(PATH に記録用 stub のみ・空 cwd)で 30 本をsh起動した実測で
gh12 回 +git3 回が発火し、その中にgh pr merge/gh pr review --approve/gh pr closeが
含まれていました(gh_exec.py単体でgh6 回)。v8.20.0 以前の配布物にはこの経路が残っています。
是正後は同じ実測で発火 0 件。scripts/ai-loop/30 本と、その配布ミラー
plugin/plangate/skills/ai-loop-cycle/scripts/30 本に polyglot ガード(PG-SH-GUARD)を入れ、
sh/bash/zsh起動時は何も評価する前に診断メッセージ +exit 2で停止します。
python3起動時の挙動は不変です(no-args /--helpの rc と出力を全数比較して確認済み)。
更新後、これらの.pyをsh(またはbash/zsh)で起動していたスクリプト・手順はexit 2で止まります。
python3 <path>へ書き換えてください(元からpython3起動なら影響ありません)。
semver 裁定: 規約 docs/ai/versioning-stability-policy.md §2.2
「既定挙動の変更(SKIP → BLOCK)」は上記 2 件を major と示すが、本リリースは Human 裁定により minor。
影響が plugin 配布物に含まれない hook 配線利用者に限定されること、および v8.19.0(EH-13 の
exit 1 → exit 2 fail-closed 化)で同型を minor と裁定した前例に揃えた。判定者・判定日・残る不整合と
follow-up は docs/working/_merge/v8.21.0-release-runbook.md §1 に記録した。
Added
diff-auditskill に検証観点を追加(#1152 / #1137)— シェルオプションの意味論・実行文脈・多配置先追従の 4 観点、およびテスト検証の検出力 3 観点と自己宣言制約の Rationalization。配布物に含まれるcheck-skill-name-collisions.pyに「同一 root 内の重複」検出を追加(#1087 / PR #1149)— 従来は「2 定義以上」を見ておらず原理的に検出できなかったクラス。repo-local と plugin export のミラーは 4 条件の合接に限って除外し、握り潰さず INFO として印字する
Fixed
- skill の参照解決順から、構造上必ず空振りする plugin root 段を除去(#954 / PR #1139・#1146・#1154・#1158。PR #1158 単体で 41 ファイル、4 PR のユニーク和は 73 ファイル)—
docs/**はsync-plugin-plangate.shの設計上 plugin の配布対象外のため、docs/**専用の解決順に置かれた plugin root 段は常に解決されない手順だった。rules/*.md(クラス A)の解決順は plugin root 配下が実在するため不変 - 不在 rules 6 件への参照を現行正本へ張り替え、後継なしは明記(#1125)/クラス A' の rules 参照を正本 root で壊れない形へ是正(#1123・#1127)/
intent-classifier/skill-policy-routerの正本宣言を実態へ是正し 4 root を新版で統一(#1126) - クラス A(
rules/*.md参照)の解決梯子を 4 skill に追加(#1159 / PR #1164)—design-gate/intent-classifier/plan-review-gate/skill-policy-routerで、plugin 経由の導入だと判定の正本(mode-classification.md等)が引けない状態だった。配布物 4 ファイルを含む - skill の CLI 呼び出し表記を PATH 解決名へ統一し、CLI 不在時の degrade を明記(#1122)
ai-loopの run 指定に関する CLI 誤読を解消(#982 / PR #1160)— 入口は/ai-loop-workflowの引数仕様であることをai-loop-cycleskill と runbook / loopspec で明示(配布物を含む 3 root =.agents/.claude/plugin/plangateとdocs/workflows/ai-loop。.codex/skills/ai-loop-cycle/SKILL.mdは未追従のまま)- C-1 セルフレビューの項目数を実体(全 25 項目)へ是正(#960 / PR #1118。非 HO 分 24 ファイル)。PR #1122 が「17 項目」表記を再導入した退行も是正した(PR #1138)
- EH-3 の Hardening Override を
task_id文脈に依存せず評価(#1089 / PR #1097)— HO 判定がtask_id未設定分岐の内側にあったため、PLANGATE_HOOK_TASKが設定されたセッションでは HO 9 カテゴリすべてが block されなかった(PLANGATE_HOOK_TASKはplan.md編集の正規経路であり、PlanGate 作業中のセッションこそ HO 保護が外れる状態だった)。判定をtask_id分岐より前へ移動し、TASK 文脈の有無に依らず block する。回帰はtests/extras/ta-65-eh3-ho-task-context.sh。適用済みのためtests/fixtures/eh3-known-gap-1089.flagは削除されている(scripts/apply-eh3-ho-always.shは repo に残るが再実行不要) - EH-13 の外側ゲート迂回とリダイレクト誤検出(#1115 / PR #1148、#1110 / PR #1121)— 上記「
⚠️ 更新前に必ずお読みください」2. を参照 - plugin skill spec 検査の silently skip(#1109 / PR #1120)— 宣言した検査対象が不在でも緑になっていた状態を解消し、
.codex/skills/の 8 件のagents/openai.yamlを是正 - 配布物検査 2 本の判定を実態へ是正(#1087 / PR #1149)—
check-skill-name-collisions.py/check-stale-skill-refs.pyは rc=1 のまま放置され CI にも未配線だった。全件を実測分類した結果 rc=1 の中身はいずれも検査側の誤りだったため rc=0 化した(CI 配線は patch 提示まで) ta-62TC-D の timeout を誤診断せず切り分け(#1062 / PR #1142)— 実行回数 7 回の実測調査つき- skill 名衝突検出のミラー判定に plugin 名と内容同一性を要求(#1153 / PR #1174)— #1149 が入れたミラー除外は
startswith("plugin:")しか見ていなかったため、consumer の.claude/skills/<name>と第三者 plugin のplugin/<other>/skills/<name>という真の名前衝突を「正常なミラー」としてrc=0で通していた。除外条件に (3) 自リポジトリの export 先 plugin 名であること(既定plangate。--mirror-pluginで置換指定。判定不能なら衝突=安全側)と (5) 内容同一性(description 一致、または drift が構造的に説明できるskillkind のみ許容し、agent/commandの drift は衝突)を追加した。回帰はtests/extras/ta-69-distribution-checks.shの TC-C10〜C14。scripts/check-skill-name-collisions.pyは plugin 配布物には含まれない shで.pyを起動すると repo が書き換わる経路を封鎖(#1169 / PR #1175)—sh scripts/check-skill-frontmatter.pyのように誤ったインタプリタで起動すると、shが module docstring 全体を二重引用符文字列として読むため docstring 内のバッククォートがコマンド置換として評価され、scripts/install-plangate-skills-to-codex.shが実際に起動して.codex/skills/**が書き換わっていた(本リリース準備のレビュー中に実害として発生。shebang と実行権限は既に付いており、それだけでは塞がらない)。scripts/直下の*.py27 本すべての先頭に、python3以外で起動された場合に何も評価する前に診断メッセージ +exit 2で停止する polyglot ガード(PG-SH-GUARD)を追加した。__doc__を argparse の description 等で消費するスクリプトのため、元の docstring は__doc__ = """..."""として保持している。回帰はtests/extras/ta-70-py-sh-misinvocation-guard.sh。PR #1175 の適用範囲はscripts/直下 27 本のみだったが、PR #1187 でscripts/ai-loop/30 本と配布ミラーplugin/plangate/skills/ai-loop-cycle/scripts/30 本へ拡張し、3 群すべてを適用済みにした(実測:git grep -l PG-SH-GUARD 375c791 -- 'scripts/*.py'= 57 = 直下 27 + ai-loop 30、同-- 'plugin/plangate/skills/ai-loop-cycle/scripts/*.py'= 30。母数はgit ls-treeで同数)。scripts/ai-loop/を残したままにできなかった理由は「⚠️ 更新前に必ずお読みください」3. のとおりgh pr merge/gh pr review --approveへ実際に到達していたため。ta-70も 3 群走査へ拡張し、glob が丸ごと空振りした状態で緑になる false green をGLOB-EMPTY検出で機械検査するようにした(件数は契約値にしない)。follow-up issue #1177 / #1178 はタグ時点で OPEN のまま(実体は本リリースで解消済みだが、close 判断は未実施)- plugin 配布 allowlist を
scripts/ai-loop/の実体と照合するようにし、配布漏れ 2 件を是正(#1173 / PR #1185)—ta-57の TC-E8 はsync-plugin-plangate.shの for 側 / case 側の相互一致しか見ていなかったため、両方に載っていないファイルは検査をすり抜け、plugin 導入先だけ壊れるのに CI は緑になっていた。TC-E9 を追加して allowlist をscripts/ai-loop/*.pyの実体と突き合わせ、UNDECLARED/REASON_MISSING/STALE_IN_ALLOWLIST/STALE_MISSINGを FAIL にする(総件数は契約にせず集合差分のみで判定 / #1162)。非配布は<basename> reason: <#NNNN を含む理由>の明示宣言でのみ許容し、CI 層では該当 issue が OPEN であることを要求する。実測された配布漏れdiscovery.py/test_discovery.pyを allowlist に追加した(同梱のtest_check_exec_boundary.pyが両ファイルを実読みするため、導入先で 2 件がFileNotFoundErrorになっていた) - クラス A(
rules/*.md参照)の解決梯子を ai-loop 正本 5 本と plugin 生成物へ追加(#954 / PR #1184)— PR #1164 が 4 skill に対して行った是正の取り残し分。docs/workflows/ai-loop/+docs/ai/ai-loop/の 5 本と、その sync 生成物であるplugin/plangate/skills/ai-loop-cycle/references/5 本(scripts/_ai_loop_link_rewrite.pyと同じ変換を適用し、sync 後も一致することを機械照合済み)
Changed
- plugin ドキュメントの絶対件数を再現コマンド + 集合スナップショットへ置換(#863 / PR #1182・#1183)—
plugin/plangate/README.mdの CLI 依存節と Contents 節が、運用で増減するディレクトリの件数を固定値で書いていたため、無関係な PR で陳腐化していた。件数は契約値にせず、再現コマンドを正・件数は測定日つきスナップショットとして扱う形に変えた mode-classification.mdの Hardening Override 参照を行番号アンカーから記号アンカーへ(#1089)—check-plan-hash.shの_override=0直後のcaseブロックを指す形に変更。行番号アンカーは実装の移動で黙って別ブロックを指すため- hook 配線の前提(
jq/sed)を導入導線へ明記(#1079 / PR #1099) - EH-3 の HO 注記を退役し、no-task 経路の正規手順を明文化(#1095 / #1089 / PR #1100)
- ファイル書き込みガードが
Edit|Writematcher 限定である事実を明記(PR #1106) chore(deps): github-actions group 4 件の更新(PR #1113)
Notes
- 本リリースには 適用が Human-owned の patch 設計 docs が多数含まれる(#937 / #960 HO 分 / #984 / #990 / #997 / #1011 / #1018 / #1021 / #1101 / #1102 / #1104 / #1135 / #1144 など)。これらは 設計と patch の提示のみで、適用は含まれない(適用は
sh scripts/apply-*.sh --apply相当の Human オペレーション)。hook / 承認境界ガード本体への適用は EH-3(#1089)と EH-13(#1115 / #1110)の 2 件のみで、それ以外の実行系変更は検査スクリプト側(#1109 のcheck-codex-skill-spec.sh/ #1087・#1153 のcheck-skill-name-collisions.py・check-stale-skill-refs.py)、sh誤起動ガード(#1169 / PR #1175 =scripts/直下 27 本、PR #1187 =scripts/ai-loop/30 本 + 配布ミラー 30 本)、plugin 配布 allowlist の実体照合(#1173 / PR #1185)、および CI actions の bump(#1113) .codex/skillsと.agents/skillsの二重 root 登録(#1086 / PR #1112)は調査と是正案の提示までで、実装は #956 の判断待ち- improvement-seeds の読み出し導線(#1157 / PR #1161)は patch 設計書のみ(
docs/working/_reports/1157-seeds-read-path-patch.md)。適用は含まない sh誤起動問題(#1169)の patch 設計書(PR #1176 /docs/working/_reports/1169-sh-invocation-patch.md)も同梱している(設計書自体はscripts/**/*.py全 59 件を実測して 45 件を影響ありと分類したもの)。実装は PR #1175(scripts/直下 27 本)と PR #1187(scripts/ai-loop/30 本 + 配布ミラー 30 本)の 2 段で本リリースに入っている- open bug 40 件の棚卸し(PR #1181 /
docs/working/_reports/bug-backlog-triage-2026-08-20.md)—origin/main実体に対して全件を再実測した結果 RESOLVED は 0 件で、滞留の実体は「修正済みだが適用が Human-owned で待ちになっている」ものだった。調査記録のみで挙動変更は含まない AGENT_LEARNINGS.mdに測定時の ref 明示(共有 checkout は stale になりうる)と extras 判定パターンのスイート別導出を追記(PR #1186)- 本リリース準備そのものの追従 PR: #1179(1 つ前の基点への追従)と #1188(
.claude/→plugin/plangate/の自動同期。#1185 が追加したdiscovery.py/test_discovery.pyへ #1187 のガードを反映) - skill 参照解決順の機械ゲートの検出器設計書(#1163 / PR #1172、
docs/working/_reports/1163-ref-resolution-ci-design.md)も 設計のみで、CI 配線は含まない