From 8488811b80c0b2a658c3561b095e040cebff57fa Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Sun, 5 Apr 2026 20:19:21 -0700 Subject: [PATCH] chore: remove legacy insaits integration --- WORKING-CONTEXT.md | 1 + docs/pt-BR/README.md | 2 +- docs/zh-CN/README.md | 2 +- docs/zh-CN/hooks/README.md | 2 - hooks/README.md | 2 - hooks/hooks.json | 12 - mcp-configs/mcp-servers.json | 5 - scripts/hooks/insaits-security-monitor.py | 269 ---------------------- scripts/hooks/insaits-security-wrapper.js | 88 ------- tests/hooks/hooks.test.js | 32 --- 10 files changed, 3 insertions(+), 412 deletions(-) delete mode 100644 scripts/hooks/insaits-security-monitor.py delete mode 100644 scripts/hooks/insaits-security-wrapper.js diff --git a/WORKING-CONTEXT.md b/WORKING-CONTEXT.md index 82ae07ba..66a70ef0 100644 --- a/WORKING-CONTEXT.md +++ b/WORKING-CONTEXT.md @@ -155,6 +155,7 @@ Keep this file detailed for only the current sprint, blockers, and next actions. - 2026-04-05: Direct-ported the safe `globals` bump from PR `#1243` into `main` as part of the council lane and closed the PR as superseded. - 2026-04-05: Closed PR `#1232` after full audit. The proposed `skill-scout` workflow overlaps current `search-first`, `/skill-create`, and `skill-stocktake`; if a dedicated marketplace-discovery layer returns later it should be rebuilt on top of the current install/catalog model rather than landing as a parallel discovery path. - 2026-04-05: Ported the safe localized README switcher fixes from PR `#1209` directly into `main` rather than merging the docs PR wholesale. The navigation now consistently includes `Português (Brasil)` and `Türkçe` across the localized README switchers, while newer localized body copy stays intact. +- 2026-04-05: Removed the stale InsAIts shipped surface from `main`. ECC no longer ships the external Python MCP entry, opt-in hook wiring, wrapper/monitor scripts, or current docs mentions for `insa-its`; changelog history remains, but the live product surface is now fully ECC-native again. - 2026-04-05: Salvaged the reusable Hermes-generated operator workflow lane without replaying the whole branch. Added six ECC-native top-level skills instead of the old nested `skills/hermes-generated/*` tree: `automation-audit-ops`, `email-ops`, `finance-billing-ops`, `messages-ops`, `research-ops`, and `terminal-ops`. `research-ops` now wraps the existing research stack, while the other five extend `operator-workflows` without introducing any external runtime assumptions. - 2026-04-05: Added `skills/product-capability` plus `docs/examples/product-capability-template.md` as the canonical PRD-to-SRS lane for issue `#1185`. This is the ECC-native capability-contract step between vague product intent and implementation, and it lives in `business-content` rather than spawning a parallel planning subsystem. - 2026-04-05: Tightened `product-lens` so it no longer overlaps the new capability-contract lane. `product-lens` now explicitly owns product diagnosis / brief validation, while `product-capability` owns implementation-ready capability plans and SRS-style constraints. diff --git a/docs/pt-BR/README.md b/docs/pt-BR/README.md index 88e6fa2e..8298a2ba 100644 --- a/docs/pt-BR/README.md +++ b/docs/pt-BR/README.md @@ -89,7 +89,7 @@ Este repositório contém apenas o código. Os guias explicam tudo. - **Revisão de orquestração** — Pontuação de auditoria de harness tornado determinístico, status de orquestração e compatibilidade de launcher reforçados, prevenção de loop de observer com guarda de 5 camadas. - **Confiabilidade do observer** — Correção de explosão de memória com throttling e tail sampling, correção de acesso sandbox, lógica de início preguiçoso e guarda de reentrância. - **12 ecossistemas de linguagem** — Novas regras para Java, PHP, Perl, Kotlin/Android/KMP, C++ e Rust se juntam ao TypeScript, Python, Go e regras comuns existentes. -- **Contribuições da comunidade** — Traduções para coreano e chinês, hook de segurança InsAIts, otimização de hook biome, skills VideoDB, skills operacionais Evos, instalador PowerShell, suporte ao IDE Antigravity. +- **Contribuições da comunidade** — Traduções para coreano e chinês, otimização de hook biome, skills VideoDB, skills operacionais Evos, instalador PowerShell, suporte ao IDE Antigravity. - **CI reforçado** — 19 correções de falhas de teste, aplicação de contagem de catálogo, validação de manifesto de instalação e suíte de testes completa no verde. ### v1.8.0 — Sistema de Desempenho de Harness (Mar 2026) diff --git a/docs/zh-CN/README.md b/docs/zh-CN/README.md index 3ea2d83a..851e9697 100644 --- a/docs/zh-CN/README.md +++ b/docs/zh-CN/README.md @@ -90,7 +90,7 @@ * **编排系统大修** — 使治理审核评分具有确定性,强化编排状态和启动器兼容性,通过 5 层防护防止观察者循环。 * **观察者可靠性** — 通过节流和尾部采样修复内存爆炸问题,修复沙箱访问,实现延迟启动逻辑,并增加重入防护。 * **12 个语言生态系统** — 新增 Java、PHP、Perl、Kotlin/Android/KMP、C++ 和 Rust 规则,与现有的 TypeScript、Python、Go 及通用规则并列。 -* **社区贡献** — 韩语和中文翻译,InsAIts 安全钩子,biome 钩子优化,VideoDB 技能,Evos 操作技能,PowerShell 安装程序,Antigravity IDE 支持。 +* **社区贡献** — 韩语和中文翻译,biome 钩子优化,VideoDB 技能,Evos 操作技能,PowerShell 安装程序,Antigravity IDE 支持。 * **CI 强化** — 修复 19 个测试失败问题,强制执行目录计数,验证安装清单,并使完整测试套件通过。 ### v1.8.0 — 平台性能系统(2026 年 3 月) diff --git a/docs/zh-CN/hooks/README.md b/docs/zh-CN/hooks/README.md index b7aa75b1..0cfb571f 100644 --- a/docs/zh-CN/hooks/README.md +++ b/docs/zh-CN/hooks/README.md @@ -25,8 +25,6 @@ | **Git 推送提醒器** | `Bash` | 在 `git push` 前提醒检查变更 | 0 (警告) | | **文档文件警告器** | `Write` | 对非标准 `.md`/`.txt` 文件发出警告(允许 README、CLAUDE、CONTRIBUTING、CHANGELOG、LICENSE、SKILL、docs/、skills/);跨平台路径处理 | 0 (警告) | | **策略性压缩提醒器** | `Edit\|Write` | 建议在逻辑间隔(约每 50 次工具调用)手动执行 `/compact` | 0 (警告) | -| **InsAIts 安全监控器(可选加入)** | `Bash\|Write\|Edit\|MultiEdit` | 对高信号工具输入的可选安全扫描。除非设置 `ECC_ENABLE_INSAITS=1`,否则禁用。对关键发现进行拦截,对非关键发现发出警告,并将审计日志写入 `.insaits_audit_session.jsonl`。需要 `pip install insa-its`。[详情](../../../scripts/hooks/insaits-security-monitor.py) | 2 (拦截关键) / 0 (警告) | - ### PostToolUse 钩子 | 钩子 | 匹配器 | 功能 | diff --git a/hooks/README.md b/hooks/README.md index a88c91bf..bbdbed10 100644 --- a/hooks/README.md +++ b/hooks/README.md @@ -26,8 +26,6 @@ User request → Claude picks a tool → PreToolUse hook runs → Tool executes | **Pre-commit quality check** | `Bash` | Runs quality checks before `git commit`: lints staged files, validates commit message format when provided via `-m/--message`, detects console.log/debugger/secrets | 2 (blocks critical) / 0 (warns) | | **Doc file warning** | `Write` | Warns about non-standard `.md`/`.txt` files (allows README, CLAUDE, CONTRIBUTING, CHANGELOG, LICENSE, SKILL, docs/, skills/); cross-platform path handling | 0 (warns) | | **Strategic compact** | `Edit\|Write` | Suggests manual `/compact` at logical intervals (every ~50 tool calls) | 0 (warns) | -| **InsAIts security monitor (opt-in)** | `Bash\|Write\|Edit\|MultiEdit` | Optional security scan for high-signal tool inputs. Disabled unless `ECC_ENABLE_INSAITS=1`. Blocks on critical findings, warns on non-critical, and writes audit log to `.insaits_audit_session.jsonl`. Requires `pip install insa-its`. [Details](../scripts/hooks/insaits-security-monitor.py) | 2 (blocks critical) / 0 (warns) | - ### PostToolUse Hooks | Hook | Matcher | What It Does | diff --git a/hooks/hooks.json b/hooks/hooks.json index c0a38037..3da90a22 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -92,18 +92,6 @@ "description": "Capture tool use observations for continuous learning", "id": "pre:observe:continuous-learning" }, - { - "matcher": "Bash|Write|Edit|MultiEdit", - "hooks": [ - { - "type": "command", - "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/run-with-flags.js\" \"pre:insaits-security\" \"scripts/hooks/insaits-security-wrapper.js\" \"standard,strict\"", - "timeout": 15 - } - ], - "description": "Optional InsAIts AI security monitor for Bash/Edit/Write flows. Enable with ECC_ENABLE_INSAITS=1. Requires: pip install insa-its", - "id": "pre:insaits:security" - }, { "matcher": "Bash|Write|Edit|MultiEdit", "hooks": [ diff --git a/mcp-configs/mcp-servers.json b/mcp-configs/mcp-servers.json index d163d937..03e2e2fb 100644 --- a/mcp-configs/mcp-servers.json +++ b/mcp-configs/mcp-servers.json @@ -104,11 +104,6 @@ "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/your/projects"], "description": "Filesystem operations (set your path)" }, - "insaits": { - "command": "python3", - "args": ["-m", "insa_its.mcp_server"], - "description": "AI-to-AI security monitoring — anomaly detection, credential exposure, hallucination checks, forensic tracing. 23 anomaly types, OWASP MCP Top 10 coverage. 100% local. Install: pip install insa-its" - }, "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp", "--browser", "chrome"], diff --git a/scripts/hooks/insaits-security-monitor.py b/scripts/hooks/insaits-security-monitor.py deleted file mode 100644 index da1bbf24..00000000 --- a/scripts/hooks/insaits-security-monitor.py +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/env python3 -""" -InsAIts Security Monitor -- PreToolUse Hook for Claude Code -============================================================ - -Real-time security monitoring for Claude Code tool inputs. -Detects credential exposure, prompt injection, behavioral anomalies, -hallucination chains, and 20+ other anomaly types -- runs 100% locally. - -Writes audit events to .insaits_audit_session.jsonl for forensic tracing. - -Setup: - pip install insa-its - export ECC_ENABLE_INSAITS=1 - - Add to .claude/settings.json: - { - "hooks": { - "PreToolUse": [ - { - "matcher": "Bash|Write|Edit|MultiEdit", - "hooks": [ - { - "type": "command", - "command": "node scripts/hooks/insaits-security-wrapper.js" - } - ] - } - ] - } - } - -How it works: - Claude Code passes tool input as JSON on stdin. - This script runs InsAIts anomaly detection on the content. - Exit code 0 = clean (pass through). - Exit code 2 = critical issue found (blocks tool execution). - Stderr output = non-blocking warning shown to Claude. - -Environment variables: - INSAITS_DEV_MODE Set to "true" to enable dev mode (no API key needed). - Defaults to "false" (strict mode). - INSAITS_MODEL LLM model identifier for fingerprinting. Default: claude-opus. - INSAITS_FAIL_MODE "open" (default) = continue on SDK errors. - "closed" = block tool execution on SDK errors. - INSAITS_VERBOSE Set to any value to enable debug logging. - -Detections include: - - Credential exposure (API keys, tokens, passwords) - - Prompt injection patterns - - Hallucination indicators (phantom citations, fact contradictions) - - Behavioral anomalies (context loss, semantic drift) - - Tool description divergence - - Shorthand emergence / jargon drift - -All processing is local -- no data leaves your machine. - -Author: Cristi Bogdan -- YuyAI (https://github.com/Nomadu27/InsAIts) -License: Apache 2.0 -""" - -from __future__ import annotations - -import hashlib -import json -import logging -import os -import sys -import time -from typing import Any, Dict, List, Tuple - -# Configure logging to stderr so it does not interfere with stdout protocol -logging.basicConfig( - stream=sys.stderr, - format="[InsAIts] %(message)s", - level=logging.DEBUG if os.environ.get("INSAITS_VERBOSE") else logging.WARNING, -) -log = logging.getLogger("insaits-hook") - -# Try importing InsAIts SDK -try: - from insa_its import insAItsMonitor - INSAITS_AVAILABLE: bool = True -except ImportError: - INSAITS_AVAILABLE = False - -# --- Constants --- -AUDIT_FILE: str = ".insaits_audit_session.jsonl" -MIN_CONTENT_LENGTH: int = 10 -MAX_SCAN_LENGTH: int = 4000 -DEFAULT_MODEL: str = "claude-opus" -BLOCKING_SEVERITIES: frozenset = frozenset({"CRITICAL"}) - - -def extract_content(data: Dict[str, Any]) -> Tuple[str, str]: - """Extract inspectable text from a Claude Code tool input payload. - - Returns: - A (text, context) tuple where *text* is the content to scan and - *context* is a short label for the audit log. - """ - tool_name: str = data.get("tool_name", "") - tool_input: Dict[str, Any] = data.get("tool_input", {}) - - text: str = "" - context: str = "" - - if tool_name in ("Write", "Edit", "MultiEdit"): - text = tool_input.get("content", "") or tool_input.get("new_string", "") - context = "file:" + str(tool_input.get("file_path", ""))[:80] - elif tool_name == "Bash": - # PreToolUse: the tool hasn't executed yet, inspect the command - command: str = str(tool_input.get("command", "")) - text = command - context = "bash:" + command[:80] - elif "content" in data: - content: Any = data["content"] - if isinstance(content, list): - text = "\n".join( - b.get("text", "") for b in content if b.get("type") == "text" - ) - elif isinstance(content, str): - text = content - context = str(data.get("task", "")) - - return text, context - - -def write_audit(event: Dict[str, Any]) -> None: - """Append an audit event to the JSONL audit log. - - Creates a new dict to avoid mutating the caller's *event*. - """ - try: - enriched: Dict[str, Any] = { - **event, - "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), - } - enriched["hash"] = hashlib.sha256( - json.dumps(enriched, sort_keys=True).encode() - ).hexdigest()[:16] - with open(AUDIT_FILE, "a", encoding="utf-8") as f: - f.write(json.dumps(enriched) + "\n") - except OSError as exc: - log.warning("Failed to write audit log %s: %s", AUDIT_FILE, exc) - - -def get_anomaly_attr(anomaly: Any, key: str, default: str = "") -> str: - """Get a field from an anomaly that may be a dict or an object. - - The SDK's ``send_message()`` returns anomalies as dicts, while - other code paths may return dataclass/object instances. This - helper handles both transparently. - """ - if isinstance(anomaly, dict): - return str(anomaly.get(key, default)) - return str(getattr(anomaly, key, default)) - - -def format_feedback(anomalies: List[Any]) -> str: - """Format detected anomalies as feedback for Claude Code. - - Returns: - A human-readable multi-line string describing each finding. - """ - lines: List[str] = [ - "== InsAIts Security Monitor -- Issues Detected ==", - "", - ] - for i, a in enumerate(anomalies, 1): - sev: str = get_anomaly_attr(a, "severity", "MEDIUM") - atype: str = get_anomaly_attr(a, "type", "UNKNOWN") - detail: str = get_anomaly_attr(a, "details", "") - lines.extend([ - f"{i}. [{sev}] {atype}", - f" {detail[:120]}", - "", - ]) - lines.extend([ - "-" * 56, - "Fix the issues above before continuing.", - "Audit log: " + AUDIT_FILE, - ]) - return "\n".join(lines) - - -def main() -> None: - """Entry point for the Claude Code PreToolUse hook.""" - raw: str = sys.stdin.read().strip() - if not raw: - sys.exit(0) - - try: - data: Dict[str, Any] = json.loads(raw) - except json.JSONDecodeError: - data = {"content": raw} - - text, context = extract_content(data) - - # Skip very short content (e.g. "OK", empty bash results) - if len(text.strip()) < MIN_CONTENT_LENGTH: - sys.exit(0) - - if not INSAITS_AVAILABLE: - log.warning("Not installed. Run: pip install insa-its") - sys.exit(0) - - # Wrap SDK calls so an internal error does not crash the hook - try: - monitor: insAItsMonitor = insAItsMonitor( - session_name="claude-code-hook", - dev_mode=os.environ.get( - "INSAITS_DEV_MODE", "false" - ).lower() in ("1", "true", "yes"), - ) - result: Dict[str, Any] = monitor.send_message( - text=text[:MAX_SCAN_LENGTH], - sender_id="claude-code", - llm_id=os.environ.get("INSAITS_MODEL", DEFAULT_MODEL), - ) - except Exception as exc: # Broad catch intentional: unknown SDK internals - fail_mode: str = os.environ.get("INSAITS_FAIL_MODE", "open").lower() - if fail_mode == "closed": - sys.stdout.write( - f"InsAIts SDK error ({type(exc).__name__}); " - "blocking execution to avoid unscanned input.\n" - ) - sys.exit(2) - log.warning( - "SDK error (%s), skipping security scan: %s", - type(exc).__name__, exc, - ) - sys.exit(0) - - anomalies: List[Any] = result.get("anomalies", []) - - # Write audit event regardless of findings - write_audit({ - "tool": data.get("tool_name", "unknown"), - "context": context, - "anomaly_count": len(anomalies), - "anomaly_types": [get_anomaly_attr(a, "type") for a in anomalies], - "text_length": len(text), - }) - - if not anomalies: - log.debug("Clean -- no anomalies detected.") - sys.exit(0) - - # Determine maximum severity - has_critical: bool = any( - get_anomaly_attr(a, "severity").upper() in BLOCKING_SEVERITIES - for a in anomalies - ) - - feedback: str = format_feedback(anomalies) - - if has_critical: - # stdout feedback -> Claude Code shows to the model - sys.stdout.write(feedback + "\n") - sys.exit(2) # PreToolUse exit 2 = block tool execution - else: - # Non-critical: warn via stderr (non-blocking) - log.warning("\n%s", feedback) - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/scripts/hooks/insaits-security-wrapper.js b/scripts/hooks/insaits-security-wrapper.js deleted file mode 100644 index 9f3e46d8..00000000 --- a/scripts/hooks/insaits-security-wrapper.js +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env node -/** - * InsAIts Security Monitor — wrapper for run-with-flags compatibility. - * - * This thin wrapper receives stdin from the hooks infrastructure and - * delegates to the Python-based insaits-security-monitor.py script. - * - * The wrapper exists because run-with-flags.js spawns child scripts - * via `node`, so a JS entry point is needed to bridge to Python. - */ - -'use strict'; - -const path = require('path'); -const { spawnSync } = require('child_process'); - -const MAX_STDIN = 1024 * 1024; - -function isEnabled(value) { - return ['1', 'true', 'yes', 'on'].includes(String(value || '').toLowerCase()); -} - -let raw = ''; -process.stdin.setEncoding('utf8'); -process.stdin.on('data', chunk => { - if (raw.length < MAX_STDIN) { - raw += chunk.substring(0, MAX_STDIN - raw.length); - } -}); - -process.stdin.on('end', () => { - if (!isEnabled(process.env.ECC_ENABLE_INSAITS)) { - process.stdout.write(raw); - process.exit(0); - } - - const scriptDir = __dirname; - const pyScript = path.join(scriptDir, 'insaits-security-monitor.py'); - - // Try python3 first (macOS/Linux), fall back to python (Windows) - const pythonCandidates = ['python3', 'python']; - let result; - - for (const pythonBin of pythonCandidates) { - result = spawnSync(pythonBin, [pyScript], { - input: raw, - encoding: 'utf8', - env: process.env, - cwd: process.cwd(), - timeout: 14000, - }); - - // ENOENT means binary not found — try next candidate - if (result.error && result.error.code === 'ENOENT') { - continue; - } - break; - } - - if (!result || (result.error && result.error.code === 'ENOENT')) { - process.stderr.write('[InsAIts] python3/python not found. Install Python 3.9+ and: pip install insa-its\n'); - process.stdout.write(raw); - process.exit(0); - } - - // Log non-ENOENT spawn errors (timeout, signal kill, etc.) so users - // know the security monitor did not run — fail-open with a warning. - if (result.error) { - process.stderr.write(`[InsAIts] Security monitor failed to run: ${result.error.message}\n`); - process.stdout.write(raw); - process.exit(0); - } - - // result.status is null when the process was killed by a signal or - // timed out. Check BEFORE writing stdout to avoid leaking partial - // or corrupt monitor output. Pass through original raw input instead. - if (!Number.isInteger(result.status)) { - const signal = result.signal || 'unknown'; - process.stderr.write(`[InsAIts] Security monitor killed (signal: ${signal}). Tool execution continues.\n`); - process.stdout.write(raw); - process.exit(0); - } - - if (result.stdout) process.stdout.write(result.stdout); - if (result.stderr) process.stderr.write(result.stderr); - - process.exit(result.status); -}); diff --git a/tests/hooks/hooks.test.js b/tests/hooks/hooks.test.js index 2a526b38..20c52487 100644 --- a/tests/hooks/hooks.test.js +++ b/tests/hooks/hooks.test.js @@ -527,24 +527,6 @@ async function runTests() { passed++; else failed++; - // insaits-security-wrapper.js tests - console.log('\ninsaits-security-wrapper.js:'); - - if ( - await asyncTest('passes through input unchanged when integration is disabled', async () => { - const stdinData = JSON.stringify({ - tool_name: 'Write', - tool_input: { file_path: 'src/index.ts', content: 'console.log("ok");' } - }); - const result = await runScript(path.join(scriptsDir, 'insaits-security-wrapper.js'), stdinData, { ECC_ENABLE_INSAITS: '' }); - assert.strictEqual(result.code, 0, `Exit code should be 0, got ${result.code}`); - assert.strictEqual(result.stdout, stdinData, 'Should pass stdin through unchanged'); - assert.strictEqual(result.stderr, '', 'Should stay silent when integration is disabled'); - }) - ) - passed++; - else failed++; - // check-console-log.js tests console.log('\ncheck-console-log.js:'); @@ -2025,20 +2007,6 @@ async function runTests() { passed++; else failed++; - if ( - test('InsAIts hook is opt-in and scoped to high-signal tool inputs', () => { - const hooksPath = path.join(__dirname, '..', '..', 'hooks', 'hooks.json'); - const hooks = JSON.parse(fs.readFileSync(hooksPath, 'utf8')); - const insaitsHook = hooks.hooks.PreToolUse.find(entry => entry.description && entry.description.includes('InsAIts')); - - assert.ok(insaitsHook, 'Should define an InsAIts PreToolUse hook'); - assert.strictEqual(insaitsHook.matcher, 'Bash|Write|Edit|MultiEdit', 'InsAIts hook should avoid matching every tool'); - assert.ok(insaitsHook.description.includes('ECC_ENABLE_INSAITS=1'), 'InsAIts hook should document explicit opt-in'); - assert.ok(insaitsHook.hooks[0].command.includes('insaits-security-wrapper.js'), 'InsAIts hook should execute through the JS wrapper'); - }) - ) - passed++; - else failed++; // plugin.json validation console.log('\nplugin.json Validation:');