Skip to content

v8.21.0 — 参照解決順の空振り段の除去 + EH-3 / EH-13 / sh 誤起動のガード迂回封鎖

Latest

Choose a tag to compare

@s977043 s977043 released this 20 Aug 02:10
· 101 commits to main since this release
684949e

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/*.jsonbin/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-cycle skill 同梱の
scripts/*.py が配布物に入るため)。NO MERGE BY AI(Iron Law)に直接関わる是正のため、
本リリースで最も重要な告知です。

  1. EH-3: Hardening Override の block が TASK 文脈でも発火するようになりました#1089 / PR #1097)。
    v8.20.0 で「既知の未解消ギャップ」として出荷した迂回(PLANGATE_HOOK_TASK を設定していると HO 判定が
    一度も評価されず、9 カテゴリすべてで rc=2rc=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 に残りますが、再実行は不要です)。

  2. 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.txtv2 列)。残存クラスと follow-up 候補は
    docs/working/TASK-1115/plan.md §残存クラス を参照してください。あわせてリダイレクト判定を「先と保護パスの相関」で行うようにし、
    コミットメッセージにパス名を書きつつ無関係な出力を /tmp へ流すだけのコマンドが block される
    誤検出(#1110)を解消しました。判定不能なケースは従来どおり block 側に倒します(fail-closed 不変)。

  3. 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 起動した実測で
    gh 12 回 + git 3 回が発火し、その中に gh pr merge / gh pr review --approve / gh pr close
    含まれていました
    gh_exec.py 単体で gh 6 回)。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 と出力を全数比較して確認済み)。
    更新後、これらの .pysh(または 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 1exit 2 fail-closed 化)で同型を minor と裁定した前例に揃えた。判定者・判定日・残る不整合と
follow-up は docs/working/_merge/v8.21.0-release-runbook.md §1 に記録した。

Added

  • diff-audit skill に検証観点を追加#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#1158PR #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-cycle skill と runbook / loopspec で明示(配布物を含む 3 root = .agents / .claude / plugin/plangatedocs/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_TASKplan.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-62 TC-D の timeout を誤診断せず切り分け#1062 / PR #1142)— 実行回数 7 回の実測調査つき
  • skill 名衝突検出のミラー判定に plugin 名と内容同一性を要求#1153 / PR #1174)— #1149 が入れたミラー除外は startswith("plugin:") しか見ていなかったため、consumer の .claude/skills/<name>第三者 pluginplugin/<other>/skills/<name> という真の名前衝突を「正常なミラー」として rc=0 で通していた。除外条件に (3) 自リポジトリの export 先 plugin 名であること(既定 plangate--mirror-plugin置換指定。判定不能なら衝突=安全側)と (5) 内容同一性(description 一致、または drift が構造的に説明できる skill kind のみ許容し、agent / command の drift は衝突)を追加した。回帰は tests/extras/ta-69-distribution-checks.sh の TC-C10〜C14。scripts/check-skill-name-collisions.pyplugin 配布物には含まれない
  • 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/ 直下の *.py 27 本すべての先頭に、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 #1187scripts/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.shfor 側 / 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|Write matcher 限定である事実を明記(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 件のみで、それ以外の実行系変更は検査スクリプト側(#1109check-codex-skill-spec.sh / #1087#1153check-skill-name-collisions.pycheck-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 #1175scripts/ 直下 27 本)と PR #1187scripts/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 #1172docs/working/_reports/1163-ref-resolution-ci-design.md)も 設計のみで、CI 配線は含まない