diff --git a/.claude/hooks/dry-run-gate.sh b/.claude/hooks/dry-run-gate.sh index 5c2e0aa27..a66f54fcc 100755 --- a/.claude/hooks/dry-run-gate.sh +++ b/.claude/hooks/dry-run-gate.sh @@ -82,19 +82,34 @@ case "$TOOL_NAME" in ;; esac -# === MCP-write whitelist (точные совпадения tool_name) === +# === MCP-write: IWE Gateway tools (namespace-agnostic action match) === +# Префикс MCP-инструмента дрейфует между способами подключения к одному Gateway +# (server "iwe-knowledge", mcp.aisystant.com/mcp): +# mcp__claude_ai_IWE__ — legacy connector с именем "IWE" +# mcp__iwe_knowledge_ — OMP runtime (одинарный разделитель "_") +# mcp__iwe-knowledge__ — project .mcp.json (server id "iwe-knowledge") +# mcp__claude_ai_https_..._mcp__ — connector с именем из URL +# Exact-list по префиксу устаревает при каждой миграции namespace и пропускает +# write-инструменты (bug: gate не блокировал mcp__iwe-knowledge__personal_write и др.). +# Решение: сверять ДЕЙСТВИЕ (суффикс после последнего разделителя), а не полное имя. +# Паттерн "*_" ловит и "__" (двойной разделитель), и "_" (OMP). +if [[ "$TOOL_NAME" == mcp__* ]]; then + for action in \ + personal_write personal_delete personal_create_pack personal_propose_capture \ + personal_reindex_source personal_scaffold_notes personal_connect_source \ + personal_disconnect_source personal_purge_source personal_generate_fault_remind \ + dt_write_digital_twin create_repository github_connect github_disconnect \ + knowledge_feedback knowledge_reindex_source send_telegram_message \ + run_strategist run_extractor capture_trace grant_consent \ + agent_status_update request_equipment_upgrade; do + if [[ "$TOOL_NAME" == *"_${action}" ]]; then + block "$TOOL_NAME (action: $action)" + fi + done +fi + +# === MCP-write: vendor tools (exact tool_name — префиксы вендоров стабильны) === case "$TOOL_NAME" in - mcp__claude_ai_IWE__personal_write|\ - mcp__claude_ai_IWE__personal_delete|\ - mcp__claude_ai_IWE__personal_create_pack|\ - mcp__claude_ai_IWE__personal_propose_capture|\ - mcp__claude_ai_IWE__personal_reindex_source|\ - mcp__claude_ai_IWE__personal_scaffold_notes|\ - mcp__claude_ai_IWE__dt_write_digital_twin|\ - mcp__claude_ai_IWE__create_repository|\ - mcp__claude_ai_IWE__github_connect|\ - mcp__claude_ai_IWE__github_disconnect|\ - mcp__claude_ai_IWE__knowledge_feedback|\ mcp__claude_ai_Gmail__create_draft|\ mcp__claude_ai_Gmail__create_label|\ mcp__claude_ai_Gmail__label_message|\ diff --git a/README.md b/README.md index 32c8be144..64bf0a507 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # IWE — Intellectual Work Environment [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) -[![Version](https://img.shields.io/badge/version-0.35.4-blue.svg)](CHANGELOG.md) +[![Version](https://img.shields.io/badge/version-0.35.5-blue.svg)](CHANGELOG.md) [![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows%20(WSL)-lightgrey.svg)]() [![EN sync](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/TserenTserenov/FMT-exocortex-template/en-draft/badge-data.json)](https://github.com/TserenTserenov/FMT-exocortex-template/tree/en-draft) diff --git a/memory/dry-run-contract.md b/memory/dry-run-contract.md index 8b5b3e475..a684229e6 100644 --- a/memory/dry-run-contract.md +++ b/memory/dry-run-contract.md @@ -82,22 +82,36 @@ Expected: tool blocked by contract, this is rehearsal failure point \bsed\s+-i ``` -### MCP-write whitelist +### MCP-write matcher -Точное имя tool (полный список — все, что НЕ read-only): +**IWE Gateway (`iwe-knowledge`, `mcp.aisystant.com/mcp`) — сверка по ДЕЙСТВИЮ, не по префиксу.** + +Префикс MCP-инструмента дрейфует между способами подключения к одному и тому же Gateway, +поэтому exact-list по полному имени устаревает при каждой миграции namespace: + +| Namespace | Откуда | Пример | +|---|---|---| +| `mcp__claude_ai_IWE__` | legacy connector с именем «IWE» | `mcp__claude_ai_IWE__personal_write` | +| `mcp__iwe_knowledge_` | OMP runtime (одинарный разделитель `_`) | `mcp__iwe_knowledge_personal_write` | +| `mcp__iwe-knowledge__` | project `.mcp.json` (server id `iwe-knowledge`) | `mcp__iwe-knowledge__personal_write` | +| `mcp__claude_ai_https_..._mcp__` | connector с именем, производным от URL | `mcp__claude_ai_https_mcp_aisystant_com_mcp__personal_write` | + +Хук блокирует по **действию** — суффиксу после последнего разделителя (`*_` ловит и +`__`, и OMP-вариант `_`). Список действий (все write / side-effect): + +``` +personal_write personal_delete personal_create_pack personal_propose_capture +personal_reindex_source personal_scaffold_notes personal_connect_source +personal_disconnect_source personal_purge_source personal_generate_fault_remind +dt_write_digital_twin create_repository github_connect github_disconnect +knowledge_feedback knowledge_reindex_source send_telegram_message +run_strategist run_extractor capture_trace grant_consent +agent_status_update request_equipment_upgrade +``` + +**Vendor MCP — exact tool_name** (префиксы вендоров стабильны): ``` -mcp__claude_ai_IWE__personal_write -mcp__claude_ai_IWE__personal_delete -mcp__claude_ai_IWE__personal_create_pack -mcp__claude_ai_IWE__personal_propose_capture -mcp__claude_ai_IWE__personal_reindex_source -mcp__claude_ai_IWE__personal_scaffold_notes -mcp__claude_ai_IWE__dt_write_digital_twin -mcp__claude_ai_IWE__create_repository -mcp__claude_ai_IWE__github_connect -mcp__claude_ai_IWE__github_disconnect -mcp__claude_ai_IWE__knowledge_feedback mcp__claude_ai_Gmail__create_draft mcp__claude_ai_Gmail__create_label mcp__claude_ai_Gmail__label_message