Metadata-Version: 2.4
Name: ata-coder
Version: 2.4.5
Summary: ATA Coder — AI-powered coding assistant
Author: ATA Coder Team
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: colorama>=0.4.6
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: rich>=13.0.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: prompt-toolkit>=3.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: pytest-timeout>=2.0; extra == "dev"
Requires-Dist: tiktoken>=0.5.0; extra == "dev"
Dynamic: license-file

# ATA Coder v2.4.5

**AI-powered coding assistant — async, AST-aware, single config file.**

[English](#english) | [中文](#中文)

> **v2.4.5** — 🛡️ **Comprehensive Bug & Security Fix**: 19 bugs fixed — thread safety, SSRF IPv6, rate limiter leak, auth hardening, DRY refactoring, CI coverage. 12 files changed.
>
> > **v2.4.4** — 🔒 **Security Hardening**: 19 fixes across safety, storage, and reliability.
>
> > **v2.4.3** — 🧠 **Comprehensive Refactoring**: Memory overhaul, unified token counting, safety pipeline, tool call optimization. 60+ issues fixed.
>
> > **v2.4.2** — 🐾 **Clawd working state + Window tokens**: Clawd shows 'working' immediately. Status line shows window tokens (~120k) not cumulative (7.8M). Surrogate-safe session saves.
>
> > **v2.4.1** — 🗂️ **3-Part Session IDs + /resume**: Session ID: `xxxxxxxx-xxxxxxxx-xxxxxxxx` (workspace·timestamp·task). `/resume` lists sessions for current project folder. Resume by any 8-char hash.
>
> > **v2.4.0** — 💾 **Auto-Save Sessions**: Every conversation auto-saved to `~/.ata_coder/sessions/`. Hash-based session IDs. Resume by hash: `ata --resume xxxxxxxx`. Round 9 self-repair.
>
> > **v2.3.11** — ⚡ **Self-Bootstrapped Streaming + Crash Fixes**: 15 bugs found and fixed by **ATA Coder auditing its own source code** — round 7.5. Real-time shell/web output, full command display, subprocess hang fixes, surrogate crash fix.
>
> > **v2.3.10** — 🐛 **Self-Bootstrapped Bug Hunt**: 25 bugs found, 18 fixed by ATA Coder scanning its own source code. Semaphore leak, command injection, missing import, memory leak — round 7 of closed-loop self-repair.

> **v2.3.6** — 🧹 Code Quality Audit: version sync, CI/CD, ruff/mypy config.
> **v2.3.5** — 🤖 Security Audit v2: 23 findings, 20 fixed. Auth, shell/RCE, CORS.
> **v2.3.4** — 🤖 First self-bootstrapped audit.

---

## English

### Overview

ATA Coder is a CLI AI coding assistant compatible with OpenAI and Anthropic APIs. It runs on a **single-threaded asyncio event loop** — no threads, no race conditions, low memory. Features deterministic AST-based code editing, sub-agent pool, MCP support, and a built-in HTTP API server.

```bash
pip install ata-coder
```

### Architecture (v2.3.3)

```
asyncio Event Loop (single-threaded)
├── REPL (prompt_toolkit + Rich)
│     await controller.submit(task)
│     await event_queue.drain() → ui.on_event()
│
├── AgentController (asyncio.Task)
│     CoderAgent.run() → async LLM loop → await tool calls
│     BaseLLMClient (ABC) — unified OpenAI/Anthropic async interface
│     ExtensionManager → skill prompt aggregation
│     Keyword-based task classification (zero extra API calls)
│
├── Sub-Agent Tasks (asyncio.TaskGroup)
│     SubAgent 1..N: independent LLM, tools, context
│     asyncio.Semaphore → concurrency limit
│
└── MCP Clients (asyncio subprocess)
      StdioConnection → create_subprocess_exec + async read loop
      HTTPConnection → httpx.AsyncClient
```

### Key Features

| Feature | Description |
|---------|-------------|
| **Async Event Loop** | Single-threaded asyncio — zero race conditions, no thread overhead |
| **AST Code Editing** | libcst-based deterministic edits for Python, preserves all formatting |
| **Safe Rename** | `rename_symbol` tool — renames definitions + references, skips strings/comments |
| **Sub-Agent Pool** | Parallel sub-agents with isolated context, asyncio.Semaphore bounded |
| **Skill System** | Keyword-based auto-detection, single-skill activation for clean prompts |
| **MCP Support** | Model Context Protocol — cross-tool interoperability via stdio/HTTP |
| **Multimodal Vision** | `analyze_image` tool — vision model auto-falls back to main API config |
| **Diff Preview** | Colorized unified diff before file edits — green/red lines in terminal |
| **Session Persistence** | Save / resume / export conversation history by workspace |
| **Safety Pipeline** | Fool-proof validation → permissions → privilege → self-correction |
| **HTTP API Server** | SSE streaming, shell sessions, multi-session management |
| **One Dark Pro Theme** | Rich syntax highlighting for code blocks |
| **Web GUI** | SPA with SSE streaming, markdown, sidebar, command popup |

### Quick Start

```bash
# Install from PyPI (recommended)
pip install ata-coder

# Or install from source (development)
pip install -e .

ata                          # Interactive REPL
ata run "Add type hints"     # Single task
ata server --port 8080       # HTTP API server
ata --skill debugger         # With specific skill
ata --resume <session-id>    # Resume saved session
```

### Project Structure

```
ata_coder/
├── main.py              # CLI entry point (click) + asyncio.run()
├── agent.py             # Core agent: async run loop + tool execution
├── agent_controller.py  # asyncio.Task-based orchestrator
├── agent_subsystems.py  # Subsystem container dataclass
├── core/                # Extracted from agent.py
│   ├── events.py        # AgentEvent dataclasses
│   └── state.py         # AgentState dataclass
├── tools.py             # 15 built-in tools (incl. rename_symbol, analyze_image)
├── llm_client.py        # OpenAI-compatible async client (httpx.AsyncClient)
├── anthropic_client.py  # Anthropic Messages API async client
├── skills.py            # Folder-based skill manager
├── skill_extension.py   # Skill → Extension adapter
├── extension.py         # Plugin/extension system
├── sub_agent.py         # asyncio.Task-based sub-agent
├── sub_agent_manager.py # asyncio.Semaphore-bounded pool
├── event_queue.py       # asyncio.Queue-based event bus
├── mcp_client.py        # Async MCP (stdio + HTTP/SSE)
├── memory.py            # Persistent file-based memory
├── session.py           # Session save/load/search
├── change_tracker.py    # File change undo/redo
├── safety_guard.py      # Pattern-based risk analysis
├── fool_proof.py        # Unified pre-execution safety check
├── permissions.py       # Interactive allow/deny rules
├── privilege.py         # OS-aware privilege elevation
├── config.py            # Runtime config (reads settings.json only)
├── settings.py          # ~/.ata_coder/settings.json persistence
├── self_correct.py      # Error diagnosis + auto-fix (8 patterns)
├── system_prompt_builder.py
├── model_registry.py    # Model metadata + pricing
├── model_router.py      # Keyword-based complexity classification
├── commands.py          # Slash command registry (~40 commands)
├── repl_ui.py           # Rich/prompt-toolkit REPL + diff preview
├── server.py            # HTTP API server + SSE streaming
├── utils.py             # Shared utilities + API error helper
├── prompt_template.py   # {% if %} templating
├── task_planner.py      # Task decomposition
├── git_workflow.py      # Git integration
├── project.py           # Project auto-detection
├── skills/              # Built-in skill folders
├── extensions/          # Plugin directory
├── examples/            # Usage examples
├── tests/               # pytest suite
└── README.md
```

### Configuration

**settings.json is the single source of truth.** All config lives in `~/.ata_coder/settings.json`:

```json
{
  "env": {
    "ATA_CODER_BASE_URL": "https://api.deepseek.com",
    "ATA_CODER_API_KEY": "sk-...",
    "ATA_CODER_DEFAULT_MODEL": "deepseek-v4-pro",
    "ATA_CODER_DEFAULT_OPUS_MODEL": "deepseek-v4-pro",
    "ATA_CODER_DEFAULT_SONNET_MODEL": "deepseek-v4-pro",
    "ATA_CODER_DEFAULT_HAIKU_MODEL": "deepseek-v4-flash",
    "ATA_CODER_SUBAGENT_MODEL": "deepseek-v4-flash",
    "ATA_CODER_MAX_OUTPUT_TOKENS": "131072",
    "ATA_CODER_EFFORT_LEVEL": "max",
    "ATA_CODER_VISION_MODEL": "",
    "ATA_CODER_VISION_API_BASE": "",
    "ATA_CODER_VISION_API_KEY": ""
  },
  "complexity": {
    "auto_detect": true,
    "simple_max_chars": 60,
    "complex_min_chars": 500
  },
  "paths": {
    "data": "~/.ata_coder",
    "skills": "~/.ata_coder/skills",
    "sessions": "~/.ata_coder/sessions",
    "memory": "~/.ata_coder/memory",
    "changes": "~/.ata_coder/changes"
  },
  "permissions": {
    "allow": [
      "Bash(git:*)",
      "Bash(python:*)",
      "Bash(pip:*)",
      "Read(./**)",
      "Edit(./**/*.{py,pyi})",
      "Edit(./**/*.{json,md,txt,yml,yaml})"
    ],
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(sudo:*)",
      "Bash(curl:*)",
      "Bash(wget:*)",
      "Read(./.env)",
      "Read(./**/*.key)"
    ]
  }
}
```

- Vision model empty = auto-uses main model. No separate API config needed.
- Model names auto-strip `[1m]` suffix — write `deepseek-v4-pro`, not `deepseek-v4-pro[1m]`.
- API errors get friendly troubleshooting suggestions inline.

### Skills

Skills live in `skills/<name>/` folders with `SKILL.md` manifest (YAML frontmatter + markdown body). Single-skill activation via keyword matching — no extra LLM calls.

```
skills/weather-skill/
├── SKILL.md           # name, version, triggers, tools, I/O spec
├── handler.py         # Python entry point
├── utils.py           # Helpers
├── prompts/           # LLM prompt templates
├── resources/         # Static data
└── tests/             # pytest tests
```

### Commands

| Command | Description |
|---------|-------------|
| `/help` | Show help |
| `/skills` | List available skills |
| `/skill <name>` | Switch skill |
| `/review` | AI code review of git diff |
| `/fix [severity]` | Auto-fix review issues |
| `/undo [n]` | Undo file changes |
| `/changes` | List tracked changes |
| `/dry-run` | Toggle dry-run mode |
| `/save` | Save current session |
| `/resume <id>` | Resume saved session |
| `/sessions` | List/search session history |
| `/compact` | Compact conversation context |
| `/context` | Show token usage + cost |
| `/model <name>` | Change model at runtime |
| `/config` | Show current configuration |
| `/vision <img> [prompt]` | Analyze image |
| `/think` | Toggle thinking mode |
| `/extensions` | List loaded extensions |
| `/sub-agents` | List sub-agents |
| `/mcp search <q>` | Search MCP tools |
| `/permissions` | Show permission rules |
| `/git <sub>` | Git operations |
| `/plan <task>` | Task planning |
| `/remember` / `/recall` | Memory management |

### API Server

```bash
ata server --port 8080
```

| Endpoint | Description |
|----------|-------------|
| `POST /chat` | Non-streaming chat |
| `POST /chat/stream` | SSE streaming chat |
| `GET /health` | Health check |
| `GET /tools` | List tools |
| `GET /skills` | List skills |
| `GET /models` | List available models |
| `GET /sessions` | List sessions |
| `DELETE /sessions/<id>` | Delete session |
| `POST /api/shell` | Interactive shell |

```bash
# Streaming chat
curl -N -X POST http://localhost:8080/chat/stream \
  -H "Content-Type: application/json" \
  -d '{"message": "Explain async/await"}'

# Non-streaming
curl -X POST http://localhost:8080/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Write hello world", "skill": "general-coder"}'
```

### Design Patterns

| Pattern | Implementation |
|---------|---------------|
| **Async LLM** | `BaseLLMClient` ABC — `LLMClient` and `AnthropicClient` use `httpx.AsyncClient` |
| **Tool Pipeline** | SafetyCheck → PermissionCheck → PrivilegeCheck → Execute → SelfCorrect |
| **AST Editing** | libcst `CSTTransformer` — parse, match, replace, preserve formatting |
| **Cancellation** | `asyncio.Task.cancel()` + `asyncio.CancelledError` — no threading events |
| **Concurrency** | `asyncio.Semaphore` for sub-agent limits, `asyncio.gather()` for parallel tools |
| **Event Bus** | `asyncio.Queue` — agent task produces, UI task consumes |
| **Retry Jitter** | Exponential backoff + random jitter in LLM clients |
| **Circuit Breaker** | Consecutive-tool-failure counter (5 all-fail batches → break) |
| **Token Budget** | Auto-compact at 200k effective tokens, force-truncate at 95% of 1M max |
| **Diff Preview** | `difflib.unified_diff` + Rich colored output before file writes |

### 🧠 v2.4.3 Comprehensive Refactoring

60+ issues fixed across 15 files. Memory overhaul, unified token counting, safety pipeline unification.

| # | Area | Detail |
|---|------|--------|
| 1 | 🧠 **Memory** | Atomic writes, lazy loading, TF-IDF stopwords, cross-memory dedup, `/remember-suggestion` command |
| 2 | 🔢 **TokenCounter** | NEW unified service — model-aware encoding, per-message cache, batch counting, CJK fallback |
| 3 | 🛡️ **Safety** | Removed double permission check, self-correct goes through safety pipeline, explicit tool handlers |
| 4 | ⚡ **Compaction** | Sequential tools batched into single message, `_force_truncate` uses token weight |
| 5 | 🐛 **Fixes** | File cache invalidation on write, `rename_symbol` method type, system prompt cache on `/remember` |

### 🐾 v2.4.2 Clawd + Window Tokens Fix

| # | Fix | Detail |
|---|-----|--------|
| 1 | 🐾 Clawd | Shows 'working' immediately on task submit (was stuck thinking) |
| 2 | 📊 Status | Line shows window tokens (~120k) not cumulative (7.8M) |
| 3 | 🛡️ Sessions | Belt-and-suspenders surrogate stripping on all writes |
| 4 | 🔧 Cleanup | Reverted unintended skill file changes |

### 🗂️ v2.4.1 3-Part Session IDs + /resume

Session IDs now encode workspace, timestamp, and task in three 8-char hashes.

| # | Feature | Detail |
|---|---------|--------|
| 1 | 🗂️ **3-Part ID** | `xxxxxxxx-xxxxxxxx-xxxxxxxx` — workspace hash, time hash, task hash |
| 2 | 🔍 **//resume** | Lists all sessions in the current project folder |
| 3 | 🎯 **Any hash** | Resume with any of the three hashes: `ata --resume 12345678` |
| 4 | 📂 **Workspace scoped** | First hash = SHA256(workspace path)[:8] — groups sessions by project |

### 💾 v2.4.0 Auto-Save Sessions

Conversations are now automatically saved after every task — never lose your context again.

| # | Feature | Detail |
|---|---------|--------|
| 1 | 💾 **Auto-save** | Every conversation auto-saved to `~/.ata_coder/sessions/` on task completion |
| 2 | 🆔 **Hash-based IDs** | Session IDs use 8-char SHA256 hash: `add-type-hints-a3f8b91c` |
| 3 | 🔍 **Resume by hash** | `ata --resume a3f8b91c` — type just the 8-char hash suffix |
| 4 | 📁 **JSONL format** | Files named `{slug}-{hash}.jsonl`, each line = one message or tool call |
| 5 | 🔄 **Reuse on resume** | `--resume` reuses the existing session ID — no duplicate saves |

### 🛠️ v2.3.12 Self-Bootstrapped Quality Fixes

All 10 bugs found and fixed by **ATA Coder auditing its own source code** — round 8 of the closed-loop self-repair cycle.

| # | Severity | Fix |
|---|----------|-----|
| 1 | 🔴 Crash | `ToolStreamEvent` import added to `agent_tools.py` — was NameError on streaming tools |
| 2 | 🔴 Crash | `zip(tool_calls, results, strict=True)` — prevents silent data misalignment |
| 3 | 🟠 Fix | `raise ... from e` exception chaining in `anthropic_client.py` (3 sites) |
| 4 | 🟡 Fix | Threshold consistency: `<=` / `>=` across `ModelRouter` and `_ai_classify` |
| 5 | 🟢 Cleanup | Module-level logger in `config.py` (removed redundant per-call `getLogger`) |
| 6 | 🟢 Cleanup | E701 multi-statement splits in `change_tracker.py`, `anthropic_client.py`, `_workflow.py` |

### ⚡ v2.3.11 Self-Bootstrapped Streaming + Crash Fixes

All 15 fixes discovered by **ATA Coder auditing its own source code** — round 7.5 of the closed-loop self-repair cycle.

| # | Category | Fix |
|---|----------|-----|
| 1 | ⚡ Streaming | Shell output streams in real-time via `ToolStreamEvent` — no more frozen terminal |
| 2 | ⚡ Streaming | Web search shows backend progress: `🔍 Searching Bing...` → `✓ 5 results` |
| 3 | ⚡ Streaming | Web fetch shows download/extract progress in real-time |
| 4 | 👁️ Display | Shell commands displayed in full (was truncated to 70 chars) |
| 5 | 👁️ Display | SSE frontend receives full `args` object (was truncated `brief_args`) |
| 6 | 🔴 Crash | `_read_old_content` 2-tuple → 3-tuple cache unpack (regression from LRU timestamp) |
| 7 | 🔴 Crash | `_save_index` missing `sanitize_surrogates` → UTF-8 encode crash |
| 8 | 🔴 Crash | `BaseSubprocessTransport.__del__` closed pipe — explicit pipe cleanup in `finally` |
| 9 | 🔴 Crash | `import asyncio` in `__del__` fails during interpreter shutdown — cached reference |
| 10 | 🔴 Hang | `stdin=asyncio.subprocess.DEVNULL` prevents subprocess stdin-inherit freeze |
| 11 | 🟠 Fix | `--anthropic` CLI flag now sets `config.llm.use_anthropic` (was ignored) |
| 12 | 🟠 Fix | `chat_stream` error body now enriched with `enhance_api_error` (was lost) |
| 13 | 🟡 Test | Server tests skipped on Windows (`handle_request` blocks indefinitely) |
| 14 | 🟡 Test | Sub-agent tests fixed: `async def` + `@pytest.mark.asyncio` (4 tests) |
| 15 | 🟡 Test | Privilege test method names restored (7 missing underscores) |

### 🐛 v2.3.10 Self-Bootstrapped Bug Hunt

All 25 bugs in this release were found and 18 fixed by **ATA Coder scanning its own source code** — round 7 of the closed-loop "AI-driven self-repair" cycle. 7 findings confirmed as false positives (existing protections already in place).

| # | Severity | Finding | Fix |
|---|----------|---------|-----|
| 1 | 🔴 Critical | Semaphore leak in `spawn()` on exception | `try/finally` release |
| 2 | 🔴 Critical | `clear_finished()` doesn't release semaphore | Release per removed agent |
| 3 | 🔴 Critical | `agent_compact.py` missing `import json` | Added at module top |
| 4 | 🔴 Critical | PowerShell command injection in `wrap_privileged_command()` | `shlex.quote()` inner command |
| 5 | 🔴 Critical | Unparseable session timestamps never expire | `t=0` on failure (evict) |
| 6 | 🔴 High | Duplicate `_http` class attribute | Removed duplicate |
| 7 | 🔴 High | Dead CRITICAL check in `fool_proof.py` | Removed unreachable block |
| 8 | 🔴 High | Division by zero if `max_tokens=0` | `max(max_tokens, 1)` guard |
| 9 | 🔴 High | `except ImportError` never triggers | `if _yaml_mod is not None` |
| 10 | 🟡 Medium | Hardcoded complexity thresholds in `_ai_classify` | Read from `get_settings()` |
| 11 | 🟡 Medium | `Path.replace()` fails on Windows | `os.replace()` atomic |
| 12 | 🟡 Medium | `getattr(self, f"_fn_{key}")` arbitrary access | `_ALLOWED_BUILTINS` whitelist |
| 13 | 🟡 Medium | `rm -r -f /` not caught by safety regex | Broadened pattern |
| 14 | 🟡 Medium | Session file can exhaust memory | 100 MB size limit |
| 15 | 🟡 Medium | Inconsistent `errors="replace"` encoding | Unified across all writes |
| 16 | 🟡 Medium | `_deep_merge` list semantics unclear | Documented replace behavior |
| 17 | 🔵 Low | Path traversal in `_serve_static()` | ✅ Already protected (false positive) |
| 18 | 🔵 Low | `TextDeltaEvent` unused import | ✅ Used in `_streaming_chat()` (false positive) |

### 🧹 v2.3.9 Self-Bootstrapped Housekeeping & Hardening

All 10 bugs in this release were found and fixed by **ATA Coder scanning its own source code** — round 5 of the closed-loop "AI-driven self-repair" cycle. Plus 2 critical runtime fixes (`stream` parameter, `HAS_COLORAMA` import).

| # | Severity | Finding | Fix |
|---|----------|---------|-----|
| 1 | 🔴 Critical | `_run_loop()` lost `stream` closure variable (a192787) | Pass `stream` parameter explicitly |
| 2 | 🔴 Critical | `repl_theme.py` missing `HAS_COLORAMA` import | Restore `try: from colorama ...` guard |
| 3 | 🔴 Critical | `get_config()` threading.Lock adds complexity without benefit | Remove lock, document single-threaded design |
| 4 | 🟠 High | Event queue silently drops events when full | Log WARNING on `QueueFull` |
| 5 | 🟠 High | Vision provider hardcoded in tool description | Generic description referencing `VISION_*` env vars |
| 6 | 🟠 High | `SYSTEM_PROMPT` evaluated at import time | Convert to `__getattr__` lazy accessor |
| 7 | 🟡 Medium | File cache has no TTL | Add 30s TTL — re-read stale entries |
| 8 | 🟡 Medium | `SKIP_DIRS` missing common cache dirs | Add `.mypy_cache`, `.ruff_cache`, `.idea`, `.vs`, `.terraform` etc. |
| 9 | 🟡 Medium | No structured logging | `_SessionLogger` adapter injects `[session_id]` prefix |
| 10 | 🟡 Medium | `commands.py` 974 lines monolithic | Split to `commands/` package (4 sub-modules) |

**Package health**: `agent.py` 1199→829 lines (-31%), `server.py` 1067→823 (-23%), `main.py` 866→738 (-15%), `commands.py` → `commands/` package.

### 🔧 v2.3.8 Self-Bootstrapped Technical Debt Audit

Bug fixes from the project health scan — async test compat, agent/server refactoring, deprecated API cleanup.

| # | Severity | Finding | Fix |
|---|----------|---------|-----|
| 1 | 🔴 Critical | `test_chat_stream_yields_*` fails on Python 3.14 | `async def` + `async for` (5 tests) |
| 2 | 🔴 Critical | `skills.deactivate()` not called on exception | `finally` block in `run()` |
| 3 | 🟠 High | `_build_handlers()` may register mixin attrs | `callable()` guard |
| 4 | 🟠 High | `agent.py` 1199 lines | Extract 3 mixins: tools, routing, extension |
| 5 | 🟠 High | `server.py` 1067 lines | Extract `server_session.py`, `server_shell.py` |
| 6 | 🟡 Medium | `time.mktime` deprecated in Python 3.14 | `datetime.fromisoformat()` |
| 7 | 🟡 Medium | `_consecutive_failures` parameter confusion | Move constants into `_run_loop()` |
| 8 | 🟡 Medium | `_file_cache` LRU not implemented | Move-to-end on cache hit |
| 9 | 🟡 Medium | `AgentAPIHandler` class attr shared state | `__init__` copies to instance attrs |
| 10 | 🔵 Low | Version mismatch CLAUDE.md vs README | Sync to v2.3.8 |

### 🧹 v2.3.6 Self-Bootstrapped Code Quality Audit

All 24 findings in this release were audited by **ATA Coder scanning its own source code** — round 2 of the v2.3.5 closed-loop verification cycle, addressing code quality, testing, and DevOps.

| # | Severity | Finding | Fix |
|---|----------|---------|-----|
| 1 | 🔴 Critical | `main.py:__version__ = "2.3.4"` stale while `pyproject.toml` = `2.3.5` | Synced all three locations to `2.3.6` |
| 2 | 🔴 Critical | 4 config tests FAILED — env var overrides ignored by settings.json system | Updated to `get_settings()` mock pattern |
| 3 | 🔴 Critical | No CI/CD — tests never run on push | `.github/workflows/ci.yml` — matrix py3.10-3.13 + lint |
| 4 | 🟠 High | `sub_agent.py` LLMConfig missing `thinking_strength` | Passes `thinking_strength=config.llm.thinking_strength` |
| 5 | 🟠 High | `anthropic_client.py` inline `import os as _os` in `__init__` | Moved to module top-level |
| 6 | 🟠 High | `safety_guard.py` IEX regex: `IEX?\s*\(` matches `IE(` | Tightened to `\bIEX\s*\([^)]*\)` |
| 7 | 🟡 Medium | `memory.py` + `skills.py` duplicate yaml import pattern | Extracted `try_import_yaml()` to `utils.py` |
| 8 | 🟡 Medium | `ATA_CODER_ALLOW_ALL` silently allows all — no audit trail | `logger.warning()` on activation |
| 9 | 🟡 Medium | `out.txt`, `web/node_modules/` exposed in working tree | Added to `.gitignore` |
| 10 | 🟡 Medium | No ruff/mypy/pytest config in `pyproject.toml` | Added `[tool.ruff]`, `[tool.mypy]`, `[tool.pytest.ini_options]` |

---

### 🤖 v2.3.5 Self-Bootstrapped Security Audit

All 23 findings in this release were audited by **ATA Coder scanning its own source code** — the second closed-loop "AI-driven self-repair" verification. 20 fixed, 2 pre-existing mitigations confirmed, 1 deferred.

| # | Severity | Finding | Fix |
|---|----------|---------|-----|
| 1 | 🔴 Critical | `/api/shell` no auth — remote arbitrary command execution | Added `_require_auth` + `SafetyGuard.check_shell()` |
| 2 | 🔴 Critical | Auth logic backwards — denied all when no token set | `_check_auth()` returns `True` when no token configured |
| 3 | 🔴 Critical | Default `0.0.0.0` bind + wide CORS + no-auth endpoints | Default `127.0.0.1`; CORS reflects localhost only; `0.0.0.0` warns without token |
| 4 | 🟠 High | `/chat` and `/chat/stream` endpoints no authentication | Added `_require_auth()` to both |
| 5 | 🟠 High | Protected paths missing `.env`, cloud creds, Windows paths | Expanded to 30 entries; added suffix matching for dotfiles |
| 6 | 🟠 High | SSE logs leak LLM output (potential API keys, tokens) | `_sanitize_log()` redacts keys; downgraded to DEBUG |
| 7 | 🟠 High | Error responses leak internal paths (`str(e)` → client) | Generic "Internal server error" in chat handler |
| 8 | 🟠 High | PowerShell RCE vectors undetected (IEX, Invoke-*) | Added 5 new destructive patterns |
| 9 | 🟡 Medium | File read cache unbounded (memory leak on large projects) | LRU eviction at 50 entries |
| 10 | 🟡 Medium | Session store no TTL (agent instances never freed) | 30-minute `_evict_expired()` auto-cleanup |
| 11 | 🟡 Medium | `print()` instead of `logger` for runtime events | Replaced 3 `print()` calls with `logger.info()` |
| 12 | 🟡 Medium | Duplicate `@property` decorator on `vision_model` | Removed |
| 13 | 🟡 Medium | `shlex.split` called twice in `check_shell` | Reused cached `cmd_tokens` |
| 14 | 🟡 Medium | Sync `httpx.Client` blocks async event loop | `_tool_web_search`/`_tool_web_fetch` via `run_in_executor` |
| 15 | 🟡 Medium | Sync `os.walk` blocks event loop in `_tool_grep` | Filesystem traversal runs in thread pool |
| 16 | 🟡 Medium | `requirements.txt` missing `click>=8.0` | Synced with `pyproject.toml` |
| 17 | 🟡 Medium | PowerShell hardcoded (crashes on Linux/macOS) | Platform detection: PS on Windows, bash elsewhere |
| 18 | 🔵 Low | API keys in plaintext `settings.json` | Already mitigated — `chmod 0600` since v2.3.4 |
| 19 | 🔵 Low | XSS via `innerHTML` in Web UI | Already mitigated — `escapeHtml()` on all paths |
| 20 | 🔵 Low | Sub-agent concurrency unlimited | Pre-existing: `asyncio.Semaphore(max_sub_agents)` |
| 21 | 🔵 Low | Config field naming (`thinking_strength` vs `effort_level`) | Documented — backward compatibility constraint |
| 22 | 🔵 Low | CSRF protection (no token on state-changing endpoints) | Noted for future cookie-auth scenario |
| 23 | 🔵 Low | Hardcoded default API endpoint | Documented — intentional project default |

---

### 🤖 v2.3.4 Self-Bootstrapped Security Audit

All 6 findings in this release were discovered by **ATA Coder scanning its own source code** — the first closed-loop "AI-driven self-repair" verification for this project.

| # | Severity | Finding | Fix |
|---|----------|---------|-----|
| 1 | 🔴 High | Server auth allowed all when no token set | Default deny + CORS restricted to localhost:3000 |
| 2 | 🔴 Medium | HTML parser boolean flag leaked content on nested tags | `_skip_count` counter replaces `_skip` bool |
| 3 | 🔴 Medium | API keys stored plaintext without file permission lock | `chmod 0600` after every `settings.json` write |
| 4 | 🔴 Medium | Shell command guard bypassable (case, encoding, find -delete) | Added `find -delete`, `shred`, `dd of=`, cmd-sub patterns |
| 5 | 🟡 Low | Model registry substring-match caused false pricing hits | Removed substring fallback entirely |
| 6 | 🟡 Medium | CST renamers had ~60 lines of duplicated `leave_Name`/`leave_Call` | Extracted `_SymbolRenamer` base class |

**Bugs fixed in v2.3.3 (hotfixes):**
- CST import guard crash when libcst not installed
- `_summarise_messages` missing `async def` → SyntaxError
- Stale `TaskPlanner` instantiation → NameError at startup
- Nested `asyncio.run()` crash (prompt_toolkit + asyncio)
- Clawd shutdown not awaited on `/quit` exit path
- Welcome screen model labels (opus/sonnet/haiku)

---

## 中文

### 概述

ATA Coder 是一个命令行 AI 编码助手，兼容 OpenAI / Anthropic API。基于 **单线程 asyncio 事件循环** — 无线程、无竞态、低内存。配备确定性 AST 代码编辑、子 Agent 池、MCP 支持和内置 HTTP API 服务。

### 架构 (v2.3.3)

```
asyncio 事件循环（单线程）
├── REPL (prompt_toolkit + Rich)
│     await controller.submit(task)
│     await event_queue.drain() → ui.on_event()
│
├── AgentController (asyncio.Task)
│     CoderAgent.run() → 异步 LLM 循环 → await 工具调用
│     BaseLLMClient (ABC) — 统一 OpenAI/Anthropic 异步接口
│     ExtensionManager → Skill 提示聚合
│     关键词任务分类（零额外 API 调用）
│
├── 子 Agent (asyncio.TaskGroup)
│     SubAgent 1..N: 独立 LLM、工具、上下文
│     asyncio.Semaphore → 并发限制
│
└── MCP 客户端 (asyncio subprocess)
      StdioConnection → create_subprocess_exec + 异步读取
```

### 核心特性

| 特性 | 说明 |
|------|------|
| **异步事件循环** | 单线程 asyncio — 零竞态、无线程开销 |
| **AST 代码编辑** | libcst 确定性 Python 编辑，完美保留格式 |
| **安全重命名** | `rename_symbol` 工具 — 改名不碰字符串和注释 |
| **子 Agent 池** | 独立上下文并行执行，信号量限制并发 |
| **Skill 系统** | 关键词自动检测，单 Skill 激活防提示稀释 |
| **MCP 支持** | Model Context Protocol — 跨工具互操作 |
| **多模态视觉** | `analyze_image` — 视觉模型未设置自动用主模型 |
| **Diff 预览** | 编辑前彩色 unified diff，终端红绿高亮 |
| **会话持久化** | 按工作区保存/恢复/导出对话历史 |
| **API 服务** | SSE 流式、Shell 会话、多会话管理 |
| **安全管线** | 防呆 → 权限 → 特权 → 自校正 |

### 快速开始

```bash
# 从 PyPI 安装（推荐）
pip install ata-coder

# 或从源码安装（开发模式）
pip install -e .

ata                          # 交互模式
ata run "添加类型注解"        # 单任务
ata server --port 8080       # API 服务
```

### 配置

**settings.json 是唯一配置源。** 所有配置在 `~/.ata_coder/settings.json`：

```json
{
  "env": {
    "ATA_CODER_BASE_URL": "https://api.deepseek.com",
    "ATA_CODER_API_KEY": "sk-...",
    "ATA_CODER_DEFAULT_MODEL": "deepseek-v4-pro",
    "ATA_CODER_VISION_MODEL": "",
    "ATA_CODER_VISION_API_BASE": "",
    "ATA_CODER_VISION_API_KEY": ""
  }
}
```

- 视觉模型留空 = 自动用主模型，无需单独配置
- 模型名自动剥离 `[1m]` 后缀
- API 错误自动附带友好修复建议

### 常用命令

| 命令 | 说明 |
|------|------|
| `/help` | 帮助 |
| `/skills` | 列出 Skill |
| `/review` | AI 审查代码 |
| `/undo [n]` | 撤销变更 |
| `/save` | 保存会话 |
| `/resume <id>` | 恢复会话 |
| `/compact` | 压缩上下文 |
| `/context` | Token 用量 |
| `/model <name>` | 切换模型 |
| `/vision <图片>` | 视觉分析 |
| `/config` | 查看配置 |

### API 服务

```bash
ata server --port 8080
```

```bash
# SSE 流式
curl -N -X POST http://localhost:8080/chat/stream \
  -H "Content-Type: application/json" \
  -d '{"message": "解释 async/await"}'
```

### 🧠 v2.4.3 全面重构

跨 15 个文件修复 60+ 问题。记忆系统重构、统一 Token 计算、安全管道优化、工具调用优化。

| # | 领域 | 说明 |
|---|------|------|
| 1 | 🧠 **记忆系统** | 原子写入、延迟加载、TF-IDF 停用词过滤、跨记忆去重、`/remember-suggestion` 命令 |
| 2 | 🔢 **TokenCounter** | 新建统一服务 — 模型感知编码、消息缓存、批量计数、CJK 回退 |
| 3 | 🛡️ **安全管道** | 移除双重权限检查、自校正走完整安全管道、显式工具处理器注册 |
| 4 | ⚡ **压缩优化** | 顺序工具调用合并为单条消息、`_force_truncate` 按 token 权重截断 |
| 5 | 🐛 **Bug 修复** | 写入后文件缓存立即失效、`rename_symbol` method 类型、`/remember` 刷新提示缓存 |

### 🐾 v2.4.2 Clawd + 窗口 Token 修复

| # | 修复 | 说明 |
|---|------|------|
| 1 | 🐾 Clawd | 提交任务立刻显示工作中（之前卡在思考） |
| 2 | 📊 状态栏 | 显示窗口 token (~120k) 而非累计 (7.8M) |
| 3 | 🛡️ 会话 | 双重 surrogate 过滤保护所有写入 |
| 4 | 🔧 清理 | 回滚意外提交的 skill 文件改动 |

### 🗂️ v2.4.1 三段哈希会话 ID + /resume

三段哈希编码工作区、时间戳和任务。

| # | 特性 | 说明 |
|---|------|------|
| 1 | 🗂️ **三段 ID** | `xxxxxxxx-xxxxxxxx-xxxxxxxx` — 工作区哈希·时间哈希·任务哈希 |
| 2 | 🔍 **//resume** | 列出当前项目文件夹所有会话 |
| 3 | 🎯 **任意哈希** | 用三段中任意一个哈希恢复：`ata --resume 12345678` |
| 4 | 📂 **工作区隔离** | 第一段 = SHA256(工作区路径)[:8] — 按项目分组 |

### 💾 v2.4.0 会话自动保存

每轮对话自动保存 —— 再也不丢上下文。

| # | 特性 | 说明 |
|---|------|------|
| 1 | 💾 **自动保存** | 任务完成后自动存入 `~/.ata_coder/sessions/` |
| 2 | 🆔 **哈希 ID** | 8 位 SHA256 哈希：`add-type-hints-a3f8b91c` |
| 3 | 🔍 **哈希恢复** | `ata --resume a3f8b91c` — 只输 8 位哈希即可 |
| 4 | 📁 **JSONL 格式** | 文件名 `{摘要}-{哈希}.jsonl`，每行一条消息或工具调用 |
| 5 | 🔄 **恢复复用** | `--resume` 复用原有 session ID 避免重复存储 |

### 🛠️ v2.3.12 自举质量修复

全部 10 个 bug 由 **ATA Coder 审计自身源码** 发现并修复——第八轮闭环自修复。

| # | 严重度 | 修复 |
|---|--------|------|
| 1 | 🔴 崩溃 | `ToolStreamEvent` 导入添加到 `agent_tools.py` — 流式工具 NameError |
| 2 | 🔴 崩溃 | `zip(tool_calls, results, strict=True)` — 防止数据静默错位 |
| 3 | 🟠 修复 | `raise ... from e` 异常链在 `anthropic_client.py`（3 处） |
| 4 | 🟡 修复 | 阈值一致性：`ModelRouter` 和 `_ai_classify` 统一 `<=` / `>=` |
| 5 | 🟢 清理 | `config.py` 模块级 logger（移除冗余的每次调用 getLogger） |
| 6 | 🟢 清理 | E701 多语句拆分：`change_tracker.py`、`anthropic_client.py`、`_workflow.py` |

### ⚡ v2.3.11 自举流式输出 + 崩溃修复

全部 15 项修复由 **ATA Coder 审计自身源码** 发现——第七轮半闭环自修复。

| # | 类别 | 修复 |
|---|------|------|
| 1 | ⚡ 流式 | Shell 输出实时流式传输 — 不再死盯黑屏等待 |
| 2 | ⚡ 流式 | Web 搜索显示后端进度：`🔍 正在搜索 Bing...` → `✓ 5 条结果` |
| 3 | ⚡ 流式 | Web 抓取实时显示下载/提取进度 |
| 4 | 👁️ 显示 | Shell 命令完整展示（之前截断到 70 字符） |
| 5 | 👁️ 显示 | SSE 前端接收完整 `args` 对象（之前是截断的 `brief_args`） |
| 6 | 🔴 崩溃 | `_read_old_content` 2 元组 → 3 元组缓存解包（LRU 引入的回归） |
| 7 | 🔴 崩溃 | `_save_index` 缺少 `sanitize_surrogates` → UTF-8 编码崩溃 |
| 8 | 🔴 崩溃 | `BaseSubprocessTransport.__del__` 管道已关闭 — finally 中显式关闭 |
| 9 | 🔴 崩溃 | `__del__` 中 `import asyncio` 解释器关闭时失败 — 缓存引用 |
| 10 | 🔴 卡死 | `stdin=asyncio.subprocess.DEVNULL` 防止子进程继承 stdin 卡死 |
| 11 | 🟠 修复 | `--anthropic` CLI 标志写入 `config.llm.use_anthropic`（之前被忽略） |
| 12 | 🟠 修复 | `chat_stream` 错误体用 `enhance_api_error` 丰富（之前丢失） |
| 13 | 🟡 测试 | Windows 跳过服务端测试（`handle_request` 永久阻塞） |
| 14 | 🟡 测试 | 子 Agent 测试修复：`async def` + `@pytest.mark.asyncio`（4 个） |
| 15 | 🟡 测试 | 权限测试方法名恢复（7 个缺失下划线） |

### 🐛 v2.3.10 自举 Bug 狩猎

本版本全部 25 个 bug 由 **ATA Coder 扫描自身源码** 发现，18 个已修复——第七轮闭环验证。7 项确认为误报（已有防护）。

| # | 严重度 | 发现 | 修复 |
|---|--------|------|------|
| 1 | 🔴 严重 | `spawn()` 异常时信号量泄漏 | `try/finally` 释放 |
| 2 | 🔴 严重 | `clear_finished()` 不释放信号量 | 每个 agent 释放一个槽位 |
| 3 | 🔴 严重 | `agent_compact.py` 缺少 `import json` | 模块顶部添加 |
| 4 | 🔴 严重 | PowerShell 命令注入 | `shlex.quote()` 包装 |
| 5 | 🔴 严重 | 时间戳解析失败 → 永不过期 | 失败时 `t=0`（逐出） |
| 6 | 🔴 高 | 重复 `_http` 类属性 | 删除重复 |
| 7 | 🔴 高 | `fool_proof.py` 死代码 CRITICAL 检查 | 删除不可达代码块 |
| 8 | 🔴 高 | `max_tokens=0` 除零错误 | `max(max_tokens, 1)` |
| 9 | 🔴 高 | `except ImportError` 永远不触发 | `if _yaml_mod is not None` |
| 10 | 🟡 中 | `_ai_classify` 硬编码阈值 | 从 `get_settings()` 读取 |
| 11 | 🟡 中 | `Path.replace()` Windows 不兼容 | `os.replace()` |
| 12 | 🟡 中 | 模板 `getattr` 任意访问 | `_ALLOWED_BUILTINS` 白名单 |
| 13 | 🟡 中 | `rm -r -f /` 未被检测 | 拓宽正则模式 |
| 14 | 🟡 中 | 会话文件可能导致内存耗尽 | 100 MB 大小限制 |
| 15 | 🟡 中 | 编码错误处理不一致 | 统一使用 `errors="replace"` |
| 16 | 🟡 中 | `_deep_merge` 列表语义不清 | 文档化替换行为 |
| 17 | 🔵 低 | `_serve_static()` 路径遍历 | ✅ 已有防护（误报） |
| 18 | 🔵 低 | `TextDeltaEvent` 未使用 | ✅ 在 `_streaming_chat()` 使用（误报） |

### 🧹 v2.3.9 自举修缮与加固

本版本全部 10 个 bug 由 **ATA Coder 扫描自身源码** 发现并修复——第五轮闭环验证。另修复 2 个关键运行时 bug（`stream` 参数丢失、`HAS_COLORAMA` 导入缺失）。

| # | 严重度 | 发现 | 修复 |
|---|--------|------|------|
| 1 | 🔴 严重 | `_run_loop()` 丢失 `stream` 闭包变量 | 显式传递 `stream` 参数 |
| 2 | 🔴 严重 | `repl_theme.py` 缺少 `HAS_COLORAMA` 导入 | 恢复 `try: from colorama ...` |
| 3 | 🔴 严重 | `get_config()` 不必要的线程锁 | 移除锁，文档化单线程设计 |
| 4 | 🟠 高 | 事件队列满时静默丢弃 | `QueueFull` 时记录 WARNING |
| 5 | 🟠 高 | 视觉模型描述硬编码提供商 | 通用描述，引用 `VISION_*` 环境变量 |
| 6 | 🟠 高 | `SYSTEM_PROMPT` 导入时求值 | 改为 `__getattr__` 懒加载 |
| 7 | 🟡 中 | 文件缓存无 TTL | 添加 30s TTL |
| 8 | 🟡 中 | `SKIP_DIRS` 遗漏常见缓存目录 | 新增 `.mypy_cache`、`.idea`、`.terraform` 等 |
| 9 | 🟡 中 | 无结构化日志 | `_SessionLogger` 适配器注入 `[session_id]` |
| 10 | 🟡 中 | `commands.py` 974 行单体文件 | 拆分为 `commands/` 包（4 个子模块） |

### 🔧 v2.3.8 自举技术债审计

| # | 严重度 | 发现 | 修复 |
|---|--------|------|------|
| 1 | 🔴 严重 | Python 3.14 测试不兼容 | `async def` + `async for` |
| 2 | 🔴 严重 | 异常路径未清理技能状态 | `finally` 块调用 `deactivate()` |
| 3 | 🟠 高 | `agent.py` 1199 行 | 提取 3 个 Mixin |
| 4 | 🟠 高 | `server.py` 1067 行 | 提取 session/shell 模块 |
| 5 | 🟡 中 | `time.mktime` 已弃用 | `datetime.fromisoformat()` |
| 6 | 🟡 中 | LRU 缓存驱逐未实现 | 命中时 move-to-end |

### 🧹 v2.3.6 自举代码质量审计

本次版本全部 24 个质量问题均由 **ATA Coder 扫描自身源码审计** — v2.3.5 闭环验证的第二轮，针对代码质量、测试和 DevOps。

| # | 严重度 | 发现 | 修复 |
|---|--------|------|------|
| 1 | 🔴 严重 | `main.py:__version__ = "2.3.4"` 过期，与 `pyproject.toml` 不一致 | 三处同步至 `2.3.6` |
| 2 | 🔴 严重 | 4 个配置测试 FAILED — 环境变量被 settings.json 系统忽略 | 改用 `get_settings()` mock 模式 |
| 3 | 🔴 严重 | 无 CI/CD — push 时从不运行测试 | `.github/workflows/ci.yml` — 矩阵 py3.10-3.13 + lint |
| 4 | 🟠 高危 | `sub_agent.py` LLMConfig 遗漏 `thinking_strength` | 传递 `thinking_strength=config.llm.thinking_strength` |
| 5 | 🟠 高危 | `anthropic_client.py` 构造函数内 `import os as _os` | 移至模块顶层 |
| 6 | 🟠 高危 | `safety_guard.py` IEX 正则 `IEX?\s*\(` 可匹配 `IE(` | 收紧为 `\bIEX\s*\([^)]*\)` |
| 7 | 🟡 中危 | `memory.py` + `skills.py` 重复 yaml 导入模式 | 提取 `try_import_yaml()` 至 `utils.py` |
| 8 | 🟡 中危 | `ATA_CODER_ALLOW_ALL` 静默放行 — 无审计记录 | 激活时 `logger.warning()` |
| 9 | 🟡 中危 | `out.txt`、`web/node_modules/` 暴露在工作区 | 加入 `.gitignore` |
| 10 | 🟡 中危 | `pyproject.toml` 缺少 ruff/mypy/pytest 配置 | 添加 `[tool.ruff]`、`[tool.mypy]`、`[tool.pytest.ini_options]` |

---

### 🤖 v2.3.5 自举安全审计

本次版本全部 23 个安全漏洞均由 **ATA Coder 扫描自身源码审计** — 项目第二次"AI 驱动自我修复"闭环验证。修复 20 项，确认 2 项已有缓解措施，1 项延后。

| # | 严重度 | 发现 | 修复 |
|---|--------|------|------|
| 1 | 🔴 严重 | `/api/shell` 无认证 — 远程任意命令执行 | 添加 `_require_auth` + `SafetyGuard.check_shell()` |
| 2 | 🔴 严重 | 认证逻辑颠倒 — 未设 token 时拒绝所有请求 | 无 token 时返回 `True`（放行），有 token 时正确校验 |
| 3 | 🔴 严重 | 默认 `0.0.0.0` 绑定 + 宽 CORS + 无认证端点 | 默认 `127.0.0.1`；CORS 仅回显 localhost；`0.0.0.0` 无 token 时警告 |
| 4 | 🟠 高危 | `/chat` 和 `/chat/stream` 端点无认证 | 两个端点均添加 `_require_auth()` |
| 5 | 🟠 高危 | 受保护路径缺少 `.env`、云凭据、Windows 路径 | 扩展至 30 项；添加 dotfile 后缀匹配 |
| 6 | 🟠 高危 | SSE 日志泄露 LLM 输出（可能含 API 密钥） | `_sanitize_log()` 脱敏；降级为 DEBUG |
| 7 | 🟠 高危 | 错误响应泄露内部路径（`str(e)` → 客户端） | Chat 处理器返回通用 "Internal server error" |
| 8 | 🟠 高危 | PowerShell RCE 向量未检测（IEX, Invoke-*） | 新增 5 个攻击模式 |
| 9 | 🟡 中危 | 文件读取缓存无上限（大项目内存泄漏） | 50 条目 LRU 淘汰 |
| 10 | 🟡 中危 | 会话存储无过期（Agent 实例永不释放） | 30 分钟 `_evict_expired()` 自动清理 |
| 11 | 🟡 中危 | `print()` 替代 logger 记录运行时事件 | 3 处替换为 `logger.info()` |
| 12 | 🟡 中危 | `vision_model` 重复 `@property` 装饰器 | 已移除 |
| 13 | 🟡 中危 | `check_shell` 中 `shlex.split` 重复调用 | 复用缓存的 `cmd_tokens` |
| 14 | 🟡 中危 | 同步 `httpx.Client` 阻塞异步事件循环 | `_tool_web_search`/`_tool_web_fetch` 通过 `run_in_executor` 运行 |
| 15 | 🟡 中危 | 同步 `os.walk` 阻塞事件循环 | 文件系统遍历在线程池中运行 |
| 16 | 🟡 中危 | `requirements.txt` 缺少 `click>=8.0` | 与 `pyproject.toml` 同步 |
| 17 | 🟡 中危 | PowerShell 硬编码（Linux/macOS 崩溃） | 平台检测：Windows 用 PS，其他用 bash |
| 18 | 🔵 低危 | API 密钥明文存储在 `settings.json` | 自 v2.3.4 已有 `chmod 0600` |
| 19 | 🔵 低危 | Web UI `innerHTML` XSS 风险 | 已有 `escapeHtml()` 覆盖所有路径 |
| 20 | 🔵 低危 | 子 Agent 并发无限制 | 已有 `asyncio.Semaphore(max_sub_agents)` |
| 21 | 🔵 低危 | 配置字段命名不一致（`thinking_strength` vs `effort_level`） | 记录 — 向后兼容约束 |
| 22 | 🔵 低危 | CSRF 保护（状态变更端点无 token） | 留待未来 cookie 认证场景 |
| 23 | 🔵 低危 | 硬编码默认 API 端点 | 记录 — 项目有意为之的默认值 |

---

### 🤖 v2.3.4 自举安全审计

本次版本全部 6 个安全漏洞均由 **ATA Coder 扫描自身源码发现并建议修复** — 项目首次实现"AI 驱动自我修复"的闭环验证。

| # | 严重度 | 发现 | 修复 |
|---|--------|------|------|
| 1 | 🔴 高 | Server 无 token 时允许所有连接 | 默认拒绝 + CORS 限制为 localhost:3000 |
| 2 | 🔴 中 | HTML 解析器布尔标志导致嵌套标签内容泄露 | `_skip_count` 计数器替代 `_skip` 布尔值 |
| 3 | 🔴 中 | API 密钥明文存储无文件权限保护 | 每次写入 `settings.json` 后 `chmod 0600` |
| 4 | 🔴 中 | Shell 命令拦截可被绕过（大小写、编码、find -delete） | 新增 `find -delete`、`shred`、`dd of=`、命令替换模式 |
| 5 | 🟡 低 | 模型注册表子串匹配导致错误定价 | 彻底移除子串回退 |
| 6 | 🟡 中 | CST 重命名器约 60 行重复代码 | 提取 `_SymbolRenamer` 基类 |

**v2.3.3 紧急修复的 Bug：**
- libcst 未安装时 CST 类 import 崩溃
- `_summarise_messages` 遗漏 `async def` → SyntaxError
- 残留 `TaskPlanner` 实例化 → 启动 NameError
- `prompt_async` vs `asyncio.run()` 嵌套崩溃
- `/quit` 退出路径未 await Clawd shutdown
- 欢迎屏模型标签 (opus/sonnet/haiku)

---

## License

MIT — see [LICENSE](LICENSE)
