Amazon Q for IntelliJ IDEA を拡張した記録 (通称:尊師モード)
この記事の位置づけ
本記事は Amazon Q Plugin の承認フローの仕組みを理解し、ローカル環境で挙動を変更した検証記録である。
本検証はAmazon Qが提供する安全機構(Human-in-the-Loop)を意図的に無効化するものであり、実運用環境では推奨されない。
本手法は公式バイナリ/ コードを書き換えるものであり、アップデートにより正常動作しない可能性がある。また組織ポリシーに違反する場合があるため注意が必要である。
業務環境での利用については、組織のセキュリティポリシーおよび承認プロセスに従う必要がある。
実施は自己責任でお願いいたします。
きっかけ
Amazon Q for JetBrains(IntelliJ IDEA)のagentic-codingモードでは、コマンド実行のたびに「Run」ボタンの押下が必要となる。
複数ステップの調査ではこの操作がボトルネックとなるため、LSPサーバーのminified JSにパッチを適用し、セッション単位で承認をスキップする仕組みを実装した。
背景と動機
Amazon Q Plugin は以下の承認フローを持つ。
- ファイルアクセス時:Allow
- コマンド実行時:Run
これは安全性および監査性の観点では妥当な設計である。一方で調査作業においては以下の問題が顕在化する。
>数十回のコマンド実行のたびに「Run」を押下する必要がある
他ツールでは以下のような自律実行モードが提供されている。
- Kiro CLI:セッション単位で自動承認
- Codex CLI:
--full-auto - Claude Code:
--dangerously-skip-permissions
👉 一定条件下で処理を委譲できる設計となっている。うらやましい。裏山。
問題の本質 (設計思想の違い)
本件は単なる機能差ではなく、設計思想の差異である。
| 観点 | Amazon Q Plugin | CLI系(Kiro等) |
|---|---|---|
| 操作主体 | 人間 | AI |
| 実行制御 | 都度承認 | セッション単位 |
| 安全性 | 高い | 可変 |
| 作業速度 | 低め | 高い |
👉 IDEは「統制」、CLIは「自律」を前提とした設計である
本当は私も Kiroが使いたいのですが、まだWindowsでは動かないの。
WSL必須だし。そしたら、ほら改造しかないでしょ。
アーキテクチャ調査
承認制御はすべて LSPサーバー側のJavaScript に実装されている。
対象ファイルは以下である。
%LOCALAPPDATA%\aws\toolkits\language-servers\AmazonQ-JetBrains-temp\{ver}\aws-lsp-codewhisperer.js
👉 plugin配下ではなく、実行時に展開された領域が対象となる点に注意が必要
プラグインの構造
Amazon Q plugin は以下の2層構造になっている:
┌─────────────────────────────────┐
│ JetBrains側(Kotlin/JVM) │ ← UIの表示、ボタンのレンダリング
│ plugin-amazonq/lib/*.jar │
├─────────────────────────────────┤
│ LSPサーバー側(Node.js) │ ← ツール承認ロジック、チャット処理
│ aws-lsp-codewhisperer.js │
└─────────────────────────────────┘
承認フロー(Run/Allow/Rejectボタン)の制御はLSPサーバー側のJavaScriptで行われている。JetBrains側はLSPサーバーから受け取ったUIブロックをレンダリングするだけ。
承認フローのコード解析
約6MBのminified JSから、承認制御の核心部分を特定した。
// processToolUses メソッド内(簡略化)
switch(u.name) {
case EXECUTE_BASH: {
// requiresAcceptance: ファイルアクセス等で承認が必要か
{requiresAcceptance:l, warning:d, commandCategory:p} = await s.requiresAcceptance(u.input, c);
if (l || u.name === a.EXECUTE_BASH) {
const i = this.#we(u, l, d, p); // 承認UIブロック生成
e = await t.writeResultBlock(i); // UIに表示
l && await this.waitForToolApproval(...); // 承認待ち
}
break;
}
default: {
// MCPツール(search, fetch_content等)はここ
if (a) { // requiresAcceptance
await this.waitForToolApproval(...); // 承認待ち
}
}
}
ポイント:
-
executeBashはrequiresAcceptanceの結果に関わらず常にUIブロックを表示 -
waitForToolApprovalは Promise ベースで、ボタンクリック時に resolve/reject される - MCPツールは
defaultケースで別の承認フローを持つ
実装の核心
minified JSを扱う上で最も重要な原則は以下である。
既存変数を書き換えず、条件式のみを拡張する
NG例 (実際に発生した障害)
u = !0
👉 const 再代入により全ツールが使用不能となる
OK例
(l && !r.__sonshiMode) && await this.waitForToolApproval(...)
実装方針
2段階確認UI
セキュリティリスクを考慮し、発動時に2段階の確認を設けた。
1段階目: 通常のRun/Rejectボタンに「⚡ Sonshi Mode」ボタンを追加
buttons: [
{id: "run-shell-command", text: "Run", icon: "play"},
{id: "reject-shell-command", text: "Reject", icon: "cancel"},
{id: "sonshi-mode-confirm1", text: "⚡ Sonshi Mode", icon: "zap"}
]
2段階目: セキュリティ警告を表示
⚠️ SONSHI MODE WARNING
This will skip ALL confirmation dialogs (Run/Allow) for the rest of this chat session.
Commands will execute immediately without review.
Security Risk: Prompt injection or unintended commands could run without your approval.
Are you REALLY sure?
尊師モード発動
セッションオブジェクトに以下のフラグを付与。
__sonshiMode = true
この状態では以下の挙動となる。
- 承認UIの表示をスキップ
-
waitForToolApprovalを無効化
通常フロー:
executeBash → UIブロック表示 → [Run] → コマンド実行
尊師モード発動フロー:
executeBash → UIブロック表示 → [⚡ Sonshi Mode] → セキュリティ警告 → [Yes] → コマンド実行
以降: executeBash → コマンド実行(UIスキップ)
尊師モードは
コマンドが連続実行される
MCPツールも承認不要
処理が停止しない。もはや魔法の道具に早変わり。
調査プロセス (MCPツール対応)
上記改修後にMCPツール(search / fetch_content)のみ承認ダイアログが残る事象を確認した。調査手順は以下である。
- ビルトインツールとの差異を確認
-
processToolUsesを再解析 - MCPツールが
defaultケースで処理されていることを特定 - 当該分岐に
__sonshiModeチェックが存在しないことを確認 - 条件式に1行追加し検証
if (a && !r.__sonshiMode) {
👉 +17バイトの変更で全体挙動が改善された
クイックスタート(最短手順)
- 対象JSファイルを特定
- パッチを適用
- IDEを再起動
- Sonshi Modeを有効化
👉 上記で動作する
詳細手順
クリックで展開
Step1: 実行ファイル特定
wmic process where "name='node.exe'" get CommandLine
Step2: パッチ適用
まず、実際にLSPサーバーが使っているJSファイルのパスを特定する。
wmic process where "name='node.exe'" get CommandLine /format:list 2>nul | findstr /i "aws-lsp-codewhisperer"
出力例:
CommandLine=...\AmazonQ-JetBrains-temp\1.64.0\aws-lsp-codewhisperer.js...
このパスに含まれるバージョン番号(例: 1.64.0)を確認する。パッチ対象は以下のファイル:
%LOCALAPPDATA%\aws\toolkits\language-servers\AmazonQ-JetBrains-temp\{バージョン}\aws-lsp-codewhisperer.js
⚠️
plugins\plugin-amazonq\flare\配下にも同名ファイルがあるが、そちらは参照されない。必ず上記パスのファイルを修正すること。
Step 2: パッチスクリプトを配置
パッチポイント(全7箇所)
| # | 箇所 | 変更内容 | 目的 |
|---|---|---|---|
| 1 |
waitForToolApproval 呼び出し条件 |
l&&await → (l&&!r.__sonshiMode)&&await
|
承認待ちスキップ |
| 2 |
#we 関数(ボタン生成) |
Rejectボタンの後に Sonshi Mode ボタン追加 | UIに⚡ボタン表示 |
| 3 |
onButtonClick ルーティング |
sonshi-mode-confirm1/2 を追加 |
ボタンクリックのハンドリング |
| 4 | ボタンクリック resolve/reject | confirm1→__sonshiPending=true, confirm2→__sonshiMode=true
|
2段階確認でフラグ設定 |
| 5 |
#we 呼び出し前 |
__sonshiPending 時にセキュリティ警告UI表示 |
2段階目の確認ダイアログ |
| 6 | 承認ブロック全体の条件 |
if(!r.__sonshiMode&&(...)) でガード |
承認ブロック全体スキップ |
| 7 | MCPツール分岐(defaultケース) |
if(a) → if(a&&!r.__sonshiMode)
|
MCPツール承認もスキップ |
以下の2ファイルを任意のディレクトリに保存する。
sonshi_patch_v2.py(クリックで展開 — Sonshi 1-6: ビルトインツール対応)
"""
Sonshi Mode Patch v2 - Safe implementation avoiding const reassignment
Target: aws-lsp-codewhisperer.js
Patches 1-6: Built-in tool approval skip + UI + 2-step confirmation
Key rule: NEVER reassign const variables. Modify conditions inline only.
"""
import sys, io, os, shutil, subprocess
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
LSP_BASE = os.path.expandvars(
r"%LOCALAPPDATA%\aws\toolkits\language-servers\AmazonQ-JetBrains-temp"
)
def get_running_version():
try:
out = subprocess.check_output(
'wmic process where "name=\'node.exe\'" get CommandLine /format:list',
shell=True, text=True, stderr=subprocess.DEVNULL
)
for line in out.splitlines():
if "aws-lsp-codewhisperer" in line:
parts = line.replace("\\", "/").split("AmazonQ-JetBrains-temp/")
if len(parts) > 1:
return parts[1].split("/")[0]
except Exception:
pass
return None
def resolve_js_dir():
ver = get_running_version()
if ver:
print(f"Detected running version: {ver}")
return os.path.join(LSP_BASE, ver), ver
if os.path.isdir(LSP_BASE):
versions = sorted(os.listdir(LSP_BASE), reverse=True)
if versions:
print(f"IDE not running. Using newest installed version: {versions[0]}")
return os.path.join(LSP_BASE, versions[0]), versions[0]
return None, None
def main():
js_dir, ver = resolve_js_dir()
if not js_dir:
print("ERROR: No version detected"); return False
js_file = os.path.join(js_dir, 'aws-lsp-codewhisperer.js')
backup = os.path.join(js_dir, 'aws-lsp-codewhisperer.js.pre-sonshi-v2.bak')
if not os.path.exists(js_file):
print(f"ERROR: Target not found: {js_file}"); return False
shutil.copy2(js_file, backup)
print(f"Backup: {backup}")
text = open(js_file, 'r', encoding='utf-8').read()
original_len = len(text)
applied = 0
# PATCH 1: Skip waitForToolApproval when sonshi mode active
old1 = 'l&&await this.waitForToolApproval(u,t,e,r,u.name)'
new1 = '(l&&!r.__sonshiMode)&&await this.waitForToolApproval(u,t,e,r,u.name)'
if old1 in text: text = text.replace(old1, new1, 1); applied += 1; print("PATCH 1 OK")
else: print("PATCH 1 SKIP")
# PATCH 2: Add Sonshi Mode button
old2 = '{id:a.BUTTON_REJECT_SHELL_COMMAND,status:"dimmed-clear",text:"Reject",icon:"cancel",...o?{description:`Reject: ${o}`}:{}}]:[]'
new2 = '{id:a.BUTTON_REJECT_SHELL_COMMAND,status:"dimmed-clear",text:"Reject",icon:"cancel",...o?{description:`Reject: ${o}`}:{}},{id:"sonshi-mode-confirm1",status:"dimmed-clear",text:"\\u26A1 Sonshi Mode",icon:"lightning"}]:[]'
if old2 in text: text = text.replace(old2, new2, 1); applied += 1; print("PATCH 2 OK")
else: print("PATCH 2 SKIP")
# PATCH 3: Add sonshi button IDs to handler routing
old3 = 'e.buttonId===a.BUTTON_RUN_SHELL_COMMAND||e.buttonId===a.BUTTON_REJECT_SHELL_COMMAND||e.buttonId===a.BUTTON_REJECT_MCP_TOOL||e.buttonId===a.BUTTON_ALLOW_TOOLS'
new3 = old3 + '||e.buttonId==="sonshi-mode-confirm1"||e.buttonId==="sonshi-mode-confirm2"'
if old3 in text: text = text.replace(old3, new3, 1); applied += 1; print("PATCH 3 OK")
else: print("PATCH 3 SKIP")
# PATCH 4: Add sonshi mode activation logic
old4 = 'e.buttonId===a.BUTTON_REJECT_SHELL_COMMAND||e.buttonId===a.BUTTON_REJECT_MCP_TOOL?(()=>{n.reject(new F.ToolApprovalException("Command was rejected.",!0)),this.#A.add(r)})():n.res'
new4 = old4.replace(')():n.res', ')():e.buttonId==="sonshi-mode-confirm1"?(()=>{t.data.__sonshiPending=!0,n.resolve()})():e.buttonId==="sonshi-mode-confirm2"?(()=>{t.data.__sonshiMode=!0,t.data.__sonshiPending=!1,n.resolve()})():n.res')
if old4 in text: text = text.replace(old4, new4, 1); applied += 1; print("PATCH 4 OK")
else: print("PATCH 4 SKIP")
# PATCH 5: Show 2nd confirmation when sonshiPending
old5 = 'const i=this.#we(u,l,d,p);e=await t.writeResultBlock(i);const o=u.name===a.EXECUTE_BASH'
warn = '## \\u26A0\\uFE0F SONSHI MODE WARNING\\n\\nThis will skip ALL confirmation dialogs for the rest of this chat session.\\nCommands will execute immediately without review.\\n\\n**Security Risk**: Prompt injection or unintended commands could run without your approval.\\n\\nAre you REALLY sure?'
new5 = f'const i=r.__sonshiPending?{{type:"directive",messageId:u.toolUseId,body:"{warn}",buttons:[{{id:"sonshi-mode-confirm2",text:"Yes, activate Sonshi Mode",icon:"lightning",status:"clear"}},{{id:a.BUTTON_REJECT_SHELL_COMMAND,text:"Cancel",icon:"cancel",status:"dimmed-clear"}}]}}:this.#we(u,l,d,p);e=await t.writeResultBlock(i);const o=u.name===a.EXECUTE_BASH'
if old5 in text: text = text.replace(old5, new5, 1); applied += 1; print("PATCH 5 OK")
else: print("PATCH 5 SKIP")
# PATCH 6: Skip entire approval block when sonshi mode active
old6 = 'if(l||u.name===a.EXECUTE_BASH){const i='
new6 = 'if(!r.__sonshiMode&&(l||u.name===a.EXECUTE_BASH)){const i='
if old6 in text: text = text.replace(old6, new6, 1); applied += 1; print("PATCH 6 OK")
else: print("PATCH 6 SKIP")
if applied == 0:
print("\nERROR: No patches applied."); return False
open(js_file, 'w', encoding='utf-8').write(text)
print(f"\nPatched: {applied}/6 | Size: {original_len:,} -> {len(text):,} (+{len(text)-original_len})")
print(f"Rollback: copy /Y \"{backup}\" \"{js_file}\"")
return applied == 6
if __name__ == '__main__':
sys.exit(0 if main() else 1)
sonshi_patch_v3.py(クリックで展開 — Sonshi 7: MCPツール対応)
"""
Sonshi Mode Patch v3 - MCP Tool approval skip
Prerequisite: v2 patches must already be applied.
"""
import sys, io, os, shutil, subprocess
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
LSP_BASE = os.path.expandvars(
r"%LOCALAPPDATA%\aws\toolkits\language-servers\AmazonQ-JetBrains-temp"
)
def get_running_version():
try:
out = subprocess.check_output(
'wmic process where "name=\'node.exe\'" get CommandLine /format:list',
shell=True, text=True, stderr=subprocess.DEVNULL
)
for line in out.splitlines():
if "aws-lsp-codewhisperer" in line:
parts = line.replace("\\", "/").split("AmazonQ-JetBrains-temp/")
if len(parts) > 1:
return parts[1].split("/")[0]
except Exception:
pass
return None
def resolve_js_dir():
ver = get_running_version()
if ver:
print(f"Detected running version: {ver}")
return os.path.join(LSP_BASE, ver), ver
if os.path.isdir(LSP_BASE):
versions = sorted(os.listdir(LSP_BASE), reverse=True)
if versions:
print(f"IDE not running. Using newest installed version: {versions[0]}")
return os.path.join(LSP_BASE, versions[0]), versions[0]
return None, None
def main():
js_dir, ver = resolve_js_dir()
if not js_dir:
print("ERROR: No version detected"); return False
js_file = os.path.join(js_dir, 'aws-lsp-codewhisperer.js')
backup = os.path.join(js_dir, 'aws-lsp-codewhisperer.js.pre-sonshi-v3.bak')
if not os.path.exists(js_file):
print(f"ERROR: Target not found: {js_file}"); return False
text = open(js_file, 'r', encoding='utf-8').read()
# Verify v2
if '__sonshiMode' not in text:
print("ERROR: v2 patches not found. Run sonshi_patch_v2.py first."); return False
print("v2 patches verified OK")
if not os.path.exists(backup):
shutil.copy2(js_file, backup)
print(f"Backup: {backup}")
original_len = len(text)
# PATCH 7: Skip MCP tool approval when sonshi mode active
old7 = 'if(a){const n=this.#we(u,a,c,void 0,o);e=await t.writeResultBlock(n),await this.waitForToolApproval(u,t,e,r,o)}'
new7 = 'if(a&&!r.__sonshiMode){const n=this.#we(u,a,c,void 0,o);e=await t.writeResultBlock(n),await this.waitForToolApproval(u,t,e,r,o)}'
if old7 in text:
if text.count(old7) != 1:
print(f"WARNING: Pattern found {text.count(old7)} times. Aborting."); return False
text = text.replace(old7, new7, 1)
print("PATCH 7 OK: MCP tool approval skip")
elif new7 in text:
print("PATCH 7: Already applied")
else:
print("PATCH 7 FAIL: Pattern not found"); return False
open(js_file, 'w', encoding='utf-8').write(text)
print(f"\nSize: {original_len:,} -> {len(text):,} (+{len(text)-original_len})")
print(f"Rollback: copy /Y \"{backup}\" \"{js_file}\"")
print("\n** IDE restart required **")
return True
if __name__ == '__main__':
sys.exit(0 if main() else 1)
Step3: IDE再起動
Step4: 動作確認
- ⚡ Sonshi Mode ボタン表示
- 有効化後、自動実行を確認
運用の工夫
- バージョン自動検出
- パッチ自動適用
- 差分退避
- 状態チェック
👉 プラグイン更新にも一定程度追従可能な構成とした
セキュリティに関する考慮
尊師モードは「AIが任意のコマンドを確認なしで実行できる」状態を作る。
以下のリスクを認識した上で使用すること。
- プロンプトインジェクション: 悪意あるコンテンツを含むファイルを読み込んだ際に、意図しないコマンドが実行される可能性
- スコープ: セッション(チャット)単位。新しいチャットを開けばリセットされる
- 緩和策: 2段階確認UIでユーザーに明示的に警告
いずれにしても検証用途に限定すべき。
以下のケースでは本手法を適用すべきではない
- 外部リポジトリや未知のコードを扱う場合
- 本番環境または業務データを扱う環境
- セキュリティ要件が厳格な環境
結論
Amazon Q Plugin は安全性を重視した設計である。
本検証はその設計を理解した上で、自律性を拡張したものである。
本手法は開発効率向上の一手段ではあるが
Amazon Q Pluginが提供する安全機構を変更するものである。
環境情報
- IntelliJ IDEA 2026.1
- Amazon Q for JetBrains プラグイン v4.0.261
- LSPサーバー: aws-lsp-codewhisperer.js
- OS: Windows 11
- Node.js: プラグイン同梱版
通称:尊師モード
まとめ
Amazon Q は優秀な同僚です。
でも席を外すと処理が停止するし、OK出さないと何もしない。
本検証で目指したのは、
席を外しても処理が継続する状態。
でも本当に何も確認しないで突き進むから要注意。
尊師ってば自信持ちすぎ・・。
これで Amazon Q plugin があれば Kiro CLI 使わなくても大丈夫。
私には尊師がついてるから。いつも心に太陽を。
セキュリティおよび運用上の注意 (重要)
本記事の手法は以下の前提を理解した上でのみ適用すること。
- Amazon Qが提供するHuman-in-the-Loopを無効化している
- AIによる自動コマンド実行のリスクが増加する
- プロンプトインジェクション攻撃への耐性が低下する
- ローカル環境のコード改変を伴うためサプライチェーンリスクがある
本手法は検証用途に限定し、業務環境・本番環境での利用は推奨しない。
適用にあたってはリスクを十分に理解し
利用環境および組織ポリシーに従い慎重に判断されたい。
最後に。本検証はAmazon Qの設計思想を否定するものではなく
用途に応じて自律性と統制のバランスを調整する一例である。
編集後記(2026-05-06追記): v1.66.0 対応 — PATCH 4 パターン不一致の修正
概要
Amazon Q Plugin が v1.66.0 に更新された際、尊師モードパッチの PATCH 4(ボタンクリック時のフラグ設定) がパターン不一致で適用できなくなった。
原因を特定し、パッチスクリプトを正規表現対応に改修して解決した記録。
発生した事象
PATCH 1 OK: waitForToolApproval condition (skip when sonshi active)
PATCH 2 OK: Added Sonshi Mode button to EXECUTE_BASH UI
PATCH 3 OK: Added sonshi button IDs to handler routing
PATCH 4 SKIP: pattern not found ← ★ここだけ失敗
PATCH 5 OK: Added 2nd confirmation dialog for sonshi mode
PATCH 6 OK: Skip entire approval block when sonshi mode active
PATCH 4 が適用されないと、⚡ボタンを押しても __sonshiMode=true が設定されず、尊師モードが発動しない。
原因
minified JS のビルド時に、モジュールスコープの変数名が変更されていた。
| バージョン | 変数名 | コード |
|---|---|---|
| v1.63.0〜v1.65.0 | F |
new F.ToolApprovalException("Command was rejected.",!0) |
| v1.66.0 | j |
new j.ToolApprovalException("Command was rejected.",!0) |
パッチスクリプトの old4 パターンが F.ToolApprovalException をリテラル文字列で検索していたため、j.ToolApprovalException にマッチしなかった。
なぜ他のパッチは影響を受けなかったか
PATCH 1〜3, 5〜7 のパターンは定数名(a.BUTTON_REJECT_SHELL_COMMAND 等)やメソッド名(this.waitForToolApproval, this.#we)を使っており、これらはminify時に変更されない。PATCH 4 だけがモジュールスコープの短縮変数名に依存していた。
修正内容
PATCH 4 のパターンマッチを固定文字列 → 正規表現に変更し、変数名部分を [A-Za-z_$]+ でキャプチャするようにした。
Before(v1.63.0〜v1.65.0 専用)
old4 = 'e.buttonId===a.BUTTON_REJECT_SHELL_COMMAND||e.buttonId===a.BUTTON_REJECT_MCP_TOOL?(()=>{n.reject(new F.ToolApprovalException("Command was rejected.",!0)),this.#A.add(r)})():n.res'
if old4 in text:
text = text.replace(old4, new4, 1)
After(任意の変数名に対応)
import re
pat4 = re.compile(
r'e\.buttonId===a\.BUTTON_REJECT_SHELL_COMMAND\|\|e\.buttonId===a\.BUTTON_REJECT_MCP_TOOL\?\(\(\)=>\{n\.reject\(new ([A-Za-z_$]+)\.ToolApprovalException\("Command was rejected\.",!0\)\),this\.#A\.add\(r\)\}\)\(\):n\.res'
)
m4 = pat4.search(text)
if m4:
var_name = m4.group(1) # 'F' or 'j' or any future name
old4_actual = m4.group(0)
new4_actual = f'...{var_name}.ToolApprovalException...(sonshi handlers)...:n.res'
text = text.replace(old4_actual, new4_actual, 1)
print(f"PATCH 4 OK: Added sonshi mode activation logic (var={var_name})")
ポイント:
-
([A-Za-z_$]+)でminify変数名をキャプチャ - キャプチャした変数名を
new4の生成時にそのまま使用 - 将来のバージョンで変数名が
F→j→k→ ... と変わっても自動追従
適用結果
PATCH 4 OK: Added sonshi mode activation logic (var=j)
Patched: 6/6 patches applied
Size: 5,962,292 -> 5,963,226 bytes (diff: +934)
教訓
| # | 教訓 | 詳細 |
|---|---|---|
| 1 | minified JSの短縮変数名はバージョンごとに変わる | モジュールスコープの変数(F, j, k...)はビルドのたびに再割り当てされる |
| 2 | 定数名・メソッド名は安定 |
a.BUTTON_*, this.#we, this.waitForToolApproval 等はminify対象外 |
| 3 | パターンマッチは正規表現で柔軟に | 固定文字列マッチは1バージョンで壊れる。変動部分は正規表現でキャプチャすべき |
| 4 | PATCH SKIPは即座に調査 | 5/6適用でも「動くかも」と放置すると、肝心のフラグ設定が欠落して全体が機能しない |
バージョン対応状況(更新)
| バージョン | PATCH 1-7 | 備考 |
|---|---|---|
| v1.63.0 | ✅ 全OK | 初版対応 |
| v1.64.0 | ✅ 全OK | |
| v1.65.0 | ✅ 全OK | |
| v1.66.0 | ✅ 全OK | PATCH 4 を正規表現対応に修正して解決 |
環境情報(更新)
- IntelliJ IDEA 2026.1
- Amazon Q for JetBrains プラグイン v1.66.0
- LSPサーバー: aws-lsp-codewhisperer.js (5,962,292 bytes)
- OS: Windows 11
- パッチスクリプト: sonshi_patch_v2.py(正規表現対応版)
まとめ
プラグイン更新のたびにパッチが壊れるリスクは本手法の宿命。
今回の修正で「変数名の変更」という最も頻繁に起こるminify差異に対して耐性を獲得した。
ただし、コード構造自体が変わった場合(三項演算子→if文への書き換え等)は依然として手動調査が必要。
check-export-patch.py による定期チェックで早期検出する運用は引き続き有効。