# 変更履歴

このプロジェクトの重要な変更はすべてこのファイルに記録されます。

形式は [Keep a Changelog](https://keepachangelog.com/ja/1.1.0/) に従い、
このプロジェクトは [Semantic Versioning](https://semver.org/spec/v2.0.0.html) に準拠します。

> 注: 2.4.1 から 5.1.2 までは英語版 `CHANGELOG.md` のみに記録されています（ja 版は追随済みではない）。

## [5.4.0] - 2026-10-30

- 認証情報ファミリーの階段：組み込み7ファミリー（ssh / cloud / package / gitcreds / env / cli / db）、各種類4段 deny / ask（既定）/ readonly / readwrite。段の状態はルール文書自体に保持（`[deny-rule:cred.<family>]` 行 + 対になる `credWriteExemptFamilies` リスト）。設定カードは `GET/POST /api/dsh-perm-gate/cred` 経由で両ストアを単一 update で対書き込みし、ローカルミラーを持たない。readwrite はインライン確認を要求し、P0 の一条（credential-store 書き込み）のみ退く；ルートディスク・保護パス・.dsh・外部送信はどの段でも動かさない。
- エンジン：`decide()` は READ ツールに対し規則層へ先行照会（名指し命中のみ ask/deny へ；不命中は従来の無音自動通過で確認画面の予算不変）。INTERNAL 調整ツールは先行照会しない。純モジュール `src/cred-families.ts`（族 glob + `familyOfPath`）追加。
- シード注入：プリセット表 52→59 行；水位キー `presetRulesVersion` でアップグレード後は新規行のみ補完（id 単位幂等、取り消した行は復活しない）。保護ブランチ force push 解除スイッチ `allowProtectedBranchPush`（既定オフ＝床維持）とプリセット行 `[deny-rule:rsync.delete]` を追加。

## [5.3.1] - 2026-10-17

### 追加

- **ホスト対応: DSH `0.2.1-rc.1`。** サポートホストの列挙（`package.json` engines.dsh、`dsh.plugin.json`、すべての `@deepseek-ai/dsh*` peer、README の管理ブロック）に `0.2.1-rc.1` を追加（区間表記なしの rc ごとの正確な列挙）。挙動は変更なし：宣言面のリリースであり、0.2.1-alpha.4 以降 engines.dsh のみを参照するホストゲートが 0.2.1-rc.1 ホストで本プラグインを許可します。

### 変更

- `publishConfig.registry` を `https://registry.npmjs.org` に固定（リリース衛生：公開先がミラー registry に漂移しない）。

## [5.3.0] - 2026-10-17

### 追加

- **YOLO ティア**（`yolo` — `permissive-yolo` を担当）: 人手確認を一切要求しない。危険な ask（不可逆・学習不能・解読不能なペイロード、またはレビューモデルの重リスク判定）は遮断し、理由を `工具审核意见` メッセージでメイン LLM に返す。それ以外は実行する。モデルが不在・無回答の時も人には聞かず、機械スクリーニングで処理した上で `yolo-allow-no-reviewer` に記録する（下記）。
- **縮退レビュー**（`rulesFallback`）: レビューモデル未設定、または判定が返らなかったときに、誰も答えない確認画面で処理を止めず決定論的ネットだけで裁定する。モデルが応答している間は挙動不変。通常の自動審査ティア（`permissive` / `permissive-full`）向けの項目で、実装を専有する 3 ティアは答える側を既に明示しているため縮退させない。
- **スクリプトレビュー**（`scriptReview`、既定オン）: 呼び出しが実行するスクリプトの本文を読み（有界・非実行）、レビューモデル・人・決定論的ネットの三者に同じコードを見せる。ファイル名だけでは見えない削除がコードで判定される。全文を読み取れたら「解読不能」ティアを抜ける。オフにするとファイル内容は本機から出ないが、ワークスペース外スクリプトは U ティアに戻る。
- **ユーザー申告型の保護**（いずれも追記専用・即時反映）: `credentialPaths`（`.ssh` と同格——ワークスペース外からの読み取りとファイルツールによる書き換えを拒否）、`denyKeywordsExtra`（プリセットを置き換えず追記）、`extraContentArgKeys` / `extraOperationArgKeys`（どの引数が文書で、どれが操作かを内蔵表に加えて宣言）。
- **3つの無人確認実装 — スイッチ1つ・権限ティア1つずつ**：`safenetAsk`（`permissive-snet`）は決定論的な機械スクリーニングで危険を絞った上で**依然として人に聞く**。レビューモデルは一切呼ばない — 審査 LLM 未接続時、またはトークンを費やさず人に裁かせたい時の形。`safenetPass`（`permissive-mech`）は同じスクリーニングで **ask を引き取る**：名指しした危険は遮断して主モデルへ返し、特定できないものは実行する。人確認なし・モデル呼び出しなし — `approval: never` の審査付き版。`yolo`（`permissive-yolo`）はモデル付きのティアで、人が答えるべき問いにモデルが代答し、人へは絶対に格上げしない。要点は対応関係そのもの：スイッチは脇に書いたティアの挙動だけを変え、実装をオフにするとそのティアは別ティアに化けず通常の人確認へ戻る。五ティアはいずれも**プラグイン同梱**の profile patch で配布されるため、インストール直後からピッカーにあり手編集は不要（`permissive` 自体は不変）。なお 2 リビジョンだけ存在した per-preset テーブル（`<preset>=<mode>`）は退役 — この三つのスイッチと二重になり、一つの姿勢に二つの制御があれば一方は必ず嘘をつく。
- **YOLO は得ていない審査者を名乗らない**：レビューモデル未設定、または `unresolved` を返した場合、ティアは依然として人に聞かず機械スクリーニングで処理する。ただし記録は `yolo-allow-no-reviewer` となり理由にもそう書かれる — ラベル無しのフォールバックでは、モデルが居ない時だけ YOLO と機械ティアが承認履歴で区別できなくなるため。
- **全ティア共通の下層機械審査**：決定論的判定（不可逆／学習不能／読めない）が YOLO・降格ゲート・新規 passthrough の三箇所に手書きで重複していた。単一の `mechanicalJudge` に統合し、ティアが変わるのは「残りを誰が決めるか」だけで、「何を危険と数えるか」は変わらない。テストで固定：同じ呼び出しは YOLO でも passthrough でも遮断され、どちらもモデル呼び出しを消費しない。
- 設定カードの boolean 項目は**楽観式ピルスイッチ**になった（36×20 カプセル、状態は `aria-checked` が単一源泉、テーマトークン＋フォールバックで明暗両対応）。無人確認の各行は自分が制御するティア名も併記する。いずれもクリックで即反転し、書き込みの確定・拒否・未報告で表示権をストアへ返す。
- 承認履歴が素のタグで出していた判断経路にラベルを付与：`yolo-allow` / `yolo-block`、`rules-fallback-*`、`safety-net-passthrough-*`、および以前から未翻訳だった四つ（`cleanup-safe`、`escalation-auto`、`learned-granted`、`network-ask`）。
- プロファイルおよび保護された Windows ルートを**変数や glob 経由**で削除する処理の決定論ネット（`$HOME`、`~/.*`、`$env:USERPROFILE\.*`、`%WINDIR%`、`$PSHOME` など）: プロファイル根は即時拒否、他の保護ルートは「消せない永遠の ask」になる。9B レビューアでは知識注入型プロンプトでも実測で漏れたため、コード層に置いている。

### 修正

- issue #2: 文書系ツールの本文を操作として読まなくなった。共有ルール `src/scan-text.ts` がツールの区分で可読キーを決める（read / internal / write は command・url・path・query のみ。未知のツール名は引き続き実行型として全読）。`exit_plan_mode` は実行する予定のステップを正直に書けるようになり、モデルが計画文言を言い換えてゲートを抜ける状況を防ぐ。
- 同報告の付随項: 引用符外の改行、および空白なしで詰めた `;` `|` `&&` `||` を文区切りとして `decomposeShellCommand` が見るようになり、複数行コマンドの第 2 文がルールに到達する。単独の `&` は切らず、`2>&1` とバックグラウンド実行の形を守る。
- issue #3: デフォルト安全スクリーンによる格上げは自分の理由を名乗る（`write target outside the workspace (…)` / `command carries a file-write or redirect pattern`）。`no rule matched` の偽装はやめ、モデル自身の文も確認・拒否文言に載る（改行除去・角括弧除去・マスク処理・180 字上限で、`[deny-rule:…]` の偽造を防止）。
- issue #4: `=>` と `->` をファイルへのリダイレクトと誤認しなくなった。
- `write` / `edit` による資格情報ストアの変更（`~/.ssh/authorized_keys`、`.git-credentials`、`.npmrc`、クラウド資格情報）を P0 で拒否。従来は削除しか守っておらず、自動許可される書き込みでアクセス権を埋め込めた。
- 鍵組の公開側（`id_ed25519.pub`）は引数全体の資格情報スクリーンに掛からなくなった（手で鍵を復元する運用が不服申立て不能だった）。
- `deny-keyword` の監査文言から、ユーザーが追記した項目に対する "preset" 表記を除去。

### 既知のギャップ

- `pathArgument` は `file_path` / `path` / `cwd` / `workdir` のみ参照し、複数形フィールド（`paths`・`files`・`urls`）は資格情報パス基準の外。
- 渡された文書を実行するツール（`workflow`・`skill`・`ralph`）の本文はフラットなスクリーンでは読まない。委譲先の作業は独立したツール呼び出しとして審査される。

## [5.2.0] - 2026-10-14

### 追加

- `src/preset-rules.ts`: cc-safety-net から移植した 51 件の `[deny-rule:*]`（MIT。帰属は `THIRD_PARTY_NOTICES.md`）。`mergePresetIntoRaw()` は `deny`/`ask` の末尾に追記し、id 単位で冪等、ユーザーが取り消した行を再投入しない。新しい volatile キー `presetRulesSeeded` を有効化時に一度だけ記録。
- `argv.pipeline` を連結文字列だけでなく個々の単純コマンドでも評価する（プリセット命中率がそれに依存）。ルール判定は `deny-rule:<id>` で帰属。

### 修正

- シードが `apply` の同期本文内で走っており、当時 settings サービスがまだマウントされていないため、どのホストでも黙って一度も適用されていなかった。inject コールバック内、各世代が名前空間を登録した後に移動（0.1.5 では `installSection` 前の書き込みが例外を投げる）。
- ルールと冪等フラグを 2 つの `update` に分けていたため、rc.1+ では 2 つ目が `Plugin entry "dsh-perm-gate" is no longer configurable` で落ち、フラグが永遠に立たず、ユーザーが全削除したはずの表が無限に再シードされていた。現在は 1 回の更新で、ルールの成功後にフラグを書く。
- `rawEntry()` が `params` 次元に**コンパイル済み**の `ParamCondition[]` を出していたため、シード後の文書が次回起動時に本プラグイン自身のリーダーで失敗し（`permissions.deny[22].params.params must be a mapping`）、perm-gate が起動しなくなった。mapping に戻し、`!glob` 否定接頭辞も復元。
- プラグイン自身の `perm-gate/rules.yml` へのフォールバックを廃止（作者判断 2026-10-14）: 手入れのルール源に 51 件の注入行を混ぜるべきではなく、その分岐は旧ホストでしか動かず、二つのホスト世代で挙動が食い違う。settings サービスが無い今はシードせず、ファイル書き込みには劣化させず明示的に報告。
- 3 件目を捕まえられた門を追加: `test/preset-rules-roundtrip.spec.ts` がマージ済み文書をリーダーとコンパイラに再通過させる。ネガティブコントロール（修正 3 を戻すと 5 件中 3 件が失敗）も確認済み。

## [5.1.0] - 2026-10-05

### 変更

- 15-rc 列挙線を統一: 三つのホストサブパッケージ（`client-locale`・`client-ui-renderer`・`client-ui-settings`）の peer を完全列挙し、内容は検証環境で確認済みの `4.3.0-beta.2` と同一ツリー、バージョンは compat 線の `5.0.4` を超える。

## [2.4.1] - 2026-09-17

### 修正

- 承認履歴が、フラグ付きの呼び出しがなぜレビューされずに実行されたのかを説明する唯一のイベントについて、生の `preset-passthrough` 文字列を表示していました（ティアは `approval: ask` を宣言しているのに、セッションが `never` で上書きされ、ゲートの ask がパススルーに降格したためです）。他の判定と同じく読みやすいラベルで表示されるようになりました。

## [2.4.0] - 2026-09-17

### 変更

- **P3 LLM 分類器はエスカレート専用になり、拒否できなくなりました。** ハードカテゴリ
  (`deletion` / `credential` / `remote` / `system` / `bulk`) の `risky` 判定はこれまでパネルなしで
  **自動拒否**していましたが、現在は**人間への確認（ask）を維持**します。拒否は決定論的レイヤー
  （P0 ハード拒否、拒否キーワードのブラックリスト、明示的な `deny:` ルール）だけに属します。
  確率的な判定が、異議を唱えられないブロックを下してはならないからです。実測: グレーダーは無害な
  `git commit -F …` を **`remote`** と判定し、自動拒否は承認するパネルも再試行する grant も残しませんでした
  （たまたま `safe` と判定された手動リトライだけが通りました）。これは「高リスク操作は**決定論的に**
  遮断し、LLM の判断には委ねない」というプロジェクト自身のルールとも整合します。

### 追加

- ハードリスクカテゴリは `neutral` との重要な違いを一つだけ保ちます: **決して学習されません**。
  人間の承認を繰り返しても `deletion`/`credential`/`remote`/`system`/`bulk` の判定が自動許可に
  沈殿することはありません（従来は自動拒否の副作用としてのみ成立していましたが、現在は明示的な性質です）。

### 動作上の注意

- `approval: never` では、ゲートが配信できない ask は従来どおりパススルーに降格するため、分類器が
  フラグを立てた呼び出しは**実行されます**（以前は自動拒否でした）。これは「決定論的に危険なものだけを
  拒否し、それ以外は交渉する」の直接の帰結です —— 交渉には人間が必要で、`never` は人間がいないことを
  意味します。フラグを実際に受け取りたい場合は `approval` が `ask` のティアで運用してください。

## [2.3.0] - 2026-09-17

### 追加

- **ゲートの停止はもはや沈黙しません。** セッションの権限プリセットが `gatePresets` の外にあるとき、
  ゲートは停止して何も記録しませんでした —— そのためツール呼び出しは、ゲートが検査して許可した
  呼び出しと見分けがつきませんでした。現在は (session, preset) の遷移ごとに **1 件だけ**
  `stand-down` 通知を記録し（呼び出しごとではありません）、プリセット・スコープ・P0 ハード拒否が
  無効である事実を明示します。ブラウザは入力欄の上に常駐の **GATE OFF** ストリップとして表示し、
  承認履歴には `ゲート停止` タグが出ます。
- 自动审查 設定カードがゲート自身のプリセットスコープ（`gatePresets`、既定は
  `permissive` / `permissive-full`）とその外側で何が起きるかを明示するため、スコープはティアを
  設定する場所で確認できます。

### 変更

- **P0 の文書上の位置づけはグローバルではなくスコープ付きです。** P0 ハード拒否は*ゲートのプリセット
  スコープ内*で単調かつ交渉不能です。プリセットをまたぐとゲートは P0 を含めて完全に停止します ——
  選択されたティア自身のポリシーがそのセッションを所有するためです。コードは常にこう動作していましたが、
  `AGENTS.md` と 4 つの README は逆を主張しており、`danger-full-access` が「P0 は依然適用される」と
  読めてしまいました。`gatePresets: ['*']` を設定すると P0 は再びグローバルになります。

### 修正

- `DEFAULT_GATE_PRESETS` / `resolveGatePresets` を `config.ts`（schemastery を import しています）から
  依存のない `preset.ts` へ移し、ブラウザ側が node 専用依存をクライアントバンドルに引き込まずに
  スコープを描画できるようにしました。`config.ts` は両方を再エクスポートするため、既存の import は
  変更ありません。

## [2.2.0] - 2026-09-17

### 修正

- **P0 ハード拒否が、4 つのシェルツール以外をすべて素通りさせていました。** `hardDenyReason` はシェル検査をローカルの正規表現 `/^(?:bash|pwsh|sh|cmd)$/` で門番していましたが、これは `shell` / `terminal` / `powershell` に**一致しません**。`shell` は DSH の主要シェルツールであるため、P0 のシェル検査（保護パスへのリダイレクト）は**最も一般的な呼び出し形に対して無効**でした。実測、同一コマンド `echo x > /etc/passwd`：`bash` 経由は遮断、`shell` 経由は**通過**。`engine.ts` は `evaluate.ts` から `SHELL_TOOLS` を取り込むよう変更しました——同じ事実の複製が 3 か所にあり、完全だったのは 1 つだけでした。
- **`git push --delete` が通常の push として解析されていました。** `hasDelete` は `analyzeSubcommand` で計算されながら `branch` ケースでしか読まれず、`git push --delete origin main` は通常 push 分岐（`destructiveness: 4`）に落ちていました。`DESTRUCTIVENESS_MAP` の `'push-delete': 5` は死んだデータでした。
- **保護ブランチ判定が、スラッシュを含む名前に誤反応していました。** 述語は最後の `/` より前を落としていたため、`backup/main` や `feat/release` が保護扱いになっていました。既知の ref 接頭辞（`refs/heads/`、`refs/tags/`、`refs/remotes/<remote>/`）のみを剥がすよう変更しました。方向が重要です——この述語は**取り消し不能な** P0 に供給され、見逃しにはキーワード／ルール／LLM 層という受け皿がありますが、誤検出は正当なワークフローを出口なく塞いでしまいます。

### 追加

- **保護ブランチに対するリモート履歴改変の P0 ハード拒否。** `main` / `master` / `production` / `release` / `stable` を強制上書きまたは削除する `git push` を、LLM 呼び出しより前に決定的に拒否します。従来の保護は、フラットでブランチを見ず、名前空間で上書き可能なキーワード `'push --force'` でした。これはその下に敷く交渉不能な床です。
  - **「エスカレーションのみ」は慣習ではなく構造です**: ヘルパーは `string | undefined` を返し、呼び出し側はそれを deny / 未決定として読みます。allow を表現する手段がないため、P0 に配線してもゲートが許可する範囲を広げることはできません。
  - 意図的に**対象外**（引き続きキーワード／ルール／LLM 層が担当）: 非保護ブランチへの force push、ブランチ名を書かない `git push --force`、通常の push。
  - コマンドパーサ（`command-dispatcher` / `command-semantics` / `parsers/git` / `parsers/shell-cmds`）の初の本番利用です。これまで自身のテストファイルからしか参照されていませんでした。

### テスト

- 新規 `test/git-protected-push.spec.ts`（13 件）。
- **反証**: 3 つの修正をそれぞれ戻すと、それを守るケースだけが赤くなります（計 7 件）。意図的に許可するケースは緑のままです。
- 全量 **40 ファイル / 459 件**、`typecheck` クリーン。

## [2.0.0] - 2026-09-11

### 修正

- **DSH 0.1.2 ではゲートが全呼び出しで待機状態になり、「承認記録」ページが空のままでした。** セッションの
  権限プリセット fold はログを `exec.agent.session.events` として読んでいました。DSH 0.1.1 はこの配列を
  公開していましたが、0.1.2 はログを `Session.snapshotEvents()` / `ownEvents()` の背後に隠し `events`
  メンバーを残していないため、読み取りは `undefined` を返し、`presetOf` も `undefined` を返し、
  `presetInScope(undefined, ['permissive'])` によって `gateActive` が**すべての**呼び出しで false に
  なりました —— ルール / grant / 拒否キーワード / 分類器 / P0 ハード拒否のいずれの判定も行われず、監査
  イベントも記録されません（ゲート自身のティアを選択したセッションでも同様で、タブには失敗ではなく
  「本セッションにはまだ承認記録がありません」と表示されていました）。fold は既知のすべてのアクセサ形状
  （`events` 配列、`snapshotEvents()`、`ownEvents()`）でログを読み、ホストが何も公開しない場合にのみ
  「イベントなし」に縮退します。fold キャッシュはログ長と末尾イベントの同一性をキーにします（0.1.2 の
  スナップショットは同じ凍結イベントに対する毎回新しい配列のため）。`test/preset-scope.spec.ts` が両形状を
  固定します。

### 変更

- **`main` ラインのバージョン系列を `2.x` に変更し、対応する DSH ラインを表すようにしました。**
  `1.x` は DSH `<= 0.1.1` ライン、`2.x` は DSH `0.1.2+` ラインであり、プラグインのバージョンが
  どの DSH 向けかを示します。`2.0.0` が新系列の最初のリリースで、`0.2.x`
  （`0.2.0`、`0.2.1-beta.2`…`beta.5`）はこれに置き換わります。メジャー同士は互いを遮断するため
  （`^1.0.0` は `2.0.0` を解決せず、`^2.0.0` は `1.0.0` を解決しません）、既存の
  `^0.2.1-beta.4` インストール（これも `2.0.0` を解決しません）は明示的に更新する必要があります。
  `engines.dsh` も同じ分界を述べています（こちらは `>=0.1.2-alpha.1 <0.2.0-0`、`legacy` は
  `>=0.1.0-rc.7 <0.1.2-alpha.1`）が、DSH は決して読まないため、古い DSH を `1.x` に留めるのは
  バージョン範囲と dist-tag です。
- **権限ティアの表示名を全サーフェスで「自动审查」に統一し、アイコンを廃止しました。**
  `cordis.patch.yml` の preset `name:` が中国語の製品名になり、一般設定の既定行・入力欄のピッカー・
  プラグイン設定タブのすべてで同じ表示になります。DSH 0.1.2 はプラグイン提供ティアの `name:` をそのまま
  描画し、ローカライズするのは組み込み 3 値（`仅可查看` / `工作区内修改` / `完全权限`）だけなので、zh
  セッションが見るのはこの 1 つの文字列です。マシン値は `permissive` のままです（`gatePresets` が照合
  する値）。権限ピッカーのアイコン装飾は削除しました（`src/client/permission-icon.ts` を削除）：退役した
  `auto` ティアの盾グリフに合わせるためのもので、0.1.2 では `aria-haspopup="menu"` セレクタ経由で設定行にも
  適用され、ピッカーのグリフは組み込み値にのみ紐づくためプラグイン ティアは描画しません。

## [0.2.1-beta.4] - 2026-09-11

### 追加

- Permissive ティアに `trustEscalation` 戦略を追加（ティア有効時に既定オン）：ゲートがすでに許可した呼び出しの
  サンドボックス昇格承認をここで `allowed-once` と回答し、プロンプトを出さなくする。昇格は shell / pwsh / edit
  ツールの内部 — `tools/pre-execute` の決着後 — から発生するため、ゲート自身の allow はそこに届かず、
  LLM が `safe` と判定した呼び出しでも広げの確認を求めていた。ゲートが許可した呼び出しのみ
  （`callId` とツール名で一致）がプロンプトをスキップし、`workspace-write` / `danger-full-access` を
  命名する認識された昇格原因のみ適用。それ以外は変更なく人手へ委譲。自動回答はイベントフィードに記録
  （`verdict: "escalation-auto"`、`mode: <ターゲット>`）。スイッチをオフにすると広げは人手ゲート化。

### 修正

- 設定カードがルール ファイルから編集可能なホワイトリストをシードするようになりました。
  `installSettingsSection` はホスト設定スコープで `scope.set('allowlist', …)` を呼んでいましたが、
  ホスト スコープは `get` / `watch` / `update` / `replace` だけ expose —
  `set(field, value)` は *クライアント* の `mutate()` 用 convenience ラッパーで異なるオブジェクトなので、
  呼び出しが投げて名前空間がシードされませんでした。
  今度は `scope.update({ allowlist: … })` を使います。
- `approval/request` リスナーが `prepend` で登録され、パッシブ オブザーバから回答ゲートになり、
  ブラウザ プロンプトを描画するリモート ブリッジの前に位置するようになりました。
  そのブリッジの後ろにリスナーがあれば、すでに示されたプロンプトしか記録できませんでした。

## [0.2.1-beta.3] - 2026-09-10

### 追加

- リスク判定 `llmAssist`：設定されたカスタム LLM（OpenAI 互換エンドポイント）が各 `ask` を
  `safe` / `risky:<カテゴリ>` で判定。ハードカテゴリ（deletion / credential / remote / system /
  bulk）は自動拒否、タイムアウトは 1 回リトライ、失敗は常に fail-closed。
- 裁決学習（`riskLearning`、既定オフ、`riskThreshold` 1–10、既定 3）：人手で承認され実際に実行された
  neutral リスクをカウントし、指紋一致する同一操作のみ自動許可。`$DSH_HOME/perm-gate/learning.json`
  に永続化され、ユーザーの YAML ルールには書き込みません。
- 決定イベントフィード：各決定を `$DSH_HOME/perm-gate/events.jsonl` に追記し、
  `GET /api/dsh-perm-gate/events?sessionId=&since=` で提供。ブラウザ側は入力欄上の通知バーで表示。
- 権限ピッカーの盾アイコンが折りたたみトリガーにも表示されます。
- 承認記録ページ：会話ビューに「承認記録」タブを追加し、セッション内のゲート判定を新しい順に
  タイムライン表示（種類タグ・リスクカテゴリ・時刻付き）。設定カードの許可リストは行ごとに削除できる
  編集可能なリスト＋一括編集トグルになりました。
- dsh-approval-gate から継承したプリセット拒否キーワード（`DEFAULT_DENY_KEYWORDS`）：キーワード一致
  （大小文字を区別しない部分一致）で許可リスト / 許可 / LLM より先に拒否。設定カードでリスト編集でき
  プリセットタグとワンクリック復元に対応、未設定・空ならプリセットを適用（黑名単は常に有効）。
- 学習沈殿（`riskSediment`、既定オン）：しきい値に達したキーの確認サンプルが決定論的な自動許可ルールに——
  指紋の正確一致は LLM 呼び出しをスキップし、llmAssist オフでも継続。設定カードで一覧表示し、キー終止・
  サンプル削除が可能（`GET/POST /api/dsh-perm-gate/learning`）。
- 選択可能な llmAssist 受信先：**カスタム API**（OpenAI 互換、Xiaomi MiMo
  `https://api.xiaomimimo.com/v1` を含むプリセット付き）または **DSH ホストモデルグループ**
  （`llm` サービス + `agentDefaultModel.currentSelection`、provider/model 上書き可）に加え、
  **健全性テスト**ボタン（`POST /api/dsh-perm-gate/health`）で最小 completion の応答とレイテンシを確認。設定カードは
  `GET /api/dsh-perm-gate/receiver` 経由でライブのプロバイダー/モデルグループ一覧（ホスト
  `llm.listProviders`/`listModels`、カスタムグループ含む）を取得し、実効的な選択を表示します。
- **承認記録のレビュー面**：各決定が触れたファイルは変更前にスナップショットされ（≤5 ファイル、
  各 ≤256 KB、`$DSH_HOME/perm-gate/snapshots/`）、**承認記録**タブでファイルチップから行 diff
  （`GET /api/dsh-perm-gate/diff`）を開き、**取り消し**（`POST /api/dsh-perm-gate/revert`）で会話に
  復元指示を送信できます。スナップショット管理バー（`GET /api/dsh-perm-gate/snapshots-stats` /
  `POST /api/dsh-perm-gate/snapshots-clear`、セッション単位または全件）も追加。イベント行は
  `files` / `justification` / `verdict` / `category` を持つようになりました。
- **人手承認の終態記録**：人手に回した `ask` を追跡し、受動的な `approval/request` オブザーバで
  実際の回答を記録します — `allowed-once` → 承認、`rejected` → 拒否、`cancelled` → キャンセル、
  `unavailable` → 拒否（承認チャネルなし）。オブザーバが関連付けできない場合（`callId` 欠落、
  approval サービスなし、上流リスナーの短絡）は `tools/result` がフォールバックとして同じ ask を
  解決します（「解決時に削除」が唯一の重複排除ルール）。承認時には承認後の学習進捗（`n`/しきい値）を
  表示し、通知バーは 3 つの終態をラベル表示します。

### 削除

- 廃止された **Auto** 権限ティアを `cordis.patch.yml` に再記載しなくなりました。DSH の bundle
  patch は `permission.config.presets` マップ全体を**置換**するため、このファイルは残すべき
  ティアをすべて記載する必要があり、`dsh-auto-mode` が提供していた `auto` も含まれていました。
  同プラグインはアンインストール済みで、ノブは `workspace-write` と同一、説明文の
  「自動レビュー / ワンショット承認」は実装ごと失われ、さらにこのゲートはそのティアでは
  動作しません（`gatePresets` の既定は `['permissive']`）。ピッカーは組み込み 3 ティア
  （`read-only` / `workspace-write` / `danger-full-access`、`@deepseek-ai/dsh-base/cordis.patch.yml`
  から再記載）と本プラグインの `permissive` のみを提示します。
- `test/patch-presets.spec.ts` がこのキー集合を固定し、組み込みティアの脱落や廃止ティアの
  復活があればテストが失敗します。

### 変更

- ゲートは **`gatePresets` に列挙したティアでのみ動作**します（既定 `['permissive']`、
  このプラグインが追加するティア）。それ以外のティア（Read Only / Workspace Write / Auto /
  Full access / `custom`）では判定フローは一切実行されません——許可・ask・拒否・P0 ハード拒否・
  拒否キーワード遮断・監査イベントのいずれも行いません。`gatePresets: ['*']` で再び全体
  （ハード拒否を含む）に適用できます。
- `llmAssist` はリスクカテゴリプロトコルを使用（従来の allow/deny/ask 判定のスーパーセット）。
  `classifier.ts` はリスク判定器と OpenAI 互換トランスポート（`chatCompletion`）を共有します。
  ハードリスクカテゴリ（`deletion` / `credential` / `remote` / `system` / `bulk`）は
  **自動拒否**に変更（人手に渡すのではなく、明らかに危険な操作は確認不要）；`risky:neutral`
  （不確実）のみ人手に渡ります。
- `write` / `edit` に**パス感知のデフォルト**が追加され、ワークスペース内の書き込みは
  `defaultAction`（通常 `allow`）に従い、ワークスペース外への書き込みはコンテンツ審査のため
  `ask` に昇格。LLM 分類器が安全コンテンツを自動許可、有害コンテンツを自動拒否できるため、
  不確実な操作のみポップアップが発生します。

### 修正

- **`llmAssist` の `safe` は記録されるだけで、実際には自動許可されていませんでした。**
  `tools/pre-execute` リスナーは `ask` を即座に返してバックグラウンドで判定していましたが、ホストへ
  渡した ask はすでに承認 answerer へ向かっており、DSH にはそれを取り消す API がありません
  （リクエストの `signal` ができるのは `cancelled` での決着だけです）。そのためパネルは表示され続け、
  フィードには `safe` の自動許可が出ているのに人手でのクリックが必須でした — さらにハードリスクの
  `auto-deny` はホストにまったく届いていませんでした。リスナーは決定を返す**前に** `refineAsk` を
  await するようになり（`makePreExecuteListener`）、`safe` は `next()` で委譲されパネルは出ず、
  ハードカテゴリは自動拒否、`risky:neutral` / `unresolved` / 判定失敗のみが人手の ask を維持します
  （fail-closed）。待機時間は `riskTimeoutMs`（既定 20 秒）で上限が決まり、すでにキャンセルされた
  呼び出しは判定をスキップします。
- **ユーザーが選んだ権限ティアをゲートが上書きしていました。** ゲートは独立した承認ティアを
  持ちますが *すべての* プリセットで動作し、あらゆる越境が `ask` になって DSH 承認シームへ
  転送され、`danger-full-access`（`approval: never`）ではそのシームが **どの answerer よりも
  先に** `rejected` を返しました — パネルは一度も表示されず、read 専用以外のすべての呼び出しが
  誤解を招く `the user rejected tool "..."` で失敗しました。ハード拒否と拒否キーワード層も同様に
  ティアを無視していたため、`danger-full-access`（「承認プロンプトなしのフルアクセス」）が
  黙って狭められていました。ゲート全体が `gatePresets` に限定され、範囲外では何も行わず記録も
  しません。有効なティア内では、実効承認方針が `never` の場合 ask はパススルーに降格します。
- **読み取り専用の検索とセッション内ツールが ask になっていました。** `web_search` /
  `modlens_read_image` は読み取り専用クエリ、`todo_write` / `render_ui` / `validate_dsh_ui` /
  `ask_user_question` / `exit_plan_mode` / `ralph` / `workflow` はセッション内の状態または
  委譲でありながら自動許可の分類に含まれておらず、毎回 `ask`（`no rule matched; default action`
  のポップアップ）になっていました。これらを自動許可に追加し、第三者製の読み取り専用ツール向けに
  `autoAllowTools` 設定を新設しました。P0 ハード拒否と拒否キーワード層は先に実行されるため、
  このリストが権限を広げることはありません。
- **`write`/`edit` がワークスペース外のパスに静かに書き込んでいました。** `~/.bashrc` や
  別ドライブへの書き込みに `defaultAction`（通常 `allow`）が適用され、審査なしで実行されて
  いました。ルールが一致しない場合、`write`/`edit` ツールに対してパス感知のオーバーライドが
  適用され、ワークスペース内の書き込みは `defaultAction` に従い、ワークスペース外の書き込みは
  コンテンツ審査のために `ask` に昇格します。有害なコンテンツは拒否され、`llmAssist` が有効
  な場合は正常な追加が自動許可されます。`deny` ルールはパス範囲に関係なく勝ち、`allow` ルール
  は内部パスを許可できますが、外部パスの審査を回避することはできません。
- **P0 の資格情報検出が文書本文まで走査していました。** トークン・秘密鍵・`credentials.yaml` を
  単に *言及* したファイルの書き込み／編集までハード拒否されていました。操作自体を表す引数
  （`command` / `file_path` など）のみを走査するよう変更し、拒否キーワード層の「ファイルの
  テキストは操作そのものではない」という規則に揃えました。
- **`$DSH_HOME/perm-gate/rules.yml` が読み込まれませんでした。** `rulesFile` に既定値がなく、
  `config` を省略したプロファイルではルールセットが空＋`defaultAction: ask` になり、ユーザーの
  `defaultAction: allow` と `allow:` ルールは黙って無視されていました。`rulesFile` は
  `<dataDir>/rules.yml` を既定値とし、設定カードの許可リストもそこへ書き込みます。
- **`format` が PowerShell の `Format-Table` を拒否していました。** ハイフンはコマンド識別子の
  単語境界ではないため、キーワードの端を識別子文字（`[A-Za-z0-9_-]`）で判定するようにし、
  `format C: /q` は引き続き検出しつつ `Format-Table` / `mkfs.ext4` は正しく扱われます。
- 拒否キーワードのマッチングが、長い識別子の中に単に含まれるだけのキーワードを拒否しなくなり、
  文書本文の引数（`content` / `new_string` / `old_string` / `text` など）は走査対象外になりました
  — ファイルのテキストは操作そのものではありません。マッチングは単語境界を意識するようになり、
  句読点で終わるキーワードや CJK キーワードも引き続き機能し、空白は圧縮されるため余分な空白を含む
  コマンドも検出されます。

### Fixed

- **すべての読み取りクエリに手動承認が必要でした。** `read` / `read_image` / `grep` / `glob` / `ls` / `lsp`
  はワークスペース内のみの読み取り操作で、変更を加えることはできません。これらは自動許可されました。

### Added
- **Permissive モード（独立審批枠）** — read-only / workspace-write / full-access / whitelist と並ぶ独立モード。
  単一のフロントスイッチ（`permissive`）+ 組み合わせ可能なバックエンド戦略（`trustAutoAllow` / `alwaysConfirm` / `llmAssist`）。
  P0 ハード拒否は単調のまま。
- 監査に `classifier` / `permissive` の決定ソースを追加。`llmAssist` 用の注入可能な `classify` フック
  （`ask`/未指定時は fail-closed）。
- CLI に `--permissive` フラグと `--list` の permissive サマリを追加。
- **ブラウザ クライアント** — `settings.plugins.tab` ページ（「Permissive 承認ティア」）が
  設定 → プラグインに描画されます。1 つのスイッチ（`permissive`）＋ 3 つのバックエンド
  `permissiveStrategies` トグル。host は名前空間を live に読むため、再起動なしで次の
  ツール呼び出しから反映されます。
- **実際の llmAssist LLM** — 設定可能な OpenAI 互換分類器（`classifierEndpoint` /
  `classifierModel`）が `ask` の自動判定を行い、人手のシームへ fail-closed でフォールバック
  します。
- **ホワイトリスト移行** — `approveAllowEverywhere` はコマンド語をルール ファイルの
  `allow` に永続化して再読込し、`approveRepeat` は有界なセッション許可を発行します。
  いずれも always-confirm パネルの 2 つの拡張許可ボタンを裏で支えます。
- **4 言語インストール ガイド** — `INSTALL.md` / `INSTALL.zh.md` / `INSTALL.ja.md` /
  `INSTALL.ko.md`（インストール・アップグレード・分割プラグインからの移行・検証・
  トラブルシューティング）。全 README に言語切替リンク、`ja` / `ko` 互換性注記
  （公式 DSH の `LOCALE_IDS` は `["zh", "en"]`）、バージョン表記を追加。
- README.ja / README.ko を英語の正本と同等の内容に拡張（P0–P4 チェーン表、背景/機能、
  ルール ファイル形式、Permissive ティア、CLI）。

## [0.1.0] - 2026-08-30

### Added
- P0–P4 判定チェーン：ハード拒否 / セッション許可 / 静的な拒否優先ルール連鎖 / 任意の分類器（既定オフ）/ `ask`。
- 純関数ルールエンジン：glob/regex コンパイル＋ReDoS 上限、失敗時 loud-fail、コンテンツハッシュのコンパイルキャッシュ。
- argv 分解によるコマンドホワイト/ブラックリスト（`sh -c`/`bash -c` 再帰、パイプライン、リダイレクト、再帰/強制）。
- 正準フィンガープリントによる精密なセッション許可（TTL＋maxUses、対象が異なれば再利用不可）。
- `{ignorable:true}` 判定監査と、モデル可視⟺記録の不変条件。
- スタンドアロンの dry-run CLI 評価器（`dsh-perm-gate --rules … --tool … --args …`）。
- DSH cordis 関数プラグイン契約（`cordis.patch.yml`、Schemastery `Config`、exports/types）。
- 4 言語 README（en/zh/ja/ko）と Keep-a-Changelog 枠組み（en＋ja＋ko）。