diff --git a/docs/architecture/architecture-core.md b/docs/architecture/architecture-core.md
new file mode 100644
index 00000000..0282b7f3
--- /dev/null
+++ b/docs/architecture/architecture-core.md
@@ -0,0 +1,205 @@
+# NeoCode 构架设计分析(聚焦核心决策版 - By fanfeilong)
+
+**版本:** 核心决策草案
+**来源参考:** `architecture-v3.remote.md`
+**定位:** 解释 NeoCode 为什么必须长成这样,而不是罗列当前实现模块。
+
+---
+
+## 1. 系统驱动
+
+NeoCode 的比较对象不是单次 LLM 会话,而是 Claude Code、Codex 这类已经具备 Agent Loop、工具调用和代码修改能力的 AI Coding 工具。
+因此本文不把“能多轮调用工具”当成差异化理由;那是入场券,不是架构说服力。
+
+NeoCode 真正要回答的是:在已有 AI Coding 工具存在的情况下,为什么还需要一个本地优先、多端对等、模型中立、可审计可恢复的 Agent 架构。
+
+| 场景压力 | 系统必须 | 否则 |
+|----------|----------|------|
+| 用户需要掌握代码、会话、密钥和恢复点 | 把核心状态留在用户控制环境内 | Agent 变成云端或厂商控制面的一部分 |
+| 同一个 Agent 能力要被 TUI、Web、Desktop、IM、脚本共享 | 提供统一控制入口 | 每个入口形成不同状态、权限、事件和审批语义 |
+| 工具、MCP、远程执行都会产生真实副作用 | 建立统一副作用安全边界 | 安全策略随工具和客户端分裂,审计无法闭合 |
+| 模型市场和厂商能力变化很快 | 隔离模型协议、流式格式和错误语义 | 系统核心被某个模型 API 绑定 |
+| 用户希望远程触发工作区执行,但不暴露机器 | 使用受限能力的反向远程执行 | 远程能力退化成开放端口或通用 Shell |
+| 长任务需要跨轮次恢复和解释 | 持久化任务过程、审批、工具结果和恢复点 | 出错后无法追踪、无法回滚、无法解释 |
+
+---
+
+## 2. 系统构架(Overview)
+
+以下 overview 图保留自 v3 架构文档,用来说明当前系统形态。
+核心决策版不按图中的组件逐个展开,而是解释这些组件背后的构架必然性。
+
+```mermaid
+graph TD
+ subgraph Client["客户端"]
+ direction LR
+ TUI["TUI"] ~~~ Web["Web"] ~~~ DT["Desktop"] ~~~ FS["飞书"]
+ end
+
+ GW["Gateway
RPC 路由 · 流中继 · 认证"]
+ RT["Runtime
ReAct 循环编排"]
+ PR["Provider
模型适配"]
+ TL["Tools
工具执行 + 安全"]
+ CTX["Context
Prompt 构建"]
+ SESS["Session
SQLite"]
+ RN["Runner
远程执行"]
+
+ DB[("SQLite")]
+
+ Client -->|"JSON-RPC"| GW
+ GW --> RT
+ RT --> PR & TL & CTX & SESS
+ GW -.->|"SSE/WS 事件"| Client
+ GW -.->|"WS 反向连接"| RN
+ RT -.->|"HTTPS"| LLM["模型 API"]
+
+ style GW fill:#fb923c,stroke:#fb923c,color:#0f172a
+ style RT fill:#34d399,stroke:#34d399,color:#0f172a
+ style PR fill:#a78bfa,stroke:#a78bfa,color:#0f172a
+ style TL fill:#fbbf24,stroke:#fbbf24,color:#0f172a
+ style CTX fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style SESS fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style RN fill:#fb7185,stroke:#fb7185,color:#0f172a
+```
+
+这张图的关键不是组件数量,而是控制方向:
+
+- 客户端只进入统一控制入口。
+- 任务循环统一推进模型、工具、上下文和状态。
+- 模型只产生推理事件和行动意图。
+- 工具边界负责把行动意图变成受控副作用。
+- 状态边界记录会话、审计和恢复事实。
+- 远程执行端是受限能力,不是通用 Shell。
+
+---
+
+## 3. 核心构架决策
+
+| 优先级 | 核心决策 | Why | 如果不这样 | 代价 |
+|--------|----------|-----|------------|------|
+| P0 | 本地控制权 | NeoCode 的前提是用户掌握代码、会话、密钥、审批和恢复点 | 系统会退化成依赖厂商或云端控制面的 Agent | 需要承担本地状态、一致性和数据生命周期 |
+| P0 | 统一副作用安全边界 | 文件、Shell、MCP、远程执行的风险必须用同一套裁决和审计覆盖 | 工具越多,安全语义越分裂,审批和恢复点无法闭合 | 所有工具接入都必须声明能力、校验参数、接受裁决 |
+| P1 | 统一控制入口 | 多端是同一 Agent 能力的不同入口,不应产生多套任务事实 | TUI、Web、IM、脚本各自形成状态、取消、审批和事件语义 | 控制入口成为关键路径,必须轻量少状态 |
+| P1 | 模型中立边界 | NeoCode 不能被某个模型厂商的协议和能力形态绑定 | 切换模型会影响任务循环、工具语义和客户端行为 | 厂商高级能力需要先抽象后进入核心 |
+| P1 | 可恢复任务事实 | 长任务必须能解释读了什么、改了什么、谁批准了什么、为什么结束 | 会话中断不可恢复,AI 修改不可回滚,事故无法追踪 | 需要持久化过程、审批、工具结果和恢复点 |
+| P2 | 受限反向远程执行 | 远程触发工作区执行不能要求用户暴露机器,也不能变成通用 Shell | 需要开放入站端口,或形成过宽远程执行能力 | 需要管理连接、心跳、能力范围和过期 |
+| 基础能力 | 任务循环 | Agent Loop 是 AI Coding 工具的基本内核,用于承载推理、行动、观察和验收 | 没有它就不是完整 Coding Agent | 它不是 NeoCode 的差异化重点,但必须稳定、可暂停、可验收 |
+
+---
+
+## 4. 构架(中文伪代码)
+
+下面不是实现方案,而是 NeoCode 的构架语义。
+
+```text
+当客户端发来请求:
+ 确认身份
+ 判断是否有权执行这个控制动作
+
+ 如果请求不合法:
+ 拒绝,并记录原因
+
+ 如果请求合法:
+ 创建或恢复任务
+ 发布“任务开始”
+ 交给任务循环推进
+```
+
+```text
+任务循环持续推进,直到出现明确终态:
+ 构建模型上下文
+ 调用模型继续推理
+
+ 如果模型输出文本:
+ 发布为进度事件
+
+ 如果模型提出行动意图:
+ 交给工具副作用边界
+ 把执行结果或拒绝原因写回任务
+ 进入下一轮
+
+ 如果模型给出候选最终答案:
+ 做完成度检查和必要验证
+
+ 如果验收通过:
+ 保存最终答案,发布“任务完成”
+
+ 如果还有可修复缺口:
+ 把缺口证据写回任务,进入下一轮
+
+ 如果失败、无法继续、被取消或超过限制:
+ 保存终止原因,发布“任务停止”
+```
+
+```text
+处理模型提出的行动意图:
+ 检查行动格式
+ 判断副作用类型和目标范围
+ 根据主体、会话、工具、目标、风险和权限指纹做安全裁决
+
+ 如果拒绝:
+ 不执行,把拒绝原因返回任务循环
+
+ 如果需要审批:
+ 暂停任务,向客户端发出权限请求
+ 等待人类允许或拒绝
+
+ 如果允许执行:
+ 对高风险修改先创建恢复点
+ 执行工具行动
+ 记录输入、输出、审批和审计事实
+ 把工具结果返回任务循环
+```
+
+关键点:
+
+- 多端请求进入同一控制面。
+- 任务循环承载 Agent 的基础执行语义。
+- 模型意图必须经过副作用边界。
+- 最终答案必须经过系统验收。
+
+---
+
+## 5. 运行机制
+
+用户输入任务
+→ 统一控制入口认证和授权
+→ 任务循环构建上下文
+→ 模型产生文本或行动意图
+→ 行动意图进入工具副作用边界
+→ 安全裁决决定允许、拒绝或请求审批
+→ 工具结果或拒绝证据回灌任务循环
+→ 系统验收候选答案
+→ 完成、继续、失败或无法完成
+
+运行机制的重点不是证明 Agent Loop 存在,而是保证同一条循环同时受统一控制入口、副作用安全边界、本地状态和模型中立边界约束。
+
+---
+
+## 6. 失败路径
+
+| 缺失或错误设计 | 结果 |
+|----------------|------|
+| 没有本地控制权 | 状态、密钥、审批和恢复点落入外部控制面,NeoCode 失去本地优先前提 |
+| 没有统一副作用安全边界 | 工具、MCP、远程执行各自定义风险语义,审批和审计无法闭合 |
+| 没有统一控制入口 | 多端状态、审批、取消、事件和鉴权语义分裂 |
+| 没有模型中立边界 | 模型厂商差异进入核心逻辑,切换模型影响全系统 |
+| 没有可恢复任务事实 | 会话不可恢复,AI 修改不可回滚,审计链断裂 |
+| 远程执行设计成通用 Shell | 能力过宽,攻击面扩大,用户机器暴露不必要风险 |
+| 任务循环不可暂停或不可验收 | 审批、取消、失败回灌和系统验收只能散落在临时逻辑中 |
+
+---
+
+## 7. 构架核心总结
+
+NeoCode 的关键不在于“比单次 LLM 会话多一层工具调用”。成熟 AI Coding 工具都已经具备 Agent Loop。
+NeoCode 的核心在于把 Agent Loop 放进一组更强的控制约束里:
+
+| 抽象 | 作用 |
+|------|------|
+| 本地控制权 | 用户掌握代码、状态、密钥、审批和恢复点 |
+| 统一副作用安全边界 | 工具、MCP、远程执行共享同一裁决和审计语义 |
+| 统一控制入口 | 多端共享同一任务事实和控制语义 |
+| 模型中立边界 | 模型变化不能污染核心任务语义 |
+| 可恢复任务事实 | 执行过程可追踪、可解释、可回滚 |
+| 受限远程执行 | 跨机器执行不退化为开放机器或通用 Shell |
diff --git a/docs/architecture/architecture-v1.md b/docs/architecture/architecture-v1.md
new file mode 100644
index 00000000..d580bb59
--- /dev/null
+++ b/docs/architecture/architecture-v1.md
@@ -0,0 +1,1810 @@
+# NeoCode 系统架构文档
+
+**文档版本:** v0.1
+**维护者:** NeoCode 团队
+**最后更新:** 2026-05-08
+**适用系统版本:** main 分支 HEAD
+**目标读者:** 团队成员、项目贡献者
+
+---
+
+## 1. 文档元信息
+
+本文档用于描述 **NeoCode** 的整体架构设计,包括系统边界、核心模块、关键流程、部署拓扑、安全设计和架构决策记录(ADR)。
+
+本文档面向 **团队成员、项目贡献者**,旨在回答以下问题:
+- 系统解决什么问题、边界在哪里?
+- 核心组件如何划分、如何协作?
+- 为什么选择这种架构而不是其他方案?
+- 有哪些质量目标、已知风险和演进方向?
+
+本文档 **不包含**:
+- 详细 API 字段说明(参见 `docs/reference/gateway-rpc-api.md`)
+- 具体部署操作步骤(参见部署手册)
+- 用户使用指南(参见官方文档站)
+
+本文档随代码库演进持续更新。当架构决策发生变更时,应在第 15 节追加新的 ADR,并更新受影响的相关章节。
+
+---
+
+## 2. 设计约束
+
+### 2.1 架构驱动力
+
+以下六条驱动力贯串全部架构决策。它们不是功能需求,而是**系统必须满足的约束**——文档后续的每个重要决策都应能追溯回这里。
+
+| # | 驱动力 | 含义 | 强制了怎样的设计 |
+|---|--------|------|-----------------|
+| D1 | **本地优先** | 代码、会话、配置和密钥的全部生命周期停留在用户机器上 | 零依赖单二进制分发;嵌入式数据库(SQLite);离线可运行;Web UI 嵌入二进制 |
+| D2 | **多端对等接入** | TUI、Web、Desktop、IM Bot、CI/CD 脚本都是对等的一等公民客户端 | Gateway 作为唯一 RPC 边界,不含端侧特化逻辑;新增客户端不修改 Runtime 或 Gateway |
+| D3 | **多模型可替换** | 用户自由选择和切换底层大模型,厂商差异不向上泄漏 | Provider 插件化(极简接口);新增模型零侵入上层;厂商特定逻辑收敛在 Provider 层内 |
+| D4 | **工具执行可控** | AI 拥有读写文件、执行 Shell 的权限——每次执行需可审计、可阻断、可回滚 | 所有工具调用经过 Security Engine;Human-in-the-Loop 权限审批;WorkspaceSandbox 路径隔离;Checkpoint 写前快照 |
+| D5 | **Human-in-the-Loop** | 危险操作在执行前需经过人类审批,系统不假设审批发生在哪个客户端 | 事件驱动的暂停-恢复推理循环;PolicyEngine 三态决策(allow/deny/ask);会话级权限记忆 |
+| D6 | **单机零运维** | 系统在本地机器上运行,用户不需要是 DBA 或 SRE | 无外部数据库/消息队列依赖;核心模块同进程运行;数据生命周期全自动管理 |
+
+### 2.2 驱动力 → 决策追溯
+
+| 驱动力 | 直接导致的架构决策(章节/ADR) |
+|--------|-----------------------------|
+| D1 本地优先 | SQLite 持久化(ADR-005)、Go 单二进制静态编译(ADR-004)、离线可用 Web UI(§3.3)、Checkpoint 本地快照(ADR-008) |
+| D2 多端对等 | Gateway 唯一 RPC 边界(ADR-001、§7.4 决策 1)、JSON-RPC 2.0(ADR-006)、客户端适配器模式(§3.3、§7.6) |
+| D3 多模型可替换 | Provider 插件化 2 方法接口(ADR-002、§7.4 决策 2)、厂商差异不出 Provider 层(§8.3、§7.6.3) |
+| D4 工具可控 | Security Engine 关键路径(§8.4)、WorkspaceSandbox 路径隔离(§13.3)、敏感路径自动检测(§13.3)、Checkpoint 写前快照(ADR-008、§8.5.1) |
+| D5 Human-in-the-Loop | 事件驱动模型(ADR-003、§7.4 决策 3)、PolicyEngine ask 态 + PermissionFingerprint 会话记忆(§9.3、§10.2.3) |
+| D6 零运维 | 强边界单体(ADR-004)、SQLite 零依赖(ADR-005)、自动过期清理 + Checkpoint 修剪(§9.5、§12.5) |
+
+---
+
+## 3. 系统范围与边界
+
+### 3.1 系统职责(In Scope)
+
+| 职责域 | 说明 |
+|--------|------|
+| 多模型 Provider 适配 | 归一化不同厂商的 Chat API 协议为统一流式事件模型 |
+| ReAct 推理循环 | 用户输入 → 上下文构建 → 模型推理 → 工具调用 → 结果回灌 → 循环,直到产出最终回复 |
+| 工具执行与安全管理 | 文件读写、Bash 执行(含 Git 语义分类)、代码库检索、Web 抓取、MCP 扩展、Todo/子代理等工具的 schema 暴露、参数校验、权限决策和执行 |
+| 多端客户端接入 | 通过 Gateway 统一暴露 JSON-RPC、SSE、WebSocket 接口,支持 TUI、Web、桌面端(Electron)、飞书 Bot 等对等接入 |
+| 会话与状态管理 | 会话创建、持久化(SQLite)、历史消息管理、Token 追踪、上下文裁剪(Compact) |
+| Skills 系统 | 从本地文件系统加载 SKILL.md,按需激活并注入 System Prompt,为特定任务提供专用行为和流程 |
+| 上下文构建与压缩 | 按照会话状态、预算阈值、消息历史动态构建 Provider 请求的 System Prompt 和消息列表 |
+| 记忆(Memo)系统 | 跨会话保存用户偏好、项目事实和上下文,通过 LLM 提取结构化记忆 |
+| 自我更新 | 通过 Go 自更新机制拉取最新版本 |
+
+### 3.2 明确不在范围内(Out of Scope)
+
+| 不在范围内 | 说明 |
+|-----------|------|
+| 中心化云端 SaaS / 多租户 | 数据、会话、代码上下文全部留在本地工作区,权限继承系统进程权限 |
+| 与单一模型厂商绑定 | Provider 接口保持开放,允许随时切换到新模型或本地部署的开源模型 |
+| 完全无人值守的黑盒程序员 | 所有操作可打断、可审查,坚持 Human-in-the-loop |
+| 重型 IDE 插件 / fork | 不 Fork VS Code 或任何编辑器;可在 IDE 中嵌入瘦客户端复用 Gateway 能力 |
+| 强依赖公网的 Web 客户端 | Web/桌面端可在离线局域网环境下直连本机 Gateway |
+| 代码托管(远程仓库) | 有本地 Checkpoint 快照(§10),不替代 GitHub/GitLab;Git 操作经 Bash 语义分类层安全管控 |
+| 自主研发大模型 | NeoCode 是 Agent 框架,不训练或部署自有模型 |
+| 项目管理和需求跟踪 | 不替代 Jira、Linear 等,可通过 Todo 工具做任务级编排 |
+| 组织级 RBAC 与多租户 | 鉴权仅限于 Gateway 连接级 Token,不做企业组织架构映射 |
+
+### 3.3 客户端接入架构与外部依赖
+
+NeoCode 的客户端分为两类:**原生客户端**(由 NeoCode 自身提供)和 **第三方客户端**(通过适配器接入)。所有客户端均通过 Gateway 暴露的统一 RPC 接口与 Runtime 通信,Gateway 内部不包含任何端侧特化逻辑。
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ NeoCode 系统 │
+│ │
+│ 原生客户端(NeoCode 内置) 第三方客户端(适配器接入) │
+│ ┌────────┐ ┌────────┐ ┌──────────┐ ┌───────────┐ │
+│ │ TUI │ │ Web │ │ Desktop │ │ 飞书 Bot │ ... │
+│ └───┬────┘ └───┬────┘ └────┬─────┘ └─────┬─────┘ │
+│ │ │ │ │ │
+│ │ RPC (JSON-RPC / SSE / WebSocket) │ Feishu Adapter │
+│ │ │ │ │ │
+│ └───────────┼───────────┼──────────────┘ │
+│ │ │ │
+│ └───────────┘ │
+│ │ │
+│ ┌─────┴──────┐ │
+│ │ Gateway │ ← 统一 RPC 边界,无客户端特化逻辑 │
+│ └─────┬──────┘ │
+│ │ │
+│ ┌─────┴──────┐ │
+│ │ Runtime │ │
+│ └─────┬──────┘ │
+│ │ │
+│ ┌─────────────┼──────────────┐ │
+│ │ │ │ │
+│ ┌────┴────┐ ┌────┴────┐ ┌─────┴──────┐ │
+│ │Provider │ │ Tools │ │ Session │ │
+│ └────┬────┘ └────┬────┘ └────────────┘ │
+│ │ │ │
+└────────┼─────────────┼────────────────────────────────────────────┘
+ │ │
+ ▼ ▼
+ ┌──────────┐ ┌──────────────┐
+ │ 模型厂商 │ │ 外部工具/服务 │
+ │ │ │ │
+ │ Anthropic│ │ MCP Servers │
+ │ OpenAI │ │ Git (local) │
+ │ Gemini │ │ Filesystem │
+ │ DeepSeek │ │ Shell │
+ │ MiniMax │ │ Web (HTTP) │
+ │ ... │ │ │
+ └──────────┘ └──────────────┘
+```
+
+**原生客户端(NeoCode 内置):**
+- **TUI**:终端交互界面(Bubble Tea),通过 RPC 连接 Gateway
+- **Web**:React SPA,embed 到二进制中,由 Gateway 提供静态文件服务
+- **Desktop**:Electron 壳,内嵌 Web UI,提供系统托盘和原生通知等桌面能力
+
+**第三方客户端接入模式:**
+- 第三方软件可通过编写适配器接入 NeoCode,适配器负责将外部事件/消息转换为 Gateway RPC 调用
+- **飞书 Bot** 是第三方客户端的典型范例:`Feishu Adapter` 接收飞书开放平台 Webhook → 转换为 Gateway JSON-RPC 请求 → 将 Runtime 回复通过飞书消息 API 返回
+- 同模式可扩展至其他 IM 平台(企业微信、钉钉、Slack 等)或自定义系统
+
+**对外依赖(模型与工具层):**
+- **模型厂商 API**:Anthropic、OpenAI、Google Gemini、DeepSeek、MiniMax、Mimo、Qwen、GLM 等(通过 HTTPS)
+- **MCP 服务器**:本地 stdio 子进程,提供外部工具扩展
+- **Git**:本地 Git 命令行(通过 Bash 工具的语义分类层间接调用,不暴露为独立 `git_*` 工具)
+- **Shell**:操作系统原生 Shell(bash/zsh/pwsh 等,用于 `bash` 工具)
+- **飞书开放平台 API**:供 Feishu Adapter 使用,用于接收 Webhook 与发送消息回复
+
+### 3.4 边界规则
+
+1. **代码数据不出本地**:所有文件系统操作限制在 `--workdir` 指定目录内,代码内容不经 Gateway 上传至任何云端服务。
+2. **模型请求仅含必要上下文**:发送给模型厂商的请求仅包含 System Prompt + 对话历史 + 工具定义,不泄露本地路径、环境变量或密钥。
+3. **Gateway 是唯一跨边界通道**:所有客户端(原生或第三方)通过 Gateway 的 RPC 接口与 Runtime 通信,不直连 Runtime。第三方接入时,适配器负责协议转换,Gateway 不感知客户端来源。
+
+---
+
+## 4. 架构目标与质量属性
+
+以下按优先级从高到低排列。每条不只陈述"要什么",更说明**当它与其他目标冲突时,系统优先保护什么。**
+
+### 4.1 安全性(Security)— 最高优先级,优先于所有其他目标
+
+作为拥有文件读写和 Bash 执行权限的本地 Agent,任何沙箱逃逸或不可控行为都可能造成严重后果。
+
+**权衡:** 安全性优先于便利性。例如——用户可能希望 AI "自动执行所有 bash 命令而不弹窗询问",但系统会对破坏性 Git 操作、越界路径访问、敏感文件读写进行审批或阻断。安全策略的默认决策是 `ask`(询问用户),即使这会增加交互摩擦。
+
+**关键设计选择:** 四层纵深防御(认证 → ACL → 工具策略 → OS 隔离);敏感路径自动检测不依赖用户配置;工具执行路径不可旁路 Security Engine。详见 §13。
+
+### 4.2 可测试性(Testability)— 对抗 AI 不确定性的工程锚
+
+大模型的输出不可预测,因此框架链路(流式解析、工具回调、状态机流转)必须可被快速、独立地验证。
+
+**权衡:** 可测试性优先于实现便利性。例如——与物理世界交互的组件(文件系统、Bash、网络、模型 API)全部 Interface 化,允许 Mock 注入。这意味着每个工具需要额外定义一个 interface + 至少一个 mock 实现,增加了代码量,但换取了核心引擎数千个单测在 5 秒内完成的能力。
+
+**关键设计选择:** Provider 仅 2 个方法;Tools Manager 通过 Executor interface 解耦;所有物理交互组件可替换。详见 §8.2–§8.4。
+
+### 4.3 可扩展性(Extensibility)— 生态兼容的核心引擎
+
+系统需要以最低成本适配新模型、新客户端和新工具。
+
+**权衡:** 可扩展性优先于深度优化。例如——Provider interface 只有 2 个方法(`EstimateInputTokens` + `Generate`),而不是为每个厂商的独特能力(如 Anthropic 的 thinking 预算、OpenAI 的 response_format)提供定制接口。这牺牲了对某些厂商高级特性的深度利用,但换取了新增模型的零侵入——不修改 Runtime 一行代码。
+
+**关键设计选择:** Provider 插件化(ADR-002);Gateway 不含端侧特化;MCP 和 Skills 提供零代码扩展路径。详见 §7.6。
+
+### 4.4 可观测性(Observability)— 黑盒执行的破局点
+
+开发者必须能追踪 AI 的完整决策链:读了什么、想了什么、调了什么工具、消耗了多少 Token。
+
+**权衡:** 可观测性优先于性能。例如——每次 Run Loop 的 Token 用量(Input/Output/Cache)作为事件透出,每个 Tool Call 的确切入参和原始结果完整保存(不受输出截断影响),SessionID + RunID 贯穿全链路。这增加了事件序列化和日志写入开销,但换取了生产环境中"为什么 AI 做了这个决策"的可追溯性。
+
+**关键设计选择:** 统一 `RuntimeEvent` channel 承载所有事件;StreamRelay 广播到所有订阅客户端;Prometheus 指标暴露认证失败、ACL 拒绝等安全关键计数器。详见 §14。
+
+### 4.5 性能(Performance)— 流畅的结对编程体验
+
+AI 推理耗时由云端 API 主导,但本地框架的组装与工具执行不能成为瓶颈。
+
+**权衡:** 本地性能优先于资源节省。例如——工具执行采用并行调度(默认并发度 4),同时发起多个独立的 goroutine。这在 I/O 密集型场景(同时读 3 个文件)显著降低延迟,但增加了 goroutine 调度开销。Single-binary 部署(Go 静态编译)的启动时间以毫秒计,换取零依赖分发体验。
+
+**关键设计选择:** 并行工具执行(可配置并发度);进程内事件驱动(Go channel 而非外部消息队列);Compact 触发耗时 < 100ms。详见 §9.1、§9.2。
+
+---
+
+## 5. 约束与设计原则
+
+### 5.1 技术栈约束
+
+| 层面 | 选型 | 约束来源 |
+|------|------|----------|
+| 语言 | Go 1.25+ | 团队能力、编译为单一二进制、跨平台 |
+| TUI 框架 | Charmbracelet Bubble Tea + Lipgloss | Go 生态最成熟的 TUI 框架 |
+| 数据库 | SQLite(modernc 纯 Go 实现) | 零依赖本地持久化,无需外部数据库进程 |
+| 配置管理 | Viper + YAML | Go 生态标准方案 |
+| CLI 框架 | Cobra | Go 生态标准方案 |
+| 自更新 | go-selfupdate | 支持跨平台二进制差分更新 |
+| Web UI | React + Vite(embed 到 Go binary) | Web 端嵌入,启动时由 Gateway 提供静态文件服务 |
+| 桌面端 | Electron | 跨平台桌面壳,内嵌 Web UI |
+
+### 5.2 部署与平台约束
+
+| 约束项 | 说明 |
+|--------|------|
+| 目标平台 | Windows、macOS、Linux 三大桌面平台全部支持;用户分布以 Windows 为主 |
+| 部署形态 | 单一二进制文件(`neocode`),提供 CLI 交互、Gateway 服务 (`neocode gateway`)、HTTP URL Scheme 唤醒 Daemon (`neocode daemon`)、Web UI、Local Runner (`neocode runner`) 等全部子命令 |
+| 网络环境 | 无特殊限制:在线环境通过 HTTPS 调用模型 API;离线环境可搭配本地模型使用,Web 端和桌面端也可在局域网环境下直连本机 Gateway |
+| 数据目录 | 默认 `~/.neocode/`(可配置),存放配置文件、SQLite 会话数据库、Skill 缓存、自更新下载等 |
+| 进程间通信 | 客户端与 Gateway 通过 JSON-RPC / SSE / WebSocket 等 RPC 协议通信;底层传输层正在从 IPC(Unix domain socket / named pipe)向全 RPC 方案迁移 |
+
+### 5.3 设计原则
+
+以下原则提炼自项目 AGENTS.md,每条原则在 NeoCode 中有其具体的设计动机。
+
+#### 原则 1:分层隔离
+
+上层只依赖下层契约,不依赖下层实现细节。`tui` 不感知 provider 协议,`runtime` 不感知具体模型厂商字段。
+
+**动机:** 分层隔离使得各层可独立开发、测试和替换。Provider 的零侵入可扩展性(§4.3)直接依赖此原则。
+
+#### 原则 2:能力入口收敛
+
+任何模型可调用的能力,必须经过 `internal/tools` 的 Schema + Execute 协议,不允许在 `runtime` 或 `tui` 中内嵌工具逻辑。
+
+**动机:** 安全性(§4.1)要求所有工具执行经过统一的安全策略引擎(权限决策、工作区边界检查)。如果工具逻辑分散在各处,安全审计将不可行。
+
+#### 原则 3:状态集中
+
+会话状态、消息历史、工具调用记录由 `runtime/session` 统一管理,不分散到 UI 或其他消费层。
+
+**动机:** 多端(TUI/Web/Desktop/飞书)共享同一 Runtime 实例时,状态若分散会导致一致性问题。集中管理保证了全链路可观测性(§4.4)中 SessionID/RunID 的全局统一。
+
+#### 原则 4:配置先行
+
+环境差异项(超时、路径、模型名、输出限制)优先通过配置注入,不硬编码。
+
+**动机:** 支持多模型自由切换和多部署环境(本地/内网/离线)的必然要求。配置的外部化也保证了密钥零泄漏(密钥仅存于环境变量,不入配置文件)。
+
+#### 原则 5:接口优于实现
+
+核心抽象上的导出类型、函数、接口优先面向接口编程,不暴露具体厂商结构。
+
+**动机:** 可测试性(§4.2)要求所有物理世界交互组件(文件系统、Bash、模型 API)可被 Mock。接口化是实现亚秒级 Mock 测试的前提。
+
+---
+
+## 6. 系统上下文视图
+
+本节描述 NeoCode 与外部世界的交互关系,即 C4 模型中的 Level 1(系统上下文图)。
+
+
+
+**图 6-1:NeoCode 系统上下文图。** 此图展示系统的四类调用方(终端开发者、Web/桌面用户、IM 用户、CI/CD 流水线)和五类外部依赖(模型厂商 API、MCP 服务器、本地 Git、操作系统 Shell、飞书开放平台)。为便于理解,系统边界内部标注了核心模块的逻辑分组,但不展开内部交互细节——详见 §7 容器图。
+
+### 6.1 调用方(Actor)分析
+
+| 调用方 | 接入方式 | 是否原生客户端 | 典型交互模式 |
+|--------|----------|---------------|-------------|
+| 终端开发者 | `neocode` CLI / TUI → Gateway RPC | 是 | 长会话交互,持续多轮对话 + 工具执行 |
+| Web/桌面用户 | Web UI / Electron → Gateway RPC | 是 | 长会话交互,UI 面板展示实时流式输出 |
+| IM 用户(飞书) | 飞书消息 → Feishu Adapter → Gateway RPC | 否(第三方适配器) | 短任务驱动:"查代码" "修 Bug" "跑诊断" |
+| CI/CD 流水线 | 脚本 → Gateway JSON-RPC | 否(自动化调用方) | 无状态单次调用:代码审查、自动修复、批量操作 |
+
+### 6.2 外部系统依赖方向
+
+- **传出依赖**(NeoCode → 外部):模型 API 调用、MCP 子进程启动、Git 信息查询、Shell 命令执行——均为 NeoCode 主动发起
+- **传入依赖**(外部 → NeoCode):飞书开放平台 Webhook → Feishu Adapter——为外部系统回调触发
+- **被动资源**:本地文件系统和 Git 仓库——由 NeoCode 通过工具层读写,不直接向 NeoCode 发送请求
+
+---
+
+## 7. 整体架构设计
+
+### 7.0 核心架构选择摘要
+
+以下五个选择定义了 NeoCode 的基本架构形态。每项选择的详细论证(背景、替代方案、后果)见对应的 ADR。
+
+| 设计张力 | 当前选择 | 原因摘要 | 详见 |
+|----------|----------|----------|------|
+| 微服务 vs 单体 | **强边界单体** | 单机单用户场景下分布式复杂度是负收益;通过 Go interface 保持模块边界 | ADR-004 |
+| 同步调用 vs 事件驱动 | **进程内事件驱动** | 流式输出、中途取消、权限审批、多客户端广播都需要异步事件模型 | ADR-003 |
+| Go vs Python/TS/Rust | **Go 单二进制** | 静态编译零依赖分发、goroutine 并行工具执行、跨平台、AI SDK 生态成熟 | ADR-004 |
+| SQLite vs 外部数据库 | **SQLite(modernc)** | 零外部依赖、ACID 事务满足会话与 Checkpoint 需求、单文件管理 | ADR-005 |
+| JSON-RPC vs gRPC/REST | **JSON-RPC 2.0 + SSE/WS** | 协议门槛最低——任何能发 JSON 的环境都能接入;配合 SSE/WS 做流式输出 | ADR-006 |
+
+### 7.1 架构风格:分层 + 事件驱动
+
+在上述选择的约束下,NeoCode 的架构风格自然收敛为 **分层架构(Layered Architecture)** + **进程内事件驱动(Event-Driven)**。
+
+**分层架构的动机:**
+- 严格接口边界使各层可独立开发、测试和替换
+- Provider 层和 Client 层的可替换性(见 §4.3)直接依赖分层边界
+- 安全审计(见 §4.1)要求工具执行路径可预测、可审计——分层保证了安全策略引擎的唯一入口
+
+**事件驱动的动机:**
+- 模型推理是流式、异步的过程:Provider 通过 channel 推送 `StreamEvent`,Runtime 消费并转换为 `RuntimeEvent`。客户端通过 JSON-RPC 发起请求,Gateway 同步返回 ack;对于长时间运行的 run/ask 操作,Gateway 通过 StreamRelay 将 Runtime 事件以 SSE 或 WebSocket 推送至订阅客户端
+- 多客户端并发:Gateway 通过流中继(Stream Relay)机制,将同一 Runtime 事件广播到多个订阅连接
+- Human-in-the-loop 权限审批:工具执行遇到需用户决策的操作时,Runtime 暂停并向 Gateway 发送 `permission_request` 事件,等待客户端通过 JSON-RPC(`gateway.resolve_permission`)回复
+
+### 7.2 容器视图(C4 Level 2)
+
+> **容器 = 可独立部署/运行的最小单元。** 在 NeoCode 中,CLI、Gateway Daemon、Runner 通过同一二进制文件的不同子命令启动;Web UI 嵌入在 Gateway 进程内。
+
+```mermaid
+graph TD
+ %% --- 客户端 ---
+ subgraph Client["客户端 (独立进程或嵌入)"]
+ direction LR
+ TUI["TUI
Bubble Tea CLI"] ~~~ WEB["Web
React SPA"] ~~~ DT["Desktop
Electron"] ~~~ FS["飞书 Bot
via Adapter"]
+ end
+
+ %% --- 核心 ---
+ GW["Gateway
══════════════
JSON-RPC · SSE · WS
Stream Relay
Token Auth"]
+ RT["Runtime
══════════════
ReAct 循环编排
权限审批 · Compact 调度
事件派发 · Hook 管理"]
+
+ %% --- 能力层 ---
+ subgraph Capability["能力层 (同一进程内的模块边界)"]
+ direction LR
+ PR["Provider
多模型适配"]
+ TL["Tools
工具执行 + 安全引擎"]
+ CTX["Context
Prompt 构建 + 压缩"]
+ SESS["Session
SQLite 持久化"]
+ end
+
+ %% --- 支撑 ---
+ subgraph Support["支撑 (同一进程)"]
+ direction LR
+ SK["Skills
SKILL.md 加载"]
+ CFG["Config
配置管理"]
+ end
+
+ %% --- 外部 ---
+ subgraph External["外部系统"]
+ direction LR
+ RN["Local Runner
独立进程 · 远程/本机"]
+ LLM["模型厂商 API
Anthropic · OpenAI · Gemini · ..."]
+ end
+
+ DB[("SQLite
~/.neocode/")]
+
+ %% --- 连线 ---
+ Client -->|"JSON-RPC"| GW
+ GW -->|"同步调用"| RT
+ RT --> Capability
+ RT --> Support
+ RT --> DB
+ GW -.->|"SSE / WS 事件流"| Client
+ GW -.->|"WebSocket
tool_exec + heartbeat"| RN
+ RT -.->|"HTTPS 流式"| LLM
+
+ %% --- 样式 ---
+ style GW fill:#fb923c,stroke:#fb923c,color:#0f172a
+ style RT fill:#34d399,stroke:#34d399,color:#0f172a
+ style PR fill:#a78bfa,stroke:#a78bfa,color:#0f172a
+ style TL fill:#fbbf24,stroke:#fbbf24,color:#0f172a
+ style CTX fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style SESS fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style SK fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style CFG fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style DB fill:#94a3b8,stroke:#94a3b8,color:#0f172a
+ style RN fill:#fb7185,stroke:#fb7185,color:#0f172a
+ style LLM fill:#94a3b8,stroke:#94a3b8,color:#0f172a
+ style Client fill:#1e293b,stroke:#22d3ee,color:white
+ style Capability fill:#1e293b40,stroke:#334155,color:white
+ style Support fill:#1e293b40,stroke:#334155,color:white
+ style External fill:#1e293b40,stroke:#475569,color:white
+```
+
+**图 7-1:NeoCode 容器图(C4 Level 2)。** 实线 = 同步调用;虚线 = 异步事件/外部通信。颜色:橙 = 协议边界、绿 = 编排中枢、紫 = 适配层、黄 = 工具层、蓝 = 支撑层、红 = 独立进程、灰 = 外部系统/数据存储。
+
+**关键拓扑特征:**
+- Gateway、Runtime、Provider、Tools、Session、Context、Skills、Config **共享同一进程**,通过 Go interface 解耦而非网络调用
+- Local Runner 是**唯一可能跨越物理机边界**的容器(通过 WebSocket 反向连接 Gateway)
+- Web UI 的静态资源嵌入在 Gateway 二进制中,不独立部署
+- SQLite 是唯一的持久化存储,无需外部数据库进程
+
+### 7.3 层间依赖规则
+
+```mermaid
+graph TB
+ L0["第 0 层:客户端
TUI / Web / Desktop / IM Adapter / CI/CD"]
+ L1["第 1 层:Gateway
协议路由 + 流中继 + 连接认证"]
+ L2["第 2 层:Runtime
ReAct 循环编排 + 权限决策 + 事件派发"]
+ L3A["Provider
模型适配"]
+ L3B["Tools
工具执行"]
+ L3C["Context
Prompt 构建"]
+ L3D["Session
状态持久化"]
+ L4A["Skills
可插拔行为注入"]
+ L4B["Runner
远程工具执行代理"]
+
+ L0 -->|"依赖接口"| L1
+ L1 -->|"依赖接口"| L2
+ L2 -->|"依赖接口"| L3A
+ L2 -->|"依赖接口"| L3B
+ L2 -->|"依赖接口"| L3C
+ L2 -->|"依赖接口"| L3D
+ L3A -.->|"可选扩展"| L4A
+ L3B -.->|"可选扩展"| L4B
+```
+
+**依赖规则:** 上层只依赖下层契约(接口),不依赖具体实现。实线箭头 = 编译时依赖,虚线箭头 = 运行时可选绑定。
+
+**跨层规则(提炼自 AGENTS.md):**
+- `tui` 不直接调用 `provider` 或 `tools`
+- `runtime` 不内嵌具体厂商字段或工具执行逻辑
+- `gateway` 不包含客户端特化逻辑(所有客户端通过统一 RPC 接入)
+- 模型厂商差异不泄漏到 `runtime` 或上层
+
+### 7.4 核心设计决策
+
+#### 决策 1:Gateway 作为唯一 RPC 边界
+
+所有客户端(原生和第三方)必须通过 Gateway 与 Runtime 通信。Gateway 内部通过 `Action` 路由表将 JSON-RPC 请求帧分发到对应的处理器(`run`、`ask`、`cancel`、`resolve_permission` 等),并通过 `StreamRelay` 将 Runtime 的异步事件广播到订阅连接。
+
+**选择理由:**
+- 多端对等接入:TUI、Web、Desktop、IM Bot 在 Gateway 视角完全一致
+- 安全收敛:认证、授权、速率限制集中在 Gateway 层,不需要每个客户端独立实现
+- 协议统一:未来新增协议(如 gRPC)只需在 Gateway 增加 transport handler
+
+**替代方案对比:**
+
+| 方案 | 优点 | 缺点 | 为何不选 |
+|------|------|------|----------|
+| 各客户端直连 Runtime | 无中间层延迟 | 每个客户端需独立实现认证/鉴权/重连;Runtime 需理解多种传输协议;新增客户端成本高 | 违背"客户端对等"原则,安全面分散 |
+| 纯 HTTP REST | 生态成熟、调试方便 | 流式推理结果需客户端轮询或长轮询,延迟高,实现不优雅 | AI 推理天然是流式的,SSE/WS 更适合 |
+| **Gateway 统一 RPC** | 安全收敛、客户端对等、流式原生支持 | 增加一跳网络延迟(本地 loopback 可忽略) | ✅ 当前选择 |
+
+#### 决策 2:Provider 作为一等公民的插件化抽象
+
+`Provider` 接口仅定义两个方法:`EstimateInputTokens` 和 `Generate`(通过 channel 推送流式事件)。所有模型厂商差异(请求组装、响应解析、工具调用格式转换)收敛在各自的 Provider 实现中。
+
+**选择理由:**
+- 零侵入新增模型:现有已接入的 Provider 实现包括 Anthropic、OpenAI Compat(Qwen/GLM/通用)、Gemini、DeepSeek、MiniMax、Mimo
+- 测试友好:Runtime 测试只需注入 Mock Provider,不依赖真实 API
+
+**替代方案对比:**
+
+| 方案 | 优点 | 缺点 | 为何不选 |
+|------|------|------|----------|
+| 统一的内部模型协议,由 Gateway 做协议转换 | Provider 实现更简单 | Gateway 成为瓶颈:每种新模型的流式格式差异需在 Gateway 处理;Gateway 职责膨胀 | 违反"Gateway 不感知模型差异"的边界原则 |
+| 每个客户端自行集成模型 SDK | 无中间损耗 | 模型切换需更新所有客户端;安全密钥分散管理;无法做统一的 Token 预算管理 | 安全性和可维护性灾难 |
+| **Provider 插件化** | 新增模型零侵入上层;Runtime 无厂商感知;测试可 Mock | 每个新厂商需写适配代码 | ✅ 当前选择 |
+
+#### 决策 3:事件驱动的异步工具执行
+
+Runtime 在 ReAct 循环中收到模型的 tool call 后,并行调度工具执行(默认并发度 4),并将结果回灌到消息历史。工具执行结果、权限请求、流式文本增量全部通过统一 `RuntimeEvent` channel 发出。
+
+**选择理由:**
+- Human-in-the-loop:`permission_request` 事件可被 Gateway 拦截,暂停执行等待用户决策
+- 实时流式透出:文本增量事件经 SSE 流式推送到客户端,用户可见 AI "打字"过程
+- 全链路可追踪:所有事件共享 `SessionID + RunID`
+
+**替代方案对比:**
+
+| 方案 | 优点 | 缺点 | 为何不选 |
+|------|------|------|----------|
+| 同步回调(工具执行完再统一返回) | 实现简单 | 工具执行期间客户端完全黑屏;不支持 Human-in-the-loop;不支持并行工具执行 | 用户体验差,无法满足 §4.4 可观测性要求 |
+| 纯轮询(客户端定时查询执行状态) | 无长连接需求 | 延迟高、带宽浪费、无法支持实时权限审批 | 不适合流式推理场景 |
+| **事件驱动 + Channel** | 实时流式、Human-in-the-loop、并行工具 | 需要客户端支持 SSE/WS 长连接 | ✅ 当前选择 |
+
+---
+
+### 7.5 关键角色与职责
+
+以下从架构视角定义系统中的关键"角色"——这里说的不是代码中的类或模块,而是在运行时协作中承担明确职责的逻辑参与者。一个 Go 包可能承载多个角色;一个角色也可能跨多个包协作完成。
+
+```mermaid
+graph LR
+ Client["客户端
Client"] -->|"JSON-RPC"| Router["协议路由器
Gateway"]
+ Router -->|"事件流"| Orch["推理编排器
Runtime"]
+
+ Orch -->|"Generate()"| Adapter["模型适配器
Provider"]
+ Orch -->|"Execute()"| Executor["工具执行器
Tools"]
+ Orch -->|"Build()"| CtxBuilder["上下文构建器
Context"]
+ Orch -->|"Load/Save"| StateMgr["状态管理者
Session"]
+
+ Executor -->|"Check()"| Guard["安全守卫
Security Engine"]
+ Adapter -.->|"HTTPS"| LLM["外部模型厂商"]
+ Executor -.->|"WebSocket"| RemoteAgent["远程执行代理
Runner"]
+
+ CtxBuilder -->|"激活/注入"| SkillInjector["技能注入器
Skills"]
+ Router -->|"Get/Update"| ConfigCoord["配置协调者
Config"]
+ Orch -->|"Get/Update"| ConfigCoord
+
+ style Router fill:#fb923c,stroke:#fb923c,color:#0f172a
+ style Orch fill:#34d399,stroke:#34d399,color:#0f172a
+ style Adapter fill:#a78bfa,stroke:#a78bfa,color:#0f172a
+ style Executor fill:#fbbf24,stroke:#fbbf24,color:#0f172a
+ style Guard fill:#fb7185,stroke:#fb7185,color:#0f172a
+ style CtxBuilder fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style StateMgr fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style SkillInjector fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style RemoteAgent fill:#fbbf24,stroke:#fbbf24,color:#0f172a
+ style ConfigCoord fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+```
+
+**图 7-3:关键角色关系图。** 实线箭头 = 同步调用依赖;虚线箭头 = 异步/外部通信。颜色:橙=协议边界、绿=编排中枢、紫=适配层、黄=执行层、红=安全、蓝=支撑角色。
+
+| 角色 | 职责 | 关键约束 | 承载模块 |
+|------|------|----------|----------|
+| **协议路由器** | 将客户端 JSON-RPC 请求路由至正确的处理器;将 Runtime 异步事件中继至订阅的客户端连接;执行连接级认证与 Token 校验 | 不包含任何客户端特化逻辑;不感知模型厂商差异 | Gateway |
+| **推理编排器** | 驱动 ReAct 循环:调度上下文构建 → 模型推理 → 工具执行 → 结果回灌;管理 Token 预算与 Compact 触发;协调权限审批的暂停/恢复 | 不直接执行工具逻辑;不内嵌厂商字段;不跨层直连客户端 | Runtime |
+| **模型适配器** | 归一化不同厂商的 Chat API 为统一的 `Generate()` + `EstimateInputTokens()` 接口;将厂商特定的流式响应格式转换为标准 `StreamEvent` | 厂商差异不泄漏到 Runtime;每个 Adapter 独立测试 | Provider |
+| **工具执行器** | 暴露工具的 Schema 供模型选择;校验参数并执行工具调用;在每次执行前经过安全守卫的权限裁决 | 所有模型可调用的能力收敛于此角色;不在 Runtime 或客户端中绕过 | Tools (Manager) |
+| **安全守卫** | 基于策略规则(Priority 排序)裁决每个操作的 allow/deny/ask 决策;校验工作区边界(路径穿越检测、Symlink 解析);管理会话级权限记忆 | 位于工具执行的关键路径上,不可跳过 | Security Engine |
+| **上下文构建器** | 按会话状态 + 预算阈值动态组装 System Prompt 和消息列表;执行上下文压缩(MicroCompact / Full Compact / Trim) | 压缩时不丢失 System Prompt 和 Pin 标记的关键消息;组装顺序稳定 | Context |
+| **状态管理者** | 持久化会话消息历史(SQLite);管理 Checkpoint 快照的创建/恢复/修剪;执行过期会话的自动清理 | 同会话并发写串行化(sessionLock);消息追加原子化 | Session |
+| **技能注入器** | 从文件系统扫描 SKILL.md;管理会话级 Skill 激活状态;按激活列表将 Skill Prompt 注入 System Prompt 的技能段落 | project 层覆盖 global 层(同名去重);单文件大小限制 1MB | Skills |
+| **远程执行代理** | 在远程/本机独立进程中接收 Gateway 的工具执行请求;校验 Capability Token;在本地完成工具执行并返回结果 | 主动连接 Gateway(反向连接);不开放入站端口;受 WorkdirAllowlist 限制 | Runner |
+| **配置协调者** | 管理配置文件加载、校验、热更新和持久化;维护跨会话的 Provider/Model 选择状态;协调多端的 Provider 切换一致性 | 密钥仅通过环境变量引用,不入配置文件;配置变更通过回调通知下游 | Config |
+
+### 7.6 可扩展性设计
+
+NeoCode 在多处预留了扩展点。本节集中描述:**哪里可以扩展、怎么扩展、哪些边界是刻意保留的以及为什么。**
+
+#### 7.6.1 扩展点总览
+
+| 扩展点 | 扩展什么 | 接口/契约 | 生效范围 | 侵入性 |
+|--------|----------|----------|----------|--------|
+| **Provider** | 新增模型厂商(如接入新的 LLM 服务) | 实现 `Provider` interface(2 方法):`EstimateInputTokens` + `Generate` | 全局 | 仅需在 `provider/` 下新增包,上层零改动 |
+| **Tools** | 新增模型可调用的工具能力 | 实现 `Executor` interface:`Name()` + `ListAvailableSpecs()` + `Execute()` + `Supports()`,注册到 `Registry` | 全局 | 工具 schema 自动进入模型上下文 |
+| **MCP** | 动态挂载外部工具(无需写 Go 代码) | MCP stdio 协议(JSON-RPC 子进程) | 会话级或全局 | 零代码:配置 MCP server 路径即可 |
+| **Skills** | 注入专用行为 Prompt(不改变工具列表) | 在指定目录下放置 `SKILL.md` 文件(YAML frontmatter + Markdown body) | 会话级(按需激活) | 零代码:文件即 Skill |
+| **Client** | 新增客户端类型(如企业微信、Slack、自定义脚本) | 实现适配器:接收外部事件 → 转换为 Gateway JSON-RPC 请求 → 接收 SSE/WS 事件 → 转换为目标格式 | 全局 | Gateway 零改动;适配器独立进程 |
+| **Hook** | 在 Runtime 生命周期节点注入自定义行为(如合规检查、自定义日志) | 在 hooks 配置目录下放置可执行文件;支持 `PreToolUse`、`PostToolUse`、`PreCompact`、`SessionStart`、`UserPromptSubmit` 等 hook point | 会话级或全局 | 零侵入:Hook 以子进程运行,通过 stdin/stdout JSON 通信 |
+| **Transport** | 新增 Gateway 传输协议(如 gRPC、QUIC) | 实现 `transport.Listener` interface | 全局 | Gateway handler 逻辑不变,仅新增 transport |
+
+#### 7.6.2 扩展机制详解
+
+**Provider 扩展(最常用的扩展点):**
+
+```
+新增模型厂商需要的步骤:
+1. 在 internal/provider/ 下创建新包
+2. 实现 Provider interface(EstimateInputTokens + Generate)
+3. 将厂商特定的流式响应格式转换为统一的 StreamEvent
+4. 在配置文件中添加 provider 条目(name + driver + base_url + api_key_env + models)
+→ 完成。Runtime 和 Gateway 代码零改动。
+
+为什么接口只有 2 个方法?
+- 接口越大,实现成本越高,厂商差异泄漏的风险越大
+- "估算 Token 数"和"发起推理"是模型调用的最小完备集
+- 其他可变行为(重试策略、超时、模型发现)通过 RuntimeConfig 注入,不进入 interface
+```
+
+**工具扩展(有代码 vs 无代码两条路径):**
+
+| 路径 | 适用场景 | 成本 |
+|------|----------|------|
+| 实现 `Executor` interface(Go 代码) | 需要深度系统集成的新工具(如 Tree-sitter 代码分析) | 写 Go 代码 + 注册 |
+| MCP stdio 子进程(零 Go 代码) | 外部团队的工具、已有 CLI 工具包装 | 配置 JSON 声明 server 路径 |
+
+**客户端扩展(适配器模式):**
+
+```
+第三方接入 NeoCode 的最小合约:
+1. 能够发送 JSON-RPC 2.0 请求到 Gateway 的 /rpc 端点
+2. 能够接收 SSE 或 WebSocket 事件流
+3. (可选) 实现 gateway.authenticate 获取 subject_id
+
+飞书 Adapter 就是按这个合约实现的第一个第三方客户端。
+任何能发 HTTP POST + 解析 JSON 的环境(Python 脚本、Shell curl、Node.js 服务)
+都可以成为 NeoCode 客户端。
+```
+
+#### 7.6.3 刻意保留的边界
+
+以下边界不是技术限制,而是架构假设。修改它们意味着改变了系统的基本设计:
+
+| 边界 | 为什么保留这个边界 |
+|------|-------------------|
+| **Gateway 是唯一的 RPC 入口** | 如果客户端绕开 Gateway 直连 Runtime,安全认证、流中继、客户端对等性全部失效 |
+| **工具执行经过 Security Engine** | 如果某个工具跳过 PolicyEngine + WorkspaceSandbox,整个安全模型无法保证 |
+| **Provider 差异不出 Provider 层** | 如果 Anthropic 的工具调用格式泄漏到 Runtime,新增 DeepSeek Provider 时就需要修改 Runtime 代码 |
+| **配置文件不存明文密钥** | API Key 通过环境变量引用而非存入 YAML。如果开放此限制,密钥泄漏风险将从"单个环境变量"扩散到"配置文件 + 备份 + 版本控制" |
+
+---
+
+## 8. 核心模块设计
+
+以下选取 9 个最具架构意义的模块,按层从上到下逐一描述。
+
+### 8.1 Gateway(协议路由与多端接入边界)
+
+**存在理由:** Gateway 是系统唯一的 RPC 边界。它的存在不是技术偏好——它是 D2(多端对等接入)和 D4(工具执行可控)的直接推论:如果每个客户端自行接入 Runtime,认证、授权、流式事件中继将在 N 个客户端中重复实现,安全面无法收敛。
+
+**拥有的决策权:**
+- 哪个客户端连接被接受(认证)
+- 哪个 RPC method 被允许(ACL)
+- Runtime 事件路由到哪个客户端连接(流绑定)
+
+**不能知道什么:**
+- 不能知道客户端的具体实现(TUI/Web/Desktop/飞书在 Gateway 视角完全相同)
+- 不能知道模型厂商的具体字段或协议(Provider 差异不出 Provider 层)
+- 不能知道工具的具体执行逻辑(那是 Tools Manager 的职责)
+
+**禁止的调用路径:**
+- 客户端直接调用 Runtime 的任意方法 ← 必须经过 Gateway
+- Gateway 内嵌特定客户端的 UI 逻辑或消息格式 ← 适配器模式处理
+- Gateway 直接执行工具或调用 Provider ← 必须委托给 Runtime
+
+**边界破坏的后果:** 如果客户端绕过 Gateway 直连 Runtime——安全认证分散、流式事件推送需要在每个客户端中重新实现、新增客户端类型需要修改 Runtime。系统的 N×M 复杂度问题从 Gateway 的一层收敛退化为全连接。如果 Gateway 内嵌了客户端特化逻辑——每新增一种客户端类型就需要修改 Gateway,这与"Gateway 无客户端感知"的架构铁律冲突。
+
+**关键接口:** JSON-RPC 2.0 over HTTP(loopback 或网络);SSE 和 WebSocket 用于流式事件推送;`transport.Listener` 允许替换底层传输协议。详见 §11。
+
+### 8.2 Runtime(ReAct 循环与会话编排)
+
+**存在理由:** Runtime 是系统的神经中枢。但它的核心设计原则是"指挥不执行"——它知道推理循环的每个步骤**何时应该发生**,但不知道每个步骤的**具体实现细节**。这是 D3(多模型可替换)和 D4(工具可控)的共同要求:如果 Runtime 知道 Anthropic 的 tool call 格式,新增 DeepSeek 就需要改 Runtime;如果 Runtime 内嵌了文件写入逻辑,安全审计就需要检查 Runtime 而非仅检查 Tools Manager。
+
+**拥有的决策权:**
+- ReAct 循环何时继续、何时终止
+- Compact(上下文压缩)何时触发
+- 权限审批(`permission_request`)何时暂停、何时恢复
+- 工具调用何时并行、何时串行(并发度控制)
+
+**不能知道什么:**
+- 不能知道模型厂商的具体协议字段 ← Provider 封装
+- 不能知道工具的具体执行逻辑 ← Tools Manager 封装
+- 不能知道 Prompt 的组装细节 ← Context Builder 封装
+- 不能知道会话的存储格式 ← Session Store 封装
+- 不能知道传输协议(HTTP/WS/IPC)← Gateway 封装
+
+**禁止的调用路径:**
+- Runtime 直接执行文件 I/O 或 Bash 命令 ← 必须通过 Tools Manager
+- Runtime 直接读取模型厂商的原始响应 ← 必须通过 Provider
+- Runtime 直接访问 SQLite ← 必须通过 Session Store
+- Runtime 直连客户端推送事件 ← 必须通过 Gateway 的 StreamRelay
+
+**边界破坏的后果:** 如果 Runtime 内嵌了工具执行逻辑——每新增一个工具都需要修改 Runtime,5 人并行开发的合并冲突频率将急剧上升,且安全审计被迫检查 Runtime 的每一行代码。如果 Runtime 内嵌了厂商字段——切换模型时会引入难以追踪的回归("为什么 DeepSeek 的行为和 Anthropic 不同?原因埋在 Runtime 的某个 if-else 里")。
+
+**关键接口:** `Runtime` interface 定义了与 Gateway 的完整契约(`Submit`、`Run`、`Ask`、`Compact`、`CancelActiveRun`、`ResolvePermission`、`Events()` 等)。所有与下层模块的交互通过 interface 完成,无具体类型依赖。
+
+### 8.3 Provider(多模型厂商协议适配)
+
+**存在理由:** D3(多模型可替换)的工程载体。Provider 层的唯一职责是将不同厂商的 Chat API 归一化为两个操作——估算 Token 数、发起流式推理——使得 Runtime 完全不感知"当前用的是哪个模型厂商"。这是 NeoCode 多模型自由度的结构保障:不是"配置项切换",而是架构级的接口隔离。
+
+**拥有的决策权:** 如何将厂商特定的请求/响应格式映射到统一的 `GenerateRequest` / `StreamEvent`。
+
+**不能知道什么:** Provider 不依赖 NeoCode 的任何上层模块。它是一个**单向依赖**——仅被 Runtime 调用,自身不调用 Runtime、Gateway、Tools 或 Session。
+
+**禁止的调用路径:** 厂商特定的字段(如 Anthropic 的 `thinking` 预算类型、OpenAI 的 `response_format`)不得以原始形态穿过 Provider 向上传递。如需暴露,必须归一化为 Provider 层定义的通用类型——否则 Runtime 就会产生厂商感知。
+
+**边界破坏的后果:** 如果某个 Provider 的特定行为(如错误格式、tool call 编码方式)被 Runtime 直接依赖——切换模型时 Runtime 行为异常,且排查时需要同时理解 Runtime 和特定 Provider 的实现。这就是"厂商差异泄漏"——也是 ADR-002 明确要避免的。
+
+**关键约束:** `Provider` interface 仅 2 个方法。接口膨胀的代价是每个已有 Provider 实现必须同步修改——因此新增方法需要极其严格的审查。
+
+### 8.4 Tools(工具执行与安全策略引擎)
+
+**存在理由:** D4(工具执行可控)和 D5(Human-in-the-Loop)的工程载体。Tools 层是系统中唯一被允许执行文件 I/O、Bash 命令、网络请求和 MCP 外部工具的模块。任何模型可调用的能力必须在此注册——这是"能力入口收敛"原则(§5.3 原则 2)的实现。
+
+**拥有的决策权:** 哪些工具暴露给模型(Schema 列表);每次工具调用是否允许执行(经 Security Engine 裁决);工具结果如何裁剪和格式化(防止输出过大撑爆上下文)。
+
+**不能知道什么:** 工具本身不感知"推理循环的状态"(那是 Runtime 的职责);不感知"当前用的是哪个模型"(那是 Provider 的职责);不感知"客户端是谁"(那是 Gateway 的职责)。
+
+**禁止的调用路径:**
+- 任何模块绕过 `Manager.Execute()` 直接执行工具 ← Security Engine 的关键路径不可旁路
+- Runtime 或客户端直接调用文件系统/shell ← 必须通过 Tools Manager
+
+**边界破坏的后果:** 如果一个新工具被添加到 Runtime 而不是 Tools Manager——安全审计需要同时检查 Runtime 和 Tools 两个模块;如果某个工具绕过 Security Engine 执行——整个安全模型崩溃,因为 D4 的唯一保障是这个关键路径不被旁路。
+
+**关键接口:** `Manager` interface(`ListAvailableSpecs` + `Execute` + `RememberSessionDecision`);`Executor` interface(每个工具的标准化契约)。Security Engine(`PolicyEngine` + `WorkspaceSandbox`)位于 `Execute()` 的关键路径上,不可跳过。详见 §13.3。
+
+#### 8.4.1 已有工具清单(Inferred from `internal/tools/`)
+
+| 工具名 | 分类 | 说明 |
+|--------|------|------|
+| `bash` | 系统执行 | 执行 Shell 命令,含 Git 语义分类(只读/远端操作/破坏性) |
+| `filesystem_read_file` | 文件系统 | 读取文件内容 |
+| `filesystem_write_file` | 文件系统 | 写入/创建文件 |
+| `filesystem_edit` | 文件系统 | 基于字符串精确替换的原地编辑 |
+| `filesystem_glob` | 文件系统 | 文件名模式匹配 |
+| `filesystem_grep` | 文件系统 | 文件内容正则搜索 |
+| `filesystem_copy_file` | 文件系统 | 复制文件 |
+| `filesystem_move_file` | 文件系统 | 移动/重命名文件 |
+| `filesystem_create_dir` | 文件系统 | 创建目录 |
+| `filesystem_delete_file` | 文件系统 | 删除文件 |
+| `filesystem_remove_dir` | 文件系统 | 删除目录 |
+| `codebase_read` | 代码库 | 读取代码文件(含语义增强) |
+| `codebase_search_text` | 代码库 | 基于文本搜索代码库 |
+| `codebase_search_symbol` | 代码库 | 基于 Tree-sitter 的跨语言符号搜索 |
+| `webfetch` | 网络 | 获取 URL 内容(限制协议与响应大小) |
+| `todo_write` | 任务管理 | 创建/更新 Todo 列表 |
+| `memo_list` / `memo_remember` / `memo_recall` / `memo_remove` | 记忆 | 跨会话结构化记忆管理 |
+| `diagnose` | 诊断 | 分析终端异常输出并给出建议 |
+| `spawn_sub_agent` | 编排 | 创建子代理处理独立子任务 |
+| MCP 工具(动态) | 扩展 | 通过 MCP stdio 协议挂载的外部工具 |
+
+### 8.5 Session(会话领域模型与 SQLite 持久化)
+
+**存在理由:** D1(本地优先)和 D6(零运维)决定了持久化必须是嵌入式的、零依赖的。Session 层是系统中**唯一拥有会话数据的模块**——消息历史、Token 计数、Todo 列表、Plan 快照、Skills 激活状态的读写全部经由此层。这是 D4(工具可控)的延伸:如果会话状态散落在多个模块中,审计和恢复将不可行。
+
+**拥有的决策权:** 会话何时创建、消息何时追加、何时触发过期清理(30 天无更新)、何时裁剪最旧消息(8192 条硬上限)。
+
+**不能知道什么:** Session 层不感知推理循环的状态(那是 Runtime 的职责),不感知 Prompt 的组装逻辑(那是 Context 的职责)。
+
+**关键不变量:** 同会话的并发写必须串行化(`sessionLock`);消息追加和 Compact 消息替换必须在 SQLite 事务中原子完成——不能出现"消息写入了但 SessionHead 未更新"的半状态。
+
+#### 8.5.1 Checkpoint(代码版本快照)
+
+D4(工具执行可控)要求 AI 的写操作可回滚。Checkpoint 在每次写操作前(`pre_write`)、每轮结束时(`end_of_turn`)、压缩前(`compact`)自动创建代码快照。快照在 SQLite 中管理,支持恢复和过期修剪。与 Git 并存:有 `.git` 时优先用 Git 版本追踪;无 `.git` 时 Checkpoint 是独立的安全网。
+
+### 8.6 Context(Prompt 构建与上下文压缩)
+
+**存在理由:** "AI 看到了什么"是一个独立于"AI 怎么推理"的架构关注点。将 Context 从 Runtime 中分离出来,意味着 Compact 策略(MicroCompact / Full Compact / Trim)可以独立演进,不需要修改推理循环。
+
+**拥有的决策权:** System Prompt 的组装顺序(`corePrompt → capabilities → rules → taskState → planModeContext → todos → skillPrompt → repositoryContext → systemState` 的固定顺序);Compact 何时触发、采用什么级别(Micro vs Full vs Trim);哪些消息不能被压缩(Pin 标记)。
+
+**不能知道什么:** Context 不感知模型厂商的具体协议(那是 Provider 的职责),不感知工具的执行结果(那是 Tools 的职责)。
+
+**关键不变量:** System Prompt(corePrompt + capabilities + rules + skillPrompt)在任何压缩级别下都不参与裁剪——丢失 System Prompt 意味着 AI 失去基本行为约束。Pin 标记的消息(用户原始问题、Plan 批准记录)不被压缩。压缩后的消息列表通过 `ReplaceTranscript` 原子替换。
+
+### 8.7 Skills(可插拔行为注入引擎)
+
+**存在理由:** D3(多模型可替换)和 D4(工具可控)的共同延伸——不仅模型和工具可替换,AI 的**行为模式**也应该可定制。Skills 提供了一条零代码路径:在指定目录放一个 `SKILL.md` 文件,AI 就获得了新的行为能力。与 MCP 互补:Skills 扩展 System Prompt(指示 AI "怎么做"),MCP 扩展工具列表(赋予 AI "能做的新能力")。
+
+**拥有的决策权:** 哪些 Skill 可用(按 source layer 加载和去重)、哪个 Skill 在哪个会话中被激活。
+
+**关键约束:** 双层来源(project > global)的去重规则——团队可以定义项目级 Skill 覆盖个人全局 Skill。会话级激活管理——Skill 不是全局开关,按需注入,避免 Prompt 膨胀。
+
+### 8.8 Runner(远程工具执行代理)
+
+**存在理由:** D2(多端接入)中最特殊的一环——不是"客户端如何接入 Gateway",而是"工具执行能力如何跨越物理机边界"。Runner 是系统中**唯一可以运行在不同物理机上的模块**——其余所有核心模块同进程。
+
+**拥有的决策权:** 是否接受工具执行请求(Capability Token 校验 + WorkdirAllowlist)。
+
+**关键约束:** 反向连接模型——Runner 主动连 Gateway(WebSocket),而非 Gateway 连 Runner。这意味着 Runner 可以在 NAT/防火墙后运行,无需公网 IP 或开放入站端口。这是 D1(本地优先)的延伸:工位电脑的代码不需要暴露到公网。
+
+**边界破坏的后果:** 如果 Runner 的 Capability Token 校验被绕过——远程客户端可以通过 Runner 执行任意工具,工作区隔离失效。
+
+### 8.9 Config(配置管理与运行时状态)
+
+**存在理由:** D3(多模型可替换)和 D6(零运维)需要一个集中的配置管理点。所有环境差异项(超时、模型名、路径、Shell)必须通过配置注入,不能硬编码——否则多模型自由切换和多环境部署(本地/内网/离线)无法实现。
+
+**拥有的决策权:** 当前生效的配置是什么(`Manager.Get()` 返回不可变快照);运行时 Provider/Model 选择状态(`state.Service`)——当一端切换了模型,其他端通过回调感知。
+
+**关键约束:** 密钥不入配置文件——`api_key_env` 仅存储环境变量名,真实密钥在 Provider 发起请求前才从环境变量读取。配置快照 copy-on-read——`Get()` 返回深拷贝,防止调用方意外修改全局状态。
+
+---
+
+## 9. 核心流程与动态视图
+
+以下选取 5 个最具架构意义的运行时流程,逐一描述触发条件、参与组件、关键步骤和异常路径。
+
+### 9.1 主 ReAct 推理循环(Run Flow)
+
+**触发条件:** 客户端通过 Gateway 发送 `gateway.run` 请求,由 Runtime.Submit / Runtime.Run 入口进入。
+
+**参与组件:** Gateway → Runtime → Context Builder → Provider → Tools Manager → Security Engine → Session Store
+
+**流程:**
+
+```mermaid
+sequenceDiagram
+ participant Client as 客户端
+ participant GW as Gateway
+ participant RT as Runtime
+ participant CTX as Context
+ participant PR as Provider
+ participant TL as Tools
+
+ Client->>GW: gateway.run (JSON-RPC)
+ GW->>RT: PrepareInput → Run
+ RT->>CTX: Build(session)
+ CTX-->>RT: [SystemPrompt + Messages]
+ RT->>PR: Generate(req)
+ PR-->>RT: [StreamEvent: text_delta, tool_call...]
+ RT-->>GW: emit(run_progress)
+ GW-->>Client: [SSE: progress event]
+
+ alt 模型产出 tool_calls
+ RT->>TL: Execute(toolCalls) [并行≤4]
+ TL-->>RT: [ToolResult]
+ RT->>RT: 回灌 tool_result 到消息历史
+ RT->>PR: Generate(req) [继续]
+ PR-->>RT: [StreamEvent ...]
+ else 模型产出最终文本
+ RT-->>GW: emit(run_done)
+ GW-->>Client: [SSE: run_done]
+ end
+```
+
+**图 9-1:ReAct 推理循环时序图。** 虚线箭头 = 异步事件;实线箭头 = 同步调用。工具执行在独立 goroutine 中并行调度。
+
+**步骤详解:**
+
+1. **输入归一化**(`PrepareInput` → `UserInput`):Gateway 将客户端 JSON-RPC 请求转换为领域模型,附加 RunID、SessionID、Workdir、CapabilityToken 等元数据
+2. **会话加载与加锁**(`loadOrCreateSession`):从 SQLite 加载会话;同一 SessionID 的并发 Run 通过 `sessionLock` 串行化(不同会话可并行)
+3. **Hook 执行**:触发 `SessionStart` 和 `UserPromptSubmit` 生命周期钩子;若 Hook 返回 `Blocked`,Run 终止并返回阻断原因
+4. **用户消息追加**:将用户输入 Parts 作为 `user` 角色消息 append 到会话消息列表
+5. **主循环(ReAct Loop)**:
+ - `prepareTurnBudgetSnapshot`:检查 Token 预算,若超阈值触发 Compact(参见 §9.2)
+ - Context Builder 组装完整 Prompt(参见 §8.6)
+ - Provider.Generate 发起流式推理,通过 channel 推送 `StreamEvent`
+ - 解析模型回复中的 `tool_calls`:若无工具调用 → 循环结束,产出最终文本
+ - 并行执行工具(`executeTools`,默认并发度 4):每个工具调用经过 Security Engine → Executor → 结果回灌
+ - 循环回到步骤 5a,直到模型产出纯文本回复或达到 `max_turns` 上限
+6. **终止处理**:发送 `run_done` 事件(含 Token Usage 汇总、Diff 摘要);更新 Resume Checkpoint;释放会话锁
+
+**异常路径:**
+
+| 异常 | 处理策略 |
+|------|----------|
+| `max_turns` 达到上限(默认由配置控制) | 发送 `run_error` + `max_turn_limit` 原因;最后一次推理结果仍保留在会话中 |
+| Provider 返回错误(网络/限流/认证) | 按 `generate_max_retries` 配置自动重试(在 turn 内最多 `max_attempts` 次);不可恢复时 `run_error` |
+| 工具执行超时 | 返回 error 类型的 ToolResult 回灌给模型(不中断循环),让模型决定如何处理 |
+| 用户手动取消(`CancelActiveRun`) | context 取消传播 → `run_error` + `cancelled` 原因 |
+| 循环检测(重复工具调用签名) | 若连续 3 轮工具签名相同,注入自愈提醒 Prompt(`NoProgressReminder`)引导模型改变策略 |
+
+### 9.2 上下文压缩流程(Compact Flow)
+
+**触发条件:** 每轮推理前 `prepareTurnBudgetSnapshot` 检测到 Token 消耗接近预算阈值(基于 Provider 的 `EstimateInputTokens` 估算 + 配置的 `compact_trigger_ratio`)。
+
+**参与组件:** Runtime → Context Builder → MicroCompact → Compact Runner (Provider) → Session Store
+
+**流程:**
+
+```mermaid
+sequenceDiagram
+ participant RT as Runtime
+ participant CC as Context/Compact
+ participant SS as Session Store
+
+ RT->>CC: BudgetSnapshot(session)
+ CC-->>RT: needsCompact = true
+
+ RT->>CC: Compact(input)
+ CC->>CC: MicroCompact: 对可压缩 tool_result 摘要化
+ alt MicroCompact 不足
+ CC->>CC: Full Compact: CompactRunner.Generate() 生成结构化摘要
+ end
+ CC->>CC: Trim: 裁剪最旧消息(保留 System Prompt + Pin 标记)
+
+ RT->>SS: SaveCompacted()
+ SS->>SS: ReplaceTranscript() 原子替换消息列表 + 更新 SessionHead
+```
+
+**两级压缩策略:**
+
+| 级别 | 触发条件 | 操作 | 对上下文的影响 |
+|------|----------|------|---------------|
+| **MicroCompact** | 单次 Tool Call 结果过大,导致本轮预算紧张 | 对单个 tool_result 内容摘要化(保留关键输出,丢弃冗长中间日志) | 仅影响当前工具结果,不改变历史 |
+| **Full Compact** | MicroCompact 后仍超预算,或累计历史消息过多 | 将历史消息中可压缩的部分通过 LLM 生成结构化摘要,替换原始消息 | 历史消息被摘要替代,System Prompt + 最近 N 轮保留 |
+
+**关键不变量:**
+- System Prompt(corePrompt + capabilities + rules + skillPrompt)永不参与压缩
+- Pin 标记的消息(如用户原始问题、Plan 批准记录)不被压缩
+- 压缩后的消息列表通过 `ReplaceTranscript` 原子替换(单事务),确保不会出现半压缩状态
+
+### 9.3 权限决策流程(Permission Resolution Flow)
+
+**触发条件:** 工具执行前,Tools Manager 调用 Security Engine 检查操作权限;若决策为 `ask`,Runtime 暂停执行并等待用户决策。
+
+**参与组件:** Runtime → Tools Manager → Security Engine(PolicyEngine + WorkspaceSandbox)→ Gateway → 客户端
+
+**流程:**
+
+```mermaid
+sequenceDiagram
+ participant RT as Runtime
+ participant TM as Tools Manager
+ participant SE as Security Engine
+ participant GW as Gateway
+ participant Client as 客户端
+
+ RT->>TM: Execute(toolCall)
+ TM->>SE: Check(action)
+ SE->>SE: 匹配策略规则(Priority 降序)
+ SE-->>TM: Decision: ask
+ TM-->>RT: PermissionDecisionError
+ RT->>GW: emit(permission_request)
+ GW-->>Client: [SSE: permission_request]
+ Client->>GW: resolve_permission (JSON-RPC)
+ GW->>RT: ResolvePermission(allow_once / allow_session / reject)
+ alt allow_once 或 allow_session
+ RT->>TM: Execute(toolCall) [重试]
+ opt allow_session
+ TM->>TM: RememberSessionDecision(PermissionFingerprint)
+ end
+ else reject
+ RT->>RT: 返回 error ToolResult
+ end
+```
+
+**图 9-3:权限决策时序图。** 关键特征:Runtime 在 `ask` 状态下暂停执行,等待客户端通过 JSON-RPC 回传决策。
+
+**安全决策链:**
+
+```mermaid
+flowchart TD
+ A["Action
(ToolName + Resource + Target)"] --> B["PolicyEngine.Check()"]
+ B -->|"匹配规则(按 Priority 降序)"| C{"命中规则?"}
+ C -->|"是"| D["返回 Rule.Decision"]
+ C -->|"否"| E["返回 defaultDecision
(通常为 ask)"]
+ D --> F["WorkspaceSandbox.Check()"]
+ E --> F
+ F -->|"路径穿越检测 (../、symlink)"| G{"安全?"}
+ G -->|"否"| H["deny"]
+ G -->|"是"| I["工作区边界检查"]
+ I -->|"越界"| J["deny
(生成 safe 候选路径)"]
+ I -->|"通过"| K["allow"]
+```
+
+**图 9-4:安全决策链。** 两阶段检查:先过策略引擎(PolicyEngine),再过沙箱(WorkspaceSandbox)。任一阶段拒绝即终止。
+
+**三类决策含义:**
+
+| 决策 | 含义 | 后续行为 |
+|------|------|----------|
+| `allow` | 安全策略明确放行 | 直接执行 |
+| `deny` | 安全策略明确拒绝 | 返回 error ToolResult,不询问用户 |
+| `ask` | 需用户判断 | Runtime 暂停,发送 `permission_request` 事件,等待用户通过 `resolve_permission` 回复 |
+
+**会话级记忆:** 用户选择 `allow_session` 后,Manager 调用 `RememberSessionDecision` 将决策持久化到会话权限记忆表,该会话后续同类操作自动放行(基于 `PermissionFingerprint` 匹配)。
+
+### 9.4 Runner 远程工具执行流程
+
+**触发条件:** Gateway 收到工具执行请求,且该 Runner 已注册并空闲,Gateway 将请求通过 WebSocket 转发至远程 Runner 执行。
+
+**参与组件:** Gateway → (WebSocket) → Runner → Tools Manager → Security Engine
+
+**流程:**
+
+```mermaid
+sequenceDiagram
+ participant GW as Gateway
+ participant RN as Runner (远程)
+ participant TL as Tools/文件系统
+
+ GW->>GW: 选择已注册的 Runner
+ GW->>RN: WebSocket: tool_exec_request
+ RN->>RN: capSigner.Verify(token)
+ RN->>TL: toolMgr.Execute()
+ TL-->>RN: [ToolResult]
+ RN->>GW: WebSocket: tool_exec_result
+
+ loop 每 N 秒
+ GW->>RN: WebSocket: heartbeat
+ RN->>GW: WebSocket: heartbeat_ack
+ end
+```
+
+**关键机制:**
+
+| 机制 | 说明 |
+|------|------|
+| **反向连接** | Runner 主动连接 Gateway(而非 Gateway 连接 Runner),因此 Runner 可位于 NAT/防火墙后 |
+| **心跳保活** | 默认 10s 间隔;超时未收到 ack 则判定断连,触发重连 |
+| **自动重连** | 指数退避(500ms → 1s → 2s → ... → 10s max) |
+| **Capability Token** | 每个工具执行请求附带签名令牌,校验 Runner 是否有权执行该工具及访问目标路径 |
+| **工作区白名单** | `WorkdirAllowlist` 限制 Runner 只能访问指定目录,即使 Capability Token 签名有效 |
+
+### 9.5 会话生命周期
+
+**触发条件:** 用户首次发起对话(创建) / 每次 Run(加载 + 追加) / 系统定时任务(清理)。
+
+**状态流转:**
+
+```mermaid
+stateDiagram-v2
+ [*] --> Empty: CreateSession()
+ Empty --> Active: LoadSession()
+ Active --> Updated: AppendMessages()
+ Updated --> Updated: AppendMessages()
+ Updated --> Compacted: Compact()
+ Active --> Compacted: Compact()
+ Active --> Expired: 30天无更新
+ Updated --> Expired: 30天无更新
+ Compacted --> Expired: 30天无更新
+ Expired --> [*]: CleanupExpiredSessions()
+```
+
+**图 9-2:会话生命周期状态机。** Active/Updated/Compacted 均为活跃状态;30 天阈值通过 `DefaultSessionMaxAge` 配置。
+
+**数据生命周期:**
+
+| 数据类型 | 存储位置 | 生命周期 |
+|----------|----------|----------|
+| 会话消息历史 | SQLite `messages` 表 | 单会话最多 8192 条;超出自动裁剪最旧消息;30 天未更新则整体清理 |
+| 会话头状态 | SQLite `sessions` 表 | 与会话同生命周期 |
+| Checkpoint 快照 | SQLite `checkpoint_records` 表 | 每个 Run 内保留;自动修剪(可配置保留数) |
+| 权限记忆 | SQLite session_permission 表 | 跟随会话,会话删除时清理 |
+| 代码变更 PerEdit | Checkpoint 文件系统存储 | Run 结束时捕获 Diff 摘要,关联 Checkpoint ID 引用 |
+| 配置文件 | `~/.neocode/config.yaml` | 持久保留,手动修改 |
+
+### 9.6 端到端动态视图:一次典型代码修改
+
+以下通过一次典型代码修改请求,串联 §9.1-§9.5 的核心流程,展示 Gateway、Runtime、Context、Provider、Tools、Security、Session 在同一 Run 中的协作关系。
+
+> **示例输入:** *"帮我在 auth.go 的 Login 函数里加一个登录失败次数限制,超过 5 次就锁定 30 秒"*
+
+```mermaid
+sequenceDiagram
+ actor User as 用户 (CLI)
+ participant GW as Gateway
+ participant RT as Runtime
+ participant CTX as Context
+ participant PR as Provider
+ participant TL as Tools
+ participant SE as Security
+ participant SS as Session
+
+ Note over User,SS: ══════════ 第 1 轮:理解需求 ══════════
+
+ User->>GW: run "帮我在 auth.go 加登录限流"
+ GW->>RT: PrepareInput → Run (RunID=r1)
+ RT->>SS: LoadSession / LockSession
+ RT->>CTX: Build(session) → SystemPrompt + Messages
+ CTX-->>RT: [Prompt: 含 codebase 上下文]
+ RT->>PR: Generate(prompt)
+ PR-->>RT: [StreamEvent: tool_call: codebase_read("auth.go")]
+ RT->>TL: Execute(codebase_read, "auth.go")
+ TL->>SE: Check(read, "auth.go")
+ SE-->>TL: allow
+ TL-->>RT: [auth.go 内容: func Login()...]
+ RT->>RT: 回灌 tool_result 到消息历史
+
+ Note over User,SS: ══════════ 第 2 轮:写代码 + 权限决策 ══════════
+
+ RT->>PR: Generate(继续)
+ PR-->>RT: [StreamEvent: tool_call: filesystem_edit("auth.go", old_str, new_str)]
+ RT->>TL: Execute(filesystem_edit, "auth.go")
+ TL->>SE: Check(write, "auth.go")
+ SE-->>TL: ask (首次写入此文件)
+ TL-->>RT: PermissionDecisionError
+ RT->>GW: emit(permission_request)
+ GW-->>User: [SSE: "是否允许编辑 auth.go?"]
+ User->>GW: resolve_permission(allow_session)
+ GW->>RT: ResolvePermission(allow_session)
+ RT->>TL: Execute(filesystem_edit, "auth.go") [重试]
+ TL->>SE: Check(write, "auth.go")
+ SE-->>TL: allow (会话记忆命中)
+ TL->>TL: RememberSessionDecision → 后续同文件编辑自动放行
+ TL-->>RT: [编辑成功]
+
+ Note over User,SS: ══════════ 第 3 轮:编译验证 ══════════
+
+ RT->>PR: Generate(继续)
+ PR-->>RT: [StreamEvent: tool_call: bash("go build ./...")]
+ RT->>TL: Execute(bash, "go build ./...")
+ TL->>SE: Check(bash, "go build")
+ SE-->>TL: allow (只读命令)
+ TL-->>RT: [编译通过或报错]
+
+ Note over User,SS: ══════════ 终结 ══════════
+
+ RT->>PR: Generate(继续)
+ PR-->>RT: [final text: "已在 auth.go 中添加..."]
+
+ opt 若 Token 预算接近阈值
+ RT->>CTX: Compact(session)
+ CTX->>CTX: MicroCompact(tool_results) → FullCompact(history)
+ CTX->>SS: ReplaceTranscript()
+ end
+
+ RT->>SS: AppendMessages + UpdateSessionHead
+ RT->>SS: CreateCheckpoint(end_of_turn)
+ RT->>GW: emit(run_done {usage, diff_summary})
+ GW-->>User: [SSE: run_done + Diff 摘要]
+```
+
+**图 9-5:端到端场景走查时序图。** 此图将五个核心流程(ReAct 循环、权限决策、Compact、Checkpoint、会话持久化)串联为一个完整的用户故事。关键观察:
+
+1. **多轮推理是自然的:** 模型先在轮 1 读文件理解现状,轮 2 写修改,轮 3 跑编译验证——这是 AI Agent 的标准行为模式,不是设计缺陷
+2. **权限决策在关键路径上:** `ask → permission_request → resolve_permission` 的暂停-恢复循环是 Human-in-the-loop 的工程实现,在第 2 轮中首次写文件时触发
+3. **会话记忆消除重复审批:** 用户选择 `allow_session` 后,同会话内同文件编辑自动放行——这是 Security Engine 的 PermissionFingerprint 机制
+4. **安全性在工具层而非 Runtime 层:** 每次工具执行前都经过 Security Engine,Runtime 不需要知道哪些操作是"安全的"
+5. **Compact 和 Checkpoint 是隐式的:** 用户不感知 Compact(Token 预算达到阈值时自动触发)和 Checkpoint(每轮 `end_of_turn` 自动创建),但它们是系统安全网的关键组成部分
+
+---
+
+## 10. 数据与状态管理
+
+### 10.1 核心数据模型
+
+**会话聚合根(Session):**
+
+```
+Session
+├── ID, Title, Provider, Model ← 身份与归属
+├── CreatedAt, UpdatedAt ← 时间戳
+├── Workdir ← 运行时工作目录
+├── TaskState ← 任务状态快照
+│ ├── Summary, Goal, Constraints
+│ ├── Architecture, Design
+│ └── Progress, NextSteps
+├── AgentMode ← 当前模式(default / plan)
+├── Messages[] ← 对话历史(关联数据)
+│ ├── UserMessage / AssistantMessage / ToolResult
+│ ├── 每条含 ContentPart[](text / tool_call / tool_result)
+│ └── TokenUsage(input / output / cache)
+├── ActivatedSkills[] ← 已激活的 Skill 列表
+├── Todos[] ← Todo 列表
+│ └── TodoItem: ID, Content, Status, Priority
+├── CurrentPlan ← 当前 Plan 快照
+│ └── PlanArtifact: Revision, Status, Steps, ...
+├── TokenInputTotal / TokenOutputTotal ← 累计 Token 消耗
+└── HasUnknownUsage ← 是否含未统计的用量
+```
+
+**工具调用与结果模型:**
+
+```
+ToolCall(模型产出) ToolResult(系统返回)
+├── ID ├── ToolCallID(对应)
+├── Name(工具名) ├── Content(文本结果)
+├── Arguments(JSON) ├── IsError
+└── Type(function) └── Metadata(结构化事实)
+```
+
+### 10.2 关键状态机
+
+#### 10.2.1 任务状态(TaskState)
+
+TaskState 是会话级别的"任务理解"快照,由模型在推理过程中填充和更新。Runtime 在每轮开始时将当前 TaskState 注入 System Prompt 的 `taskState` 段落,确保模型理解当前上下文阶段。
+
+TaskState 本身不强制执行状态转换——它是一个模型填充的数据结构,而非工作流引擎。转换完全由模型决定(在当前轮次的 System Prompt 中看到当前 TaskState 后自行决定是否更新)。
+
+#### 10.2.2 Checkpoint 状态机
+
+```mermaid
+stateDiagram-v2
+ [*] --> creating: 触发快照创建
+ creating --> available: 写入完成(原子事务)
+ creating --> broken: 写入异常
+ available --> restored: RestoreCheckpoint()
+ available --> pruned: PruneExpiredCheckpoints()
+ restored --> pruned: 修剪策略触发
+ broken --> [*]
+ pruned --> [*]
+```
+
+触发创建的场景:`pre_write`(写操作前)、`compact`(压缩前)、`plan_mode`(Plan 模式切换)、`manual`(用户手动)、`end_of_turn`(每轮结束)、`pre_restore_guard`(恢复前的安全快照)。创建和写入在同一 SQLite 事务中完成,确保不会出现"半写入"的快照记录。
+
+#### 10.2.3 权限决策状态
+
+```mermaid
+stateDiagram-v2
+ [*] --> SecurityCheck: 工具执行请求
+
+ state SecurityCheck {
+ [*] --> PolicyMatch: Action.Validate()
+ PolicyMatch --> Allow: 策略明确放行
+ PolicyMatch --> Deny: 策略明确拒绝
+ PolicyMatch --> Ask: 无匹配规则 → 询问用户
+ }
+
+ SecurityCheck --> Execute: allow
+ SecurityCheck --> Reject: deny
+ SecurityCheck --> WaitUser: ask
+
+ WaitUser --> AllowOnce: 用户选 allow_once (不记忆)
+ WaitUser --> AllowSession: 用户选 allow_session (持久化 PermissionFingerprint)
+ WaitUser --> Reject: 用户选 reject
+
+ AllowOnce --> Execute
+ AllowSession --> Execute
+```
+
+### 10.3 并发控制策略
+
+| 场景 | 机制 | 说明 |
+|------|------|------|
+| 同一会话并发 Run | `sessionLock`(mutex per sessionID) | 后续同会话 Run 排队等待;不同会话可并行 |
+| Config 读写 | `Manager.mu`(RWMutex) + copy-on-read | `Get()` 返回配置快照的深拷贝,写入通过 `Update(mutateFn)` 原子执行 |
+| Provider 实例创建 | `providerCreateMu`(Mutex) | 防止并发切换 Provider 时创建重复连接 |
+| WebSocket 并发写 | `Runner.writeMu`(Mutex) | 保护 WebSocket 连接级别的并发写入 |
+| 工具并行执行 | goroutine + WaitGroup | Runtime 在 ReAct Loop 中并行调度最多 N 个工具(可配置),每个工具在独立 goroutine 中执行 |
+
+### 10.4 数据一致性保证
+
+| 操作 | 一致性级别 | 实现方式 |
+|------|-----------|----------|
+| 消息追加 | 原子追加 | SQLite 单事务:`INSERT INTO messages` + `UPDATE sessions` |
+| Compact 替换 | 原子替换 | `ReplaceTranscript` 在单事务内删除旧消息 + 插入新摘要 + 更新 SessionHead |
+| Checkpoint 创建 | 原子写入 | 单事务:`INSERT checkpoint_record` → `INSERT session_cp` → `UPDATE record SET status=available` |
+| 配置更新 | 内存原子 + 持久化 | `Manager.Update(mutateFn)` 先在内存应用变更,再整体 `Save()` 落盘 |
+| 跨进程状态(Gateway ↔ 客户端) | 最终一致 | Gateway 通过 StreamRelay 广播 Runtime 事件;客户端通过 SSE/WS 订阅更新 |
+
+---
+
+## 11. 接口与集成
+
+### 11.1 通信模式总览
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ 通信协议分层 │
+│ │
+│ 请求 / 响应(同步) │
+│ ┌──────────────────────────────────────────────────────────┐ │
+│ │ 协议: JSON-RPC 2.0 │ │
+│ │ 传输: HTTP POST(loopback 或网络) │ │
+│ │ 方向: 客户端 → Gateway → Runtime │ │
+│ │ 典型 action: run / ask / cancel / resolve_permission │ │
+│ │ │ │
+│ │ 请求帧格式: │ │
+│ │ { "jsonrpc": "2.0", "method": "gateway.run", │ │
+│ │ "id": "req-1", "params": {...} } │ │
+│ │ │ │
+│ │ 响应帧格式: │ │
+│ │ { "jsonrpc": "2.0", "type": "ack", "action": "pong", │ │
+│ │ "request_id": "req-1", "payload": {...} } │ │
+│ └──────────────────────────────────────────────────────────┘ │
+│ │
+│ 事件流(异步) │
+│ ┌──────────────────────────────────────────────────────────┐ │
+│ │ 协议: SSE (Server-Sent Events) 或 WebSocket (双向消息) │ │
+│ │ 方向: Runtime → Gateway (StreamRelay) → 客户端 │ │
+│ │ 典型事件: run_progress / run_done / run_error / │ │
+│ │ permission_request / ask_chunk / ask_done │ │
+│ │ │ │
+│ │ SSE 端点: GET /sse?session_id=...&run_id=... │ │
+│ │ WebSocket 端点: ws://localhost:PORT/ws │ │
+│ └──────────────────────────────────────────────────────────┘ │
+│ │
+│ 消息队列(内部) │
+│ ┌──────────────────────────────────────────────────────────┐ │
+│ │ 机制: Go channel (StreamRelay 内部 pub/sub) │ │
+│ │ 方向: Runtime → StreamRelay → 所有订阅连接 │ │
+│ │ 容量: DefaultStreamQueueSize(每个连接独立缓冲) │ │
+│ └──────────────────────────────────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+```
+
+### 11.2 同步 vs 异步交互
+
+| 交互类型 | 同步/异步 | 超时 | 说明 |
+|----------|----------|------|------|
+| `gateway.run` | 异步 | 无直接超时(30 min Runtime 硬超时) | Gateway 立即返回 ack;后续通过 SSE/WS 推送 run_progress / run_done |
+| `gateway.ask` | 异步 | 同上 | 轻量问答,类似 run 但流程更短 |
+| `gateway.cancel` | 同步 | 10s | 向 Runtime 发取消信号,等待确认 |
+| `gateway.ping` | 同步 | 3s | 连接探活 |
+| `gateway.authenticate` | 同步 | 5s | Token 认证 |
+| `gateway.resolve_permission` | 同步 | 10s | 用户权限决策,Runtime 在等待此回复时处于暂停状态 |
+| Runner → Gateway | 异步 | 30s(请求级) | WebSocket 双向消息 |
+
+### 11.3 认证模型
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ 认证体系 │
+│ │
+│ 本地模式(无 Authenticator) │
+│ ┌─────────────────────────────────────────────────┐ │
+│ │ 场景: neocode CLI / TUI (本地 loopback RPC) │ │
+│ │ 身份: auth.DefaultLocalSubjectID = "local_admin" │ │
+│ │ 鉴权: gateway.authenticate 自动通过(空 Token) │ │
+│ └─────────────────────────────────────────────────┘ │
+│ │
+│ 网络模式(有 Authenticator) │
+│ ┌─────────────────────────────────────────────────┐ │
+│ │ 场景: Web / Desktop / Runner / Feishu Adapter │ │
+│ │ 身份: Authenticator.ResolveSubjectID(token) │ │
+│ │ 鉴权: 客户端先发送 gateway.authenticate 获取 │ │
+│ │ subject_id;后续请求携带此身份 │ │
+│ └─────────────────────────────────────────────────┘ │
+│ │
+│ Runner 额外层 │
+│ ┌─────────────────────────────────────────────────┐ │
+│ │ Capability Token: 签名令牌校验 Runner 有权 │ │
+│ │ 执行哪些工具、访问哪些路径 │ │
+│ │ WorkdirAllowlist: Runner 配置级目录白名单 │ │
+│ └─────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────┘
+```
+
+### 11.4 超时、重试与幂等性
+
+| 机制 | 配置项 | 默认值 | 作用域 |
+|------|--------|--------|--------|
+| 工具执行超时 | `tool_timeout_sec` | 20s | 单个工具调用(bash 工具可单独配置) |
+| 模型首包超时 | `generate_start_timeout_sec` | 90s | Provider.Generate 首次响应 |
+| 模型空闲超时 | `generate_idle_timeout` | 由 Provider 决定 | 流式响应中连续无数据 |
+| 模型重试 | `generate_max_retries` | 由 Provider 决定 | 同一 turn 内失败重试 |
+| Runtime 硬超时 | `defaultRuntimeOperationTimeout` | 30 min | 单次 Run 的最大时长 |
+| Runner 请求超时 | `RequestTimeout` | 30s | Runner 侧工具执行等待 |
+| Runner 重连 | `ReconnectBackoffMin` / `Max` | 500ms ~ 10s | WebSocket 断连后自动重连 |
+
+**幂等性保障:**
+- 每次 Run 生成唯一 `RunID`(客户端或 Gateway 生成),同一 RunID 的重复 submit 被 Gateway 去重
+- 工具执行不保证幂等(如 Bash、WriteFile 天然非幂等),由模型在 Prompt 指导下自行判断
+- Session 消息追加通过 SQLite 事务保证不重复写入
+- Checkpoint 通过 `CheckpointID` 去重
+
+### 11.5 错误分类
+
+参考 Gateway 错误编目(`docs/reference/gateway-error-catalog.md`):
+
+| 错误类别 | 错误码前缀 | 典型场景 | HTTP 映射 |
+|----------|-----------|----------|-----------|
+| 认证错误 | `unauthorized` | 无效 Token、未认证连接 | 401 |
+| 参数校验 | `invalid_params` | 缺失必填字段、类型错误 | 400 |
+| 不支持操作 | `unsupported_action` | 未注册的 action | 400 |
+| 运行时错误 | `runtime_unavailable` | Runtime 进程异常 | 503 |
+| 会话错误 | `session_not_found` | SessionID 不存在 | 404 |
+| 内部错误 | `internal_error` | Gateway 自身异常 | 500 |
+| 超时 | `timeout` | 操作超时 | 504 |
+| 权限拒绝 | `permission_denied` | 安全策略拒绝 | 403 |
+
+### 11.6 版本兼容策略
+
+| 层面 | 策略 |
+|------|------|
+| **Gateway RPC API** | JSON-RPC 2.0 协议版本固定为 `"2.0"`;新增 action 不影响旧客户端;废弃 action 保留一个版本过渡期 |
+| **Session 数据库 Schema** | `sqliteSchemaVersion` 管理(当前 v7);启动时自动迁移(`MigrateSchema`) |
+| **配置文件** | 向后兼容:新增字段有默认值;废弃字段在加载时忽略并 warn;`StaticDefaults()` 保证旧配置可启动 |
+| **Provider 接口** | `Provider` interface 仅 2 个方法,极简稳定;新增可选能力通过 `GenerateRequest` 结构体字段扩展(`omitempty` JSON tag) |
+| **Web UI** | 嵌入到 Go binary 中(`web/dist/`),与二进制同版本发布;不独立部署 |
+| **自更新** | `go-selfupdate` 机制;二进制整体替换;配置文件不自动迁移(向后兼容保证可用) |
+
+---
+
+## 12. 部署视图
+
+### 12.1 产物矩阵
+
+NeoCode 通过 goreleaser 构建两个二进制产物(Inferred from `.goreleaser.yaml`):
+
+| 产物 | 入口 | 说明 |
+|------|------|------|
+| `neocode` | `cmd/neocode/main.go` | 完整 CLI:TUI 交互、Gateway 服务端 (`neocode gateway`)、HTTP Daemon (`neocode daemon`)、Local Runner (`neocode runner`)、Shell 诊断 (`neocode diag`) |
+| `neocode-gateway` | `cmd/neocode-gateway/main.go` | 独立 Gateway 二进制:仅包含 Gateway 服务端,适合在服务器上长期运行为守护进程 |
+
+**构建目标矩阵:**
+
+| OS | Arch |
+|----|------|
+| Linux | amd64, arm64 |
+| macOS (darwin) | amd64, arm64 |
+| Windows | amd64, arm64 |
+
+所有产物均以 `CGO_ENABLED=0` 静态编译,无系统依赖。Web UI 静态资源(React build 产物)嵌入在 `neocode` 二进制中。
+
+### 12.2 部署拓扑
+
+```
+┌─────────────────────────────────────────────────────────────────────┐
+│ 单机部署(开发者工作站) │
+│ │
+│ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │
+│ │neocode │ │neocode │ │neocode │ │
+│ │CLI / TUI │ │gateway │ │daemon │ │
+│ │ │───▶│(JSON-RPC) │ │(HTTP :18921) │ │
+│ │ │ │ │ │ │ │
+│ └──────────┘ └─────┬─────┘ └──────┬───────┘ │
+│ │ │ │
+│ │ ┌─────┴────────┐ │
+│ │ │neocode:// URL │ │
+│ │ │Scheme 唤醒 │ │
+│ │ └──────────────┘ │
+│ │ │
+│ ┌───────────┴───────────┐ │
+│ │ ~/.neocode/ │ │
+│ │ ├── config.yaml │ │
+│ │ ├── session.db │ │
+│ │ ├── checkpoint/ │ │
+│ │ └── skills/ │ │
+│ └───────────────────────┘ │
+└─────────────────────────────────────────────────────────────────────┘
+
+┌─────────────────────────────────────────────────────────────────────┐
+│ 分布式部署(Runner 反向连接) │
+│ │
+│ 工位电脑 A (NAT/防火墙后) 服务器 / 云主机 │
+│ ┌──────────────────────┐ ┌──────────────────────┐ │
+│ │ neocode runner │──WS──────▶│ neocode gateway │ │
+│ │ (工具执行) │ 主动连接 │ (RPC + 事件中继) │ │
+│ └──────────────────────┘ └──────────────────────┘ │
+│ ▲ │
+│ 手机 / 远程 │ │
+│ ┌──────────────────────┐ │ │
+│ │ 飞书 / Web / CLI │──HTTPS/JSON-RPC─────┘ │
+│ └──────────────────────┘ │
+└─────────────────────────────────────────────────────────────────────┘
+```
+
+**图 12-1:部署拓扑。** 单机模式(上):所有组件在同一台机器上,通过本地 loopback RPC 通信。分布式模式(下):Local Runner 主动连接 Gateway,使远程客户端可以通过 Gateway 驱动 Runner 所在机器的工具执行。
+
+### 12.3 环境隔离
+
+| 环境 | 数据目录 | 说明 |
+|------|----------|------|
+| 默认 | `~/.neocode/` | 所有数据(配置、会话、Checkpoint、Skills 缓存)的根目录 |
+| `NEOCODE_HOME` 覆盖 | `$NEOCODE_HOME/` | 通过环境变量切换数据目录,支持多 Profile 隔离 |
+| 工作目录 | `--workdir` / `workdir` 配置项 | 限制工具的文件系统访问边界 |
+
+### 12.4 扩缩容考量
+
+| 维度 | 限制 | 说明 |
+|------|------|------|
+| 单机并发会话 | 无进程级上限 | 不同会话通过 `sessionLock` 并行执行;同会话串行化 |
+| Gateway 连接数 | `DefaultNetworkMaxStreamConnections`(可配置) | 超过上限时新连接收到 `too_many_connections` 错误 |
+| Session 消息量 | 单会话最多 8192 条 | 超限自动裁剪最旧消息 |
+| Runner 数量 | 无硬限制 | 多个 Runner 可注册到同一 Gateway,Gateway 按策略选择执行节点 |
+| 数据库容量 | SQLite 单文件 | 30 天过期会话自动清理,Checkpoint 自动修剪 |
+
+---
+
+## 13. 安全设计
+
+### 13.1 安全模型总览
+
+NeoCode 的安全设计遵循**纵深防御**原则:不依赖单一安全机制,而是在多个层面上独立校验。
+
+```
+外部输入(用户/IM/CI)
+ │
+ ▼
+┌──────────────────┐ 第 1 层:认证
+│ Gateway Auth │ Token 校验 → subject_id
+│ (本地/网络模式) │ 未认证连接仅允许 ping + authenticate
+└────────┬─────────┘
+ │
+ ▼
+┌──────────────────┐ 第 2 层:ACL 授权
+│ Gateway ACL │ method × source 白名单
+│ (每连接级) │ 未授权 method → acl_denied
+└────────┬─────────┘
+ │
+ ▼
+┌──────────────────┐ 第 3 层:工具级安全策略
+│ Security Engine │ PolicyEngine(规则匹配)
+│ (每次调用) │ + WorkspaceSandbox(路径校验)
+└────────┬─────────┘ + CapabilityToken(Runner 权限)
+ │
+ ▼
+┌──────────────────┐ 第 4 层:操作系统约束
+│ OS 级隔离 │ 进程权限 = 当前用户
+│ │ 文件系统权限 = OS ACL
+└──────────────────┘ 网络边界 = 本机 loopback
+```
+
+### 13.2 认证(Authentication)
+
+所有客户端(无论 TUI、Web、Desktop 还是第三方)统一通过 **JSON-RPC `gateway.authenticate`** 方法完成认证。Gateway 侧根据是否配置了 `Authenticator` 决定如何处理认证请求:
+
+| 模式 | Gateway 配置 | 认证行为 | 典型场景 |
+|------|-------------|----------|----------|
+| **本地模式** | 未配置 `Authenticator` | `gateway.authenticate` 可直接调用(允许空 Token),Gateway 自动授予 `local_admin` 身份 | 开发者在自己机器上启动 CLI,Gateway 默认无 Authenticator |
+| **网络模式** | 配置了 `Authenticator` | 客户端必须提供有效 Token → Authenticator 解析为 `subject_id` → 连接携带此身份发起后续请求 | Web UI、Desktop、Runner、飞书 Bot 等通过 HTTP 连接 Gateway 的场景 |
+
+**关键安全属性:**
+- Gateway 在本地模式下仅接受 loopback 地址连接(`127.0.0.1`),不可从外部网络访问
+- 网络模式下的 `Authenticator` 是可插拔接口:内置 static token 实现,可替换为 OAuth2/JWT/LDAP 等
+- `subject_id` 在连接生命周期内不变,作为所有操作的审计主体标识
+- 所有客户端使用**同一套 RPC 协议**完成认证,不存在"IPC 免认证旁路"——这是 Gateway 作为统一安全边界的基础
+
+### 13.3 授权(Authorization)
+
+**Gateway ACL(连接级):** 每个连接在认证后获得 ACL profile,控制允许调用的 RPC method 列表。未在 ACL 白名单中的 method 返回 `acl_denied`。
+
+**Security Engine(操作级):** 每次工具执行前经过两阶段检查:
+
+| 阶段 | 组件 | 检查内容 |
+|------|------|----------|
+| 策略匹配 | `PolicyEngine.Check()` | 按 Priority 降序遍历 `PolicyRule` 列表;匹配条件包括 ActionType、Resource(工具名)、TargetPrefix(路径前缀)、HostPatterns(URL 域名)等;命中返回 `allow` / `deny` / `ask` |
+| 沙箱校验 | `WorkspaceSandbox.Check()` | 路径穿越检测(`../`、Symlink 逃逸)→ `deny`;工作目录边界检查 → 越界时自动生成 safe 候选路径 |
+
+**敏感路径自动检测:**
+
+Security Engine 内置敏感路径特征库,无需配置即可检测:
+- 目录关键词:`secrets`、`.ssh`、`.gnupg`、`.aws`、`.config`
+- 文件名模式:`.env`、`*.secret`、`*.token`、`*.key`、`*.pem`、`id_rsa`、`id_ed25519` 等
+- 命中敏感路径的操作自动升级为 `deny`(即使 PolicyRule 未显式配置)
+
+### 13.4 密钥管理
+
+| 原则 | 实现 |
+|------|------|
+| **不入配置文件** | `api_key_env` 配置项仅存储环境变量名,不存储密钥值 |
+| **仅在内存中使用** | `APIKeyResolver(envName)` 在 Provider 发起请求前才从环境变量读取 |
+| **不入日志** | 日志、调试输出、配置快照序列化时排除 `api_key_env` 的值域 |
+| **不通过 Gateway 传输** | Provider 调用直接从 Runtime 进程发起,密钥不经过 Gateway 的 RPC 通道 |
+| **Runner 隔离** | Runner 的 Capability Token 使用 HMAC-SHA256 签名,包含工具白名单和路径白名单,有时效性 |
+
+### 13.5 输入校验
+
+| 校验点 | 机制 |
+|--------|------|
+| **JSON-RPC 参数** | Gateway 在 dispatch 前对每个 action 的 params 做结构校验;必填字段缺失 → `invalid_params` |
+| **工具参数** | 每个 `Executor` 在 `Execute()` 中独立校验参数;bash 工具检测交互式命令(`vim`、`top` 等)并拒绝执行 |
+| **文件路径** | 所有路径先经 `ResolveWorkspacePath()` 归一化(解析相对路径、Symlink),再经 Sandbox 校验 |
+| **URL** | `webfetch` 工具限制协议(仅 http/https)、限制响应大小(可配置)、禁止访问内网地址(可配置) |
+| **消息内容** | 用户输入 Parts 在 Runtime 入口做基本合法性校验(非空、格式正确) |
+
+### 13.6 审计追踪
+
+| 审计要素 | 记录方式 |
+|----------|----------|
+| **主体标识** | 每个请求携带 `subject_id`,贯穿 Gateway → Runtime → Session 全链路 |
+| **请求追踪** | `SessionID + RunID` 唯一标识一次完整的用户交互;所有事件(run_progress、tool_call、permission_request)附带这两个 ID |
+| **操作审计** | 工具执行前 Security Engine 的 Check 调用记录 Action 详情(ToolName、Resource、TargetType、Target、NormalizedIntent) |
+| **权限记忆** | `allow_session` 决策持久化到 SQLite,可追溯"谁在何时对什么操作授权了会话级放行" |
+| **指标暴露** | GatewayMetrics 提供 `auth_failures_total`(认证失败)、`acl_denied_total`(ACL 拒绝)等安全相关计数器 |
+
+---
+
+## 14. 可观测性设计
+
+### 14.1 指标(Metrics)
+
+Gateway 内置 Prometheus 指标收集器(`GatewayMetrics`,Inferred from `internal/gateway/metrics.go`),同时提供 Prometheus 格式和 JSON 格式的指标端点。
+
+| 指标 | 类型 | 标签 | 说明 |
+|------|------|------|------|
+| `gateway_requests_total` | Counter | source, method, status | RPC 请求总量,按来源、方法、状态分组 |
+| `gateway_auth_failures_total` | Counter | source, reason | 认证失败总量 |
+| `gateway_acl_denied_total` | Counter | source, method | ACL 拒绝总量 |
+| `gateway_connections_active` | Gauge | channel | 当前活跃流连接数(按 WS/SSE 通道) |
+| `gateway_stream_dropped_total` | Counter | reason | 流连接剔除总量 |
+
+**指标端点:**
+
+| 端点 | 格式 | 说明 |
+|------|------|------|
+| `GET /metrics` | Prometheus text | Prometheus scrape 目标 |
+| `GET /metrics.json` | JSON | 供 UI 面板或自定义监控消费 |
+| `GET /healthz` | `{"status":"ok"}` | 存活探针 |
+
+### 14.2 日志
+
+| 层面 | 机制 | 说明 |
+|------|------|------|
+| Runtime | Go `log.Printf` | 关键生命周期事件(Checkpoint 创建/恢复失败、Compact 触发、Hook 执行)使用 `log.Printf` 输出到 stderr |
+| Gateway | Go `log.Printf` + `http.Handler` 错误包装 | 连接异常、认证失败、流中继错误 |
+| Runner | 可配置 `*log.Logger` | 默认输出到 stderr,前缀 `runner: ` |
+
+**日志安全约束:**
+- 不得在日志中输出 API Key 明文
+- 不得在日志中输出用户消息内容(隐私)
+- 工具调用参数中的敏感路径名(如 `.env`)在日志中以归一化相对路径替代绝对路径
+
+### 14.3 分布式追踪
+
+NeoCode 不使用外部分布式追踪系统(Jaeger/Zipkin),而是通过 **应用级标识符串联** 实现端到端可追踪性:
+
+```
+SessionID(会话级) + RunID(单次运行级)
+ │ │
+ └──────────────────────┘
+ │
+ 贯穿所有层:
+ Client → Gateway → Runtime → Provider → Tools → Session Store
+```
+
+**附加追踪信息:**
+- `TaskID` + `AgentID`:子代理调用链追踪
+- `RequestID`:单次 JSON-RPC 请求-响应匹配
+- `ToolCallID`:模型工具调用与执行结果的关联
+
+### 14.4 健康检查
+
+| 探针 | 端点 | 说明 |
+|------|------|------|
+| **HTTP Daemon 存活** | `GET /healthz` → 200 | Daemon 进程存活 + HTTP 服务正常 |
+| **Gateway 存活** | `GET /healthz` → 200 | Gateway 进程存活 + HTTP 服务正常 |
+| **Gateway 就绪** | `gateway.ping` JSON-RPC | 全链路可达(客户端 → Gateway → Runtime) |
+
+---
+
+## 15. 架构决策记录(ADR)
+
+以下记录 NeoCode 架构演进过程中的关键决策,遵循 ADR 标准格式(Context → Alternatives → Decision → Consequences)。
+
+### ADR-001:Gateway 作为唯一 RPC 边界
+
+**状态:** Accepted
+
+**背景:** 系统需要支持多种客户端(TUI、Web、Desktop、飞书 Bot、CI/CD 脚本)。若每个客户端独立接入 Runtime,认证、授权、流式中继将在 N 个客户端中重复实现。
+
+**替代方案:**
+
+| 方案 | 评估 |
+|------|------|
+| 各客户端直连 Runtime | 安全逻辑分散、新客户端接入成本高、Runtime 需理解传输协议 |
+| 按客户端类型分别建 Gateway | 仍有重复逻辑,且客户端类型增加时需要新增 Gateway |
+| **单一 Gateway 统一 RPC** | 安全收敛、客户端对等化、流式中继集中管理 |
+
+**决策:** 所有客户端必须通过 Gateway 的 JSON-RPC 接口与 Runtime 通信。Gateway 是系统唯一的跨边界通道。
+
+**后果:**
+- 变得更容易:新增客户端类型只需实现 JSON-RPC 客户端;安全审计只需检查 Gateway 一个入口
+- 变得更困难:Gateway 成为单点故障(通过本地自动拉起 + 健康检查 + 快速重启缓解)
+- 需要关注:Gateway 不得包含任何客户端特化逻辑——这是架构铁律,违反将侵蚀客户端对等性
+
+### ADR-002:Provider 插件化(2 方法接口)
+
+**状态:** Accepted
+
+**背景:** AI 模型市场快速变化,新模型不断涌现。系统必须支持随时切换到新模型而不修改上层代码。
+
+**替代方案:**
+
+| 方案 | 评估 |
+|------|------|
+| 统一内部模型协议,Gateway 做转换 | Gateway 职责膨胀,每种新模型的流式格式差异需在 Gateway 处理 |
+| 每个客户端自行集成模型 SDK | 模型切换需更新所有客户端,密钥分散管理 |
+| **Provider interface(2 方法 + channel)** | 上层零改动接入新模型,厂商差异收敛在 Provider 包内 |
+
+**决策:** `Provider` interface 仅定义 `EstimateInputTokens` + `Generate(ctx, req, events chan)`。所有厂商差异收敛在各自的 Provider 实现中。
+
+**后果:**
+- 变得更容易:新增模型只需写 adapter;测试只需注入 Mock Provider
+- 变得更困难:Provider interface 极度简洁,但某些厂商的高级特性(如 thinking、caching)需要统一抽象层来表达
+- 需要关注:接口不可膨胀——每次新增方法需严格审查是否值得破坏所有已有 Provider 实现
+
+### ADR-003:事件驱动的异步工具执行
+
+**状态:** Accepted
+
+**背景:** AI 推理是流式的(token 逐个产出),可能持续数十秒到数分钟。纯同步调用在推理完成前客户端完全黑屏,且无法支持中途取消或实时权限审批。
+
+**替代方案:**
+
+| 方案 | 评估 |
+|------|------|
+| 同步回调(Run 阻塞等待完成) | 用户体验差,无法中途干预 |
+| 客户端轮询(定时查询执行状态) | 延迟高、带宽浪费、权限审批需实时交互 |
+| **进程内事件驱动(Go channel)** | 流式实时、Human-in-the-loop、支持并行工具执行 |
+
+**决策:** 推理结果、工具调用、权限请求、Token 用量全部通过 `RuntimeEvent` channel 异步发出,由 Gateway StreamRelay 中继到客户端。
+
+**后果:**
+- 变得更容易:Human-in-the-loop(`permission_request` 暂停等待用户决策);流式文本透出(用户可见 AI "打字"过程);全链路追踪(SessionID + RunID 贯穿所有事件)
+- 变得更困难:客户端需要支持 SSE/WebSocket 长连接;事件顺序一致性需在 Runtime 层保证
+- 需要关注:channel buffer 满时的背压策略(当前为丢弃 + drop 计数)
+
+### ADR-004:强边界单体架构
+
+**状态:** Accepted
+
+**背景:** NeoCode 运行在开发者本地机器上(单机单用户),同时由 5 人团队并行开发,需要模块独立演进但不需独立部署。
+
+**替代方案:**
+
+| 方案 | 评估 |
+|------|------|
+| 微服务(每模块独立进程) | 单机场景下序列化开销、网络延迟、运维复杂度都是净成本 |
+| 纯单体(模块间直接调用,无接口边界) | 无法支持 5 人并行开发和 Provider 零侵入可扩展性 |
+| **强边界单体(interface 解耦)** | 编译时类型安全 + 零网络延迟 + 单一二进制部署 |
+
+**决策:** 核心模块在同一进程中通过 Go interface 解耦,享受单体部署的简单性同时保持模块边界的严格性。仅当模块确实需要跨越物理机边界时(Runner),才拆分为独立进程。
+
+**后果:**
+- 变得更容易:单一二进制分发(`CGO_ENABLED=0` 静态编译);无外部服务依赖;调试简单(单进程内追踪)
+- 变得更困难:模块间耦合只能通过接口契约约束(无法通过网络隔离强制执行);单进程内存压力(需关注 Compact 和内存泄漏)
+- 需要关注:若未来出现多用户共享同一 NeoCode 实例的场景,可能需要重新审视此决策
+
+### ADR-005:SQLite 作为唯一持久化存储
+
+**状态:** Accepted
+
+**背景:** 会话数据(消息历史、Token 统计、Checkpoint 快照)需要可靠持久化,但单机场景不需要外部数据库。
+
+**替代方案:**
+
+| 方案 | 评估 |
+|------|------|
+| PostgreSQL / MySQL | 需要用户安装和运行数据库服务 → 违反零依赖部署 |
+| 纯文件存储(JSON/YAML) | 并发写不安全、无法原子事务(Compact 替换时危险)、查询需全量加载 |
+| **SQLite(modernc 纯 Go)** | ACID 事务、零外部依赖、单文件存储、开箱即用 |
+
+**决策:** 所有持久化(会话、Checkpoint、权限记忆)使用 SQLite,通过 modernc 纯 Go 实现消除 CGO 依赖。
+
+**后果:**
+- 变得更容易:单文件备份(复制 `session.db`);原子事务(Compact 替换消息列表、Checkpoint 创建)
+- 变得更困难:写并发受限(SQLite 单 writer),同会话并发写需显式加 `sessionLock`
+- 需要关注:数据库文件大小增长(8192 条消息/会话 × 多会话),通过 30 天过期清理 + Checkpoint 自动修剪控制
+
+### ADR-006:JSON-RPC 2.0 作为 RPC 协议
+
+**状态:** Accepted
+
+**背景:** Gateway 需要一种通用协议,使得任何客户端(从 Go TUI 到 Python 脚本到飞书服务端)都能平等接入。
+
+**替代方案:**
+
+| 方案 | 评估 |
+|------|------|
+| gRPC | 需要 protobuf 编译步骤 → 第三方接入门槛高;调试需专用工具 |
+| REST | 资源建模适合 CRUD,NeoCode 的操作是动词型的(`gateway.run`、`gateway.cancel`),硬映射不自然 |
+| **JSON-RPC 2.0** | 极简协议、人类可读、任何能发 HTTP POST 的环境都能接入 |
+
+**决策:** 客户端-Gateway 间使用 JSON-RPC 2.0 作为请求/响应协议。流式事件通过 SSE 或 WebSocket 推送。
+
+**后果:**
+- 变得更容易:第三方接入成本最低(发 JSON 即可);调试简单(可抓包查看明文);与 SSE/WS 配合自然
+- 变得更困难:无强类型 schema(对比 protobuf);错误格式需自行规范化(`FrameError` + `GatewayRPCError`)
+- 需要关注:JSON-RPC 的 batch 和 notification 语义当前不使用,避免引入复杂度
+
+### ADR-007:Runner 反向连接模型
+
+**状态:** Accepted
+
+**背景:** "手机飞书发指令 → 工位电脑执行代码"的场景要求 Runner 能穿过 NAT/防火墙接收指令。
+
+**替代方案:**
+
+| 方案 | 评估 |
+|------|------|
+| Gateway 主动连接 Runner | Runner 需开放入站端口 → 企业网络通常不允许 |
+| VPN/隧道统一网络 | 增加运维成本,不适合"即装即用"体验 |
+| **Runner 主动连接 Gateway(反向连接)** | Runner 位于 NAT 后也可用,无需开放入站端口 |
+
+**决策:** Runner 启动后通过 WebSocket 主动连接 Gateway 并注册自身。Gateway 将工具执行请求通过该 WebSocket 连接下发给 Runner。
+
+**后果:**
+- 变得更容易:Runner 可在任何网络环境下运行(仅需出站 HTTPS);即装即用,零网络配置
+- 变得更困难:Gateway 需管理 Runner 注册/心跳/断连重连;重连期间的工具请求需排队
+- 需要关注:WebSocket 连接安全(通过 Capability Token 签名校验工具权限和路径白名单)
+
+### ADR-008:Checkpoint 本地代码版本快照
+
+**状态:** Accepted
+
+**背景:** AI Agent 的写操作(文件编辑、删除)可能出错。需要一个轻量级的回滚安全网,且不能依赖用户已初始化 Git。
+
+**替代方案:**
+
+| 方案 | 评估 |
+|------|------|
+| 仅依赖 Git(`git stash` / `git checkout`) | 非 Git 仓库无法使用;AI 修改粒度远细于 commit |
+| 全量文件备份 | 大仓库空间开销不可接受;恢复粒度粗 |
+| **Checkpoint 快照(SQLite 记录 + 文件存储)** | 细粒度、自动触发、与 Git 并存、轻量 |
+
+**决策:** 在每次写操作前(`pre_write`)、每轮结束(`end_of_turn`)、上下文压缩前(`compact`)自动创建 Checkpoint 快照。有 `.git` 时优先用 Git 版本追踪,无 `.git` 时 Checkpoint 提供独立安全网。
+
+**后果:**
+- 变得更容易:用户无需任何操作即有安全网;支持选择性恢复;自动修剪避免空间膨胀
+- 变得更困难:需管理 Checkpoint 生命周期(creating → available → restored/pruned);大文件(二进制、vendor)的快照效率需持续优化
+- 需要关注:快照频率与磁盘空间的平衡(通过 `maxAutoKeep` 和过期修剪控制)
+
+---
+
+## 16. 架构风险
+
+以下逐项记录当前架构中的已知风险及每项的缓解计划。已知局限和技术债清单见 `docs/tech-debt.md`。
+
+### 16.1 风险清单
+
+| 风险 | 严重度 | 描述 | 缓解措施 |
+|------|--------|------|----------|
+| **Gateway 单点故障** | 中 | 所有客户端依赖 Gateway 作为唯一入口;Gateway 进程异常时整个系统不可用 | 客户端内置自动拉起(auto-spawn);本地 loopback 部署下 Gateway 与 CLI 同生命周期;网络模式下建议部署多个 Gateway 实例(当前未实现) |
+| **模型行为不可预测** | 高 | 底层模型升级或切换时,Agent 的行为可能发生微妙变化(推理深度、工具选择偏好、错误处理风格),且这种变化难以通过自动化测试捕获 | Provider 层契约极简(2 方法),限制厂商差异扩散;100% 覆盖率的框架层测试确保框架逻辑不受影响;实际模型行为通过验收测试(`runtime/acceptance/`)做抽样验证 |
+| **SQLite 写并发瓶颈** | 低 | 同会话的所有写操作(追加消息、更新状态、Compact 替换)串行执行;当需要跨多个会话做批量分析时单 writer 限制成为瓶颈 | 同会话并发写已通过 `sessionLock` 串行化,不同会话可并行;当前用户场景(单用户、顺序交互)下不构成实际瓶颈;若未来需要批量跨会话操作,可通过读写分离(读可并发)缓解 |
+| **上下文窗口天花板** | 中 | 即使有 Compact,模型原生的 context window 有硬限制(如 Claude 200K、GPT-4 128K);对于超长会话,最终仍会达到无法继续的临界点 | Compact 两级策略(Micro + Full)最大化利用现有窗口;`max_turns` 限制防止无限循环;长期来看需借助模型厂商的 context window 增长 |
+| **TOCTOU 路径竞态** | 低 | 文件系统操作在 Security Engine 校验通过后、实际读写前,目标路径的状态可能被外部进程改变(symlink 替换攻击) | 当前在校验时 resolve symlink,但存在微小的时间窗口;现代 OS 的 `O_NOFOLLOW` 等标志可进一步缓解;实际攻击面极小(本地单用户场景) |
+
+## 17. 附录
+
+> 本附录用于统一术语和索引相关文档,不属于架构主体内容。
+
+### 17.1 术语表
+
+| 术语 | 定义 |
+|------|------|
+| **ReAct Loop** | Reasoning + Acting 循环:模型推理 → 解析工具调用 → 执行工具 → 回灌结果 → 继续推理,直到产出最终文本回复 |
+| **Compact** | 上下文压缩:当对话历史累积到接近 Token 预算上限时,自动将历史消息摘要化或裁剪,以释放上下文空间 |
+| **MicroCompact** | 轻量级压缩:仅对单个 tool_result 内容做摘要化,不改变消息列表结构。是 Compact 的第一阶段 |
+| **StreamRelay** | 流式中继:Gateway 内部将 Runtime 的异步事件按 SessionID/RunID 广播到所有订阅客户端连接的 pub/sub 机制 |
+| **Checkpoint** | 代码版本快照:AI 执行写操作前自动创建的文件状态快照,支持恢复和 Diff 查看 |
+| **Human-in-the-loop** | 人机协作模式:AI 在执行可能危险的操作(如写文件、执行 Bash)前暂停,等待人类审批 |
+| **Capability Token** | 能力令牌:Runner 执行工具时携带的 HMAC 签名令牌,限定允许的工具列表、路径范围和有效期 |
+| **Skill** | 技能:通过 SKILL.md 文件定义的专用行为 Prompt,在会话中按需激活并注入 System Prompt |
+| **MCP** | Model Context Protocol:通过本地 stdio 子进程动态挂载外部工具的开放协议 |
+| **Provider** | 模型厂商适配器:实现统一 Generate 接口、封装厂商特定协议和流式格式的插件化组件 |
+| **Gateway** | 协议路由层:系统唯一的 RPC 入口,负责客户端认证、请求路由和事件流中继 |
+| **Runner** | 远程工具执行代理:独立进程,通过 WebSocket 主动连接 Gateway,在本地执行 Gateway 下发的工具请求 |
+| **ADR** | Architecture Decision Record:架构决策记录,记录背景、替代方案、决策和后果 |
+
+### 17.2 相关文档索引
+
+| 文档 | 路径 | 说明 |
+|------|------|------|
+| Gateway RPC API 参考 | `docs/reference/gateway-rpc-api.md` | 完整的 JSON-RPC method、params、error code 定义 |
+| Gateway 错误编目 | `docs/reference/gateway-error-catalog.md` | 所有 Gateway 错误码的语义和 HTTP 映射 |
+| Gateway 兼容性 | `docs/reference/gateway-compatibility.md` | 跨版本兼容性保证 |
+| TUI-Gateway 契约矩阵 | `docs/reference/tui-gateway-contract-matrix.md` | TUI 与 Gateway 间的协议契约 |
+| Provider 接入指南 | `docs/guides/adding-providers.md` | 如何新增模型厂商 |
+| Gateway 集成指南 | `docs/guides/gateway-integration-guide.md` | 第三方客户端接入指南 |
+| MCP 配置指南 | `docs/guides/mcp-configuration.md` | MCP Server 配置详解 |
+| 飞书适配器指南 | `docs/guides/feishu-adapter.md` | 飞书 Bot 接入配置 |
+| Context Compact 详解 | `docs/context-compact.md` | Compact 策略和预算管理的实现细节 |
+| Runtime 事件流 | `docs/runtime-provider-event-flow.md` | Runtime 与 Provider 间的事件协议 |
+| Stop Reason 决策 | `docs/stop-reason-and-decision-priority.md` | 停止原因和决策优先级 |
+| Skills 系统设计 | `docs/skills-system-design.md` | Skills 系统的详细设计 |
+| Gateway 详细设计 | `docs/gateway-detailed-design.md` | Gateway 内部实现细节 |
+| 开发规范 | `AGENTS.md` | 项目 AI 协作规则、模块边界、编码规范 |
+
diff --git a/docs/architecture/architecture-v2.md b/docs/architecture/architecture-v2.md
new file mode 100644
index 00000000..441ad254
--- /dev/null
+++ b/docs/architecture/architecture-v2.md
@@ -0,0 +1,432 @@
+# NeoCode 系统架构
+
+**v2.0** | 2026-05-09 | 目标读者:团队成员、项目贡献者
+
+本文档描述 NeoCode 的架构边界、核心组件、关键路径和安全约束。API 字段、部署步骤、详细设计和实现细节见 [相关文档索引](#13-相关文档索引)。
+
+// 开头应该有完整的Purpose,提供给阅读者作为引入。
+
+---
+
+## 1. 架构驱动力
+
+六条硬约束决定了全部架构决策。
+
+| # | 驱动力 | 强制的选择 |
+|---|--------|-----------|
+| D1 | **本地优先** — 代码和会话数据不出用户机器 | 零依赖单二进制;SQLite 嵌入式持久化;离线可用 |
+| D2 | **多端对等接入** — TUI/Web/Desktop/IM/CI 都是对等客户端 | Gateway 唯一 RPC 边界;JSON-RPC 协议;适配器模式 |
+| D3 | **多模型可替换** — 厂商差异不向上泄漏 | Provider 插件化(2 方法接口);上层零改动接入新模型 |
+| D4 | **工具执行可控** — 文件/Bash/网络操作需审计和审批 | Security Engine 关键路径;WorkspaceSandbox;Checkpoint 回滚 |
+| D5 | **Human-in-the-Loop** — 危险操作需人类确认 | 事件驱动暂停-恢复循环;PolicyEngine ask/allow/deny |
+| D6 | **单机零运维** — 用户不是 DBA 或 SRE | 核心模块同进程;SQLite;自动过期清理 |
+
+// 过分结构化,生硬的凝练导致信息失真。对于设计原则,应该有基本的文字描述。
+
+// 示例(参考其它开源项目的架构文档):
+
+// - Maximize parallelism
+
+// Most of the time should be spent doing fully parallelizable work. This can be observed by taking a CPU trace using the --trace=[file] flag and viewing it using go tool trace [file].
+
+// - Avoid doing unnecessary work
+
+// For example, many bundlers have intermediate stages where they write out JavaScript code and read it back in using another tool. This work is unnecessary because if the tools used the same data structures, no conversion would be needed.
+
+---
+
+## 2. 系统边界
+
+### 2.1 In Scope
+
+| 职责域 |
+|--------|
+| 多模型 Provider 归一化(流式推理 + Token 估算) |
+| ReAct 推理循环(上下文构建 → 推理 → 工具调用 → 结果回灌) |
+| 工具执行(文件/Bash/Git 语义/Codebase/WebFetch/MCP/Todo/Memo/子代理/诊断) |
+| 多端接入(TUI/Web/Desktop/飞书/CI 通过 Gateway JSON-RPC/SSE/WS) |
+| 会话管理(SQLite 持久化、Token 追踪、Compact 压缩) |
+| Skills/MCP 扩展;Memo 跨会话记忆;Checkpoint 本地快照;自我更新 |
+
+### 2.2 Out of Scope
+
+| 不在范围内 | 边界说明 |
+|-----------|----------|
+| 中心化云端 SaaS / 多租户 | 数据全在本地,权限继承系统进程 |
+| 单一模型厂商绑定 | Provider 接口开放,可切换任意模型或本地部署 |
+| 全自动黑盒程序员 | 危险操作必须经 Human-in-the-Loop 审批 |
+| 重型 IDE 插件 / fork | 不 Fork 编辑器;可嵌入瘦客户端复用 Gateway |
+| 强依赖公网的 Web 客户端 | 离线局域网下直连本机 Gateway |
+| 远程代码托管 | 有本地 Checkpoint,不替代 GitHub/GitLab |
+| 自研大模型 | Agent 框架,不训练模型 |
+| 组织级 RBAC | 鉴权限于 Gateway 连接级 Token |
+
+// #2.1,#2.2的问题同 #1。纯表格+关键句无法阐述清楚事物属性。
+
+### 2.3 外部系统
+
+```
+客户端(TUI / Web / Desktop / 飞书 Bot / CI)──RPC──▶ Gateway ──▶ Runtime ──▶ Provider ──▶ 模型 API (HTTPS)
+ │ │
+ │ ├──▶ Tools ──▶ Shell / FS / Git / MCP / Web
+ │ │
+ │ └──▶ Session ──▶ SQLite
+ │
+ └──▶ Runner (WS 反向连接)
+```
+
+// 为什么要在这里讲系统边界?作为对架构不熟悉的潜在贡献者,我会对文档说的这些感到迷茫。
+
+---
+
+## 3. 架构总览
+
+### 3.1 容器图
+
+```mermaid
+graph TD
+ %% --- 客户端 ---
+ subgraph Client["客户端 (独立进程或嵌入)"]
+ direction LR
+ TUI["TUI
Bubble Tea CLI"] ~~~ WEB["Web
React SPA"] ~~~ DT["Desktop
Electron"] ~~~ FS["飞书 Bot
via Adapter"]
+ end
+
+ %% --- 核心 ---
+ GW["Gateway
══════════════
JSON-RPC · SSE · WS
Stream Relay
Token Auth"]
+ RT["Runtime
══════════════
ReAct 循环编排
权限审批 · Compact 调度
事件派发 · Hook 管理"]
+
+ %% --- 能力层 ---
+ subgraph Capability["能力层 (同一进程内的模块边界)"]
+ direction LR
+ PR["Provider
多模型适配"]
+ TL["Tools
工具执行 + 安全引擎"]
+ CTX["Context
Prompt 构建 + 压缩"]
+ SESS["Session
SQLite 持久化"]
+ end
+
+ %% --- 支撑 ---
+ subgraph Support["支撑 (同一进程)"]
+ direction LR
+ SK["Skills
SKILL.md 加载"]
+ CFG["Config
配置管理"]
+ end
+
+ %% --- 外部 ---
+ subgraph External["外部系统"]
+ direction LR
+ RN["Local Runner
独立进程 · 远程/本机"]
+ LLM["模型厂商 API
Anthropic · OpenAI · Gemini · ..."]
+ end
+
+ DB[("SQLite
~/.neocode/")]
+
+ %% --- 连线 ---
+ Client -->|"JSON-RPC"| GW
+ GW -->|"同步调用"| RT
+ RT --> Capability
+ RT --> Support
+ RT --> DB
+ GW -.->|"SSE / WS 事件流"| Client
+ GW -.->|"WebSocket
tool_exec + heartbeat"| RN
+ RT -.->|"HTTPS 流式"| LLM
+
+ %% --- 样式 ---
+ style GW fill:#fb923c,stroke:#fb923c,color:#0f172a
+ style RT fill:#34d399,stroke:#34d399,color:#0f172a
+ style PR fill:#a78bfa,stroke:#a78bfa,color:#0f172a
+ style TL fill:#fbbf24,stroke:#fbbf24,color:#0f172a
+ style CTX fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style SESS fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style SK fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style CFG fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style DB fill:#94a3b8,stroke:#94a3b8,color:#0f172a
+ style RN fill:#fb7185,stroke:#fb7185,color:#0f172a
+ style LLM fill:#94a3b8,stroke:#94a3b8,color:#0f172a
+ style Client fill:#1e293b,stroke:#22d3ee,color:white
+ style Capability fill:#1e293b40,stroke:#334155,color:white
+ style Support fill:#1e293b40,stroke:#334155,color:white
+ style External fill:#1e293b40,stroke:#475569,color:white
+```
+
+// 基本的文字描述在哪里?
+
+// 参考:
+
+// Overview
+
+// [image]
+
+// The build pipeline has two main phases: scan and compile. These both reside in [bundler.go](https://github.com/evanw/esbuild/blob/main/internal/bundler/bundler.go).
+
+// Scan phase
+
+// This phase starts with a set of entry points and traverses the dependency graph to find all modules that need to be in the bundle. This is implemented in `bundler.ScanBundle()` as a parallel worklist algorithm. The worklist starts off being the list of entry points. Each file in the list is parsed into an AST on a separate goroutine and may add more files to the worklist if it has any dependencies (either ES6 `import` statements, ES6 `import()` expressions, or CommonJS `require()` expressions). Scanning continues until the worklist is empty.
+
+// Compile phase
+
+// This phase creates a bundle for each entry point, which involves first "linking" imports with exports, then converting the parsed ASTs back into JavaScript, then concatenating them together to form the final bundled file. This happens in `(*Bundle).Compile()`.
+
+### 3.2 核心架构选择
+
+| 设计张力 | 选择 | 代价 | 详见 |
+|----------|------|------|------|
+| 微服务 vs 单体 | **强边界单体**(同进程 interface 解耦) | 无法独立扩缩容 | ADR-004 |
+| 同步 vs 事件驱动 | **进程内事件驱动**(Go channel) | 客户端需支持 SSE/WS 长连接 | ADR-003 |
+| Go vs Python/TS/Rust | **Go 单二进制** | AI SDK 生态不如 Python 丰富 | ADR-004 |
+| SQLite vs 外部 DB | **SQLite(modernc)** | 单 writer,同会话写串行化 | ADR-005 |
+| JSON-RPC vs gRPC/REST | **JSON-RPC 2.0 + SSE/WS** | 无强类型 schema | ADR-006 |
+
+// 问题同 #1。我不能明白这些术语具体指的是什么,以及为什么这样选择架构。
+
+---
+
+## 4. 组件
+
+每个组件的核心问题:**存在理由、拥有的决策权、不能知道什么、禁止做什么。**
+
+| 组件 | 职责 | 决策权 | 不能知道 | 禁止 |
+|------|------|--------|----------|------|
+| **Gateway** | 唯一 RPC 入口:认证、路由、流中继 | 接受哪个连接、允许哪个 method、事件路由到哪个客户端 | 客户端实现细节、模型厂商字段、工具逻辑 | 不内嵌客户端特化逻辑;不直接执行工具或调 Provider |
+| **Runtime** | ReAct 循环编排:"指挥不执行" | 循环何时继续/终止、Compact 何时触发、权限审批暂停/恢复 | 厂商协议、工具实现、Prompt 组装细节、传输协议 | 不直接执行工具;不读厂商原始响应;不直连客户端 |
+| **Provider** | 厂商 API 归一化为 `Generate()` + `EstimateTokens()` | 如何映射厂商格式到统一 StreamEvent | 上层模块(单向依赖:仅被 Runtime 调用) | 厂商特定字段不向上穿透 |
+| **Tools** | 所有模型可调用的能力入口 + Security Engine 关键路径 | 暴露哪些 Schema、每次调用是否允许 | 推理循环状态、当前模型、客户端身份 | 不可跳过 Security Engine |
+| **Session** | 会话数据的唯一持有者 | 何时创建/追加/过期/裁剪 | 推理状态、Prompt 逻辑 | 同会话并发写必须串行化 |
+| **Context** | Prompt 组装 + Compact 压缩 | 组装顺序、压缩级别、哪些消息不可压缩 | 厂商协议、工具结果 | System Prompt 和 Pin 消息不可参与压缩 |
+| **Skills** | SKILL.md 加载 + 会话级激活 | 哪些 Skill 可用、哪个会话激活哪个 | — | project 层覆盖 global 层(同名去重) |
+| **Runner** | 远程工具执行代理(可跨物理机) | 是否接受执行请求(CapToken + Allowlist) | — | 不开放入站端口;反向连 Gateway |
+| **Config** | 配置加载、校验、热更新 + Provider 选择状态 | 当前生效配置;runtime 模型选择 | — | 密钥不入配置文件(仅存环境变量名) |
+
+// 过分结构化将语义拆散。阅读者没有办法从表格中得到完整的信息流。
+
+---
+
+## 5. 运行时流程
+
+### 5.1 Run Flow(ReAct 主循环)
+
+```mermaid
+sequenceDiagram
+ participant Client as 客户端
+ participant Gateway as Gateway
+ participant Runtime as Runtime
+ participant Context as Context
+ participant Provider as Provider
+ participant Tools as Tools
+ participant Security as Security Engine
+
+ Client->>Gateway: gateway.run (JSON-RPC)
+ Gateway->>Runtime: PrepareInput → Run
+ Runtime->>Context: Build(session)
+ Context-->>Runtime: [SystemPrompt + Messages]
+ Runtime->>Provider: Generate(req)
+ Provider-->>Runtime: [StreamEvent: text_delta, tool_call...]
+ Runtime-->>Gateway: emit(run_progress)
+ Gateway-->>Client: [SSE/WS 事件]
+ alt 模型产出 tool_calls
+ Runtime->>Tools: Execute(toolCalls) [并行≤4]
+ Tools->>Security: Check(action)
+ Security-->>Tools: allow/deny/ask
+ Tools-->>Runtime: [ToolResult]
+ Runtime->>Runtime: 回灌 tool_result
+ Runtime->>Provider: Generate(req)
+ else 最终文本
+ Runtime-->>Gateway: emit(run_done)
+ end
+```
+
+### 5.2 Permission Flow
+
+```mermaid
+sequenceDiagram
+ participant Runtime as Runtime
+ participant Tools as Tools
+ participant Security as Security Engine
+ participant Gateway as Gateway
+ participant Client as 客户端
+
+ Runtime->>Tools: Execute(toolCall)
+ Tools->>Security: Check(action)
+ alt allow
+ Security-->>Tools: allow → 执行
+ else deny
+ Security-->>Tools: deny → 返回 error
+ else ask
+ Security-->>Tools: ask
+ Tools-->>Runtime: PermissionDecisionError
+ Runtime->>Gateway: emit(permission_request)
+ Gateway-->>Client: [审批提示]
+ Client->>Gateway: resolve_permission (JSON-RPC)
+ Gateway->>Runtime: allow_once / allow_session / reject
+ opt allow_session
+ Tools->>Tools: RememberSessionDecision(Fingerprint)
+ end
+ end
+```
+
+### 5.3 Runner Flow
+
+```mermaid
+sequenceDiagram
+ participant Gateway as Gateway
+ participant Runner as Runner
+ participant Tools as Tools
+
+ Gateway->>Runner: WS: tool_exec_request {cap_token}
+ Runner->>Runner: capSigner.Verify(token)
+ Runner->>Tools: toolMgr.Execute()
+ Tools-->>Runner: [ToolResult]
+ Runner->>Gateway: WS: tool_exec_result
+ loop heartbeat
+ Gateway->>Runner: ping
+ Runner->>Gateway: pong
+ end
+```
+
+// 我们能清楚调用信息,但是调用的理由和结果是什么?
+
+---
+
+## 6. 状态与数据归属
+
+| 数据 | 归属组件 | 存储 | 生命周期 |
+|------|----------|------|----------|
+| 消息历史、Token 计数 | Session | SQLite `messages` | 单会话 ≤8192 条;30 天过期 |
+| 会话头(模型/模式/Todo/Plan/Skills) | Session | SQLite `sessions` | 同会话 |
+| Checkpoint 快照 | Session | SQLite `checkpoint_records` | Run 内保留;自动修剪 |
+| 权限记忆 | Session | SQLite `session_permission` | 跟随会话 |
+| 配置 + Provider 选择 | Config | `~/.neocode/config.yaml` | 持久,手动修改 |
+| 运行时推理状态 | Runtime | 内存 | Run 生命周期 |
+| Prompt 模板 | Context | 嵌入二进制 + 文件系统 | 随版本 |
+
+// 作为潜在贡献者,我第一眼不明白这个表格是用来做什么的?“谁拥有什么状态、状态如何持久化、哪些状态是临时的”没有作为关键表头或简单说明表述出来。这些状态又是做什么的?
+
+**关键不变量的实现:**
+
+| 不变量 | 机制 |
+|--------|------|
+| 同会话并发写串行 | `sessionLock`(per-session mutex) |
+| Compact 原子替换 | SQLite 事务:`ReplaceTranscript()` |
+| Checkpoint 原子创建 | SQLite 事务:record → session_cp → status update |
+| 配置线程安全 | `Manager.mu`(RWMutex)+ copy-on-read |
+
+**Checkpoint 状态机:** `creating → available → restored / pruned`(`broken` 为异常分支)
+
+**权限状态机:** `SecurityCheck → allow / deny / ask → WaitUser → allow_once / allow_session / reject`
+
+---
+
+## 7. 安全边界
+
+四层纵深防御。关键控制点逐层收紧。
+
+// 到底是给领导说的还是给同学看的?
+
+```
+客户端 ──▶ [1] Gateway Auth (Token → subject_id)
+ │
+ ▼
+ [2] Gateway ACL (method × source 白名单)
+ │
+ ▼
+ [3] Security Engine (PolicyEngine + WorkspaceSandbox)
+ │
+ ▼
+ [4] OS 约束(进程权限 = 当前用户)
+```
+
+| 控制点 | 机制 | 核心行为 |
+|--------|------|----------|
+| **认证** | `gateway.authenticate` → Token → `subject_id` | 无 Authenticator 时授予 `local_admin`(本地 loopback 场景) |
+| **ACL** | method × source 白名单 | 未允许的 method 返回 `acl_denied` |
+| **策略引擎** | PolicyRule 按 Priority 匹配 | `allow` → 执行;`deny` → 拒绝;`ask` → 暂停等用户审批 |
+| **工作区沙箱** | 路径解析 + 边界校验 | 阻断 `../` 穿越;检测 Symlink 逃逸;越界生成 safe 候选 |
+| **敏感路径** | 关键词 + 文件名模式自动检测 | `.env`/`.ssh`/密钥文件/私钥文件 → 强制 `deny` |
+| **密钥保护** | `api_key_env` 仅存环境变量名 | 密钥不入配置文件、不入日志、不经 Gateway 传输 |
+| **回滚安全网** | Checkpoint 写前快照 | `pre_write`/`end_of_turn`/`compact` 自动触发 |
+| **Runner 隔离** | Capability Token(HMAC-SHA256) | 限定工具列表 + 路径范围 + 有效期 |
+
+---
+
+## 8. 部署视图
+
+| 产物 | 目标 OS/Arch | 包含能力 |
+|------|-------------|----------|
+| `neocode` | Linux/macOS/Windows amd64+arm64 | CLI、TUI、Gateway、Daemon、Runner、Web UI |
+| `neocode-gateway` | 同上 | 独立 Gateway(服务器常驻) |
+
+**部署拓扑:**
+
+- **单机:** TUI/Web/Desktop →(loopback RPC)→ Gateway(同进程或 Daemon) → Runtime → SQLite
+- **分布:** 远程客户端 → Gateway(云/服务器)→ WebSocket ← Runner(工位 NAT 后,主动连接)
+
+---
+
+## 9. 可观测性
+
+| 维度 | 机制 |
+|------|------|
+| **追踪** | `SessionID + RunID` 贯穿全链路(Client → Gateway → Runtime → Provider → Tools) |
+| **事件流** | 所有运行时事件(text_delta、tool_call、permission_request、usage)经 `RuntimeEvent` channel 发出 |
+| **指标** | 5 个 Prometheus 指标(requests、auth_failures、acl_denied、connections_active、stream_dropped)+ `/metrics` + `/metrics.json` |
+| **健康检查** | `/healthz` 存活探针;`gateway.ping` 全链路就绪探针 |
+
+---
+
+## 10. 架构决策
+
+| ADR | 决策 | 代价 |
+|-----|------|------|
+| 001 | Gateway 唯一 RPC 边界 | Gateway 单点——通过本地 auto-spawn 缓解 |
+| 002 | Provider 2 方法接口 | 无法深度利用厂商高级特性 |
+| 003 | 事件驱动异步执行 | 客户端需支持 SSE/WS 长连接 |
+| 004 | 强边界单体 | 无法独立扩缩容单个模块 |
+| 005 | SQLite 持久化 | 单 writer 并发限制 |
+| 006 | JSON-RPC 2.0 + SSE/WS | 无强类型 schema,错误格式需自行规范化 |
+| 007 | Runner 反向连接 | 重连期间的工具请求需排队 |
+| 008 | Checkpoint 本地快照 | 大文件快照效率需持续优化 |
+
+// 这个不是说过了吗?如果信息密度相似,为什么还要保留?
+
+---
+
+## 11. 架构风险
+
+| 风险 | 缓解 |
+|------|------|
+| Gateway 单点故障 | 本地 auto-spawn;网络模式可部署多实例 |
+| 模型行为不可预测(切换模型时行为变化) | Provider 2 方法极简接口限制差异扩散;验收测试抽样验证 |
+| 上下文窗口天花板 | Compact 两级压缩 + `max_turns` 上限 |
+| SQLite 单 writer 瓶颈 | 同会话串行化(当前用户场景不构成瓶颈);不同会话并行 |
+| TOCTOU 路径竞态(Sandbox 检查与实际 I/O 之间的窗口) | `O_NOFOLLOW` 缓解;本地单用户场景攻击面极小 |
+
+---
+
+## 12. 可扩展性
+
+| 扩展点 | 如何扩展 | 代价 |
+|--------|----------|------|
+| 新增模型厂商 | 实现 `Provider`(2 方法) | 新增 Go 包 + 配置 |
+| 新增工具 | 实现 `Executor` → 注册 | 新增 Go 包;或 MCP stdio(零代码) |
+| 新增客户端类型 | 实现适配器:HTTP POST JSON-RPC + SSE/WS 消费 | 独立进程,Gateway 无改动 |
+| 新增 Skill | 放置 `SKILL.md` 文件 | 零代码;会话级激活 |
+| 新增传输协议 | 实现 `transport.Listener` | 新增适配代码 |
+
+**刻意不扩展的边界:** Gateway 是唯一 RPC 入口;工具必须经 Security Engine;Provider 差异不出 Provider 层;密钥不入配置文件。
+
+---
+
+## 13. 相关文档索引
+
+| 文档 | 路径 | 内容 |
+|------|------|------|
+| v1 完整架构文档 | [architecture-v1.md](architecture-v1.md) | 详细流程、实现细节、完整模块描述 |
+| 产品定位 | [../product/positioning.md](../product/positioning.md) | 产品定位、竞品分析、用户画像 |
+| Gateway RPC API | [../reference/gateway-rpc-api.md](../reference/gateway-rpc-api.md) | JSON-RPC method、params、error code 完整定义 |
+| Gateway 错误编目 | [../reference/gateway-error-catalog.md](../reference/gateway-error-catalog.md) | 错误码语义和 HTTP 映射 |
+| Provider 接入指南 | [../guides/adding-providers.md](../guides/adding-providers.md) | 如何新增模型厂商 |
+| 运维指南 | [../guides/operations.md](../guides/operations.md) | 安装分发、告警、诊断工具 |
+| Compact 策略 | [../context-compact.md](../context-compact.md) | Compact 策略和预算管理实现细节 |
+| Runtime 事件协议 | [../runtime-provider-event-flow.md](../runtime-provider-event-flow.md) | Runtime-Provider 事件流协议 |
+| 技术债清单 | [../tech-debt.md](../tech-debt.md) | 已知局限与技术债 |
+| 未来演进 | [../roadmap.md](../roadmap.md) | 路线图 |
+| 开发规范 | [../../AGENTS.md](../../AGENTS.md) | 项目 AI 协作规则、模块边界、编码规范 |
diff --git a/docs/architecture/architecture-v3.md b/docs/architecture/architecture-v3.md
new file mode 100644
index 00000000..e6fc07a2
--- /dev/null
+++ b/docs/architecture/architecture-v3.md
@@ -0,0 +1,588 @@
+# NeoCode 系统架构
+
+**v3.0** | 2026-05-10 | 目标读者:团队成员、项目贡献者
+
+---
+
+## 1. 概述
+
+NeoCode 是一个本地优先的 AI Coding Agent。它在开发者本地运行,通过终端、Web、桌面和 IM 等多端接入,执行代码理解、修改和验证的完整闭环。
+
+**它做什么:** 你告诉它"帮我在 auth.go 里加登录限流"——它读取文件、理解代码、写出修改、跑编译验证,每一步都经过你的审批。
+
+**它怎么跑:** 一个 `neocode` 二进制文件,不需要数据库、不需要 Docker、不需要联网(连本地模型也可以)。
+
+```mermaid
+graph TD
+ subgraph Client["客户端"]
+ direction LR
+ TUI["TUI"] ~~~ Web["Web"] ~~~ DT["Desktop"] ~~~ FS["飞书"]
+ end
+
+ GW["Gateway
RPC 路由 · 流中继 · 认证"]
+ RT["Runtime
ReAct 循环编排"]
+ PR["Provider
模型适配"]
+ TL["Tools
工具执行 + 安全"]
+ CTX["Context
Prompt 构建"]
+ SESS["Session
SQLite"]
+ RN["Runner
远程执行"]
+
+ DB[("SQLite")]
+
+ Client -->|"JSON-RPC"| GW
+ GW --> RT
+ RT --> PR & TL & CTX & SESS
+ GW -.->|"SSE/WS 事件"| Client
+ GW -.->|"WS 反向连接"| RN
+ RT -.->|"HTTPS"| LLM["模型 API"]
+
+ style GW fill:#fb923c,stroke:#fb923c,color:#0f172a
+ style RT fill:#34d399,stroke:#34d399,color:#0f172a
+ style PR fill:#a78bfa,stroke:#a78bfa,color:#0f172a
+ style TL fill:#fbbf24,stroke:#fbbf24,color:#0f172a
+ style CTX fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style SESS fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style RN fill:#fb7185,stroke:#fb7185,color:#0f172a
+```
+
+**六条设计选择:**
+
+| 选择 | 一句话原因 |
+|------|-----------|
+| **强边界单体**(同进程,interface 解耦) | 单机单用户场景下微服务是净成本 |
+| **进程内事件驱动**(Go channel) | AI 推理是流式的,需要中途可暂停等审批 |
+| **Provider 插件化**(2 方法接口) | 新增模型不改 Runtime 或 Gateway 一行代码 |
+| **SQLite 持久化**(modernc 纯 Go) | 零外部依赖,ACID 事务满足会话和 Checkpoint |
+| **JSON-RPC 2.0** + SSE/WebSocket | 任何能发 HTTP POST 的环境都能接入 |
+| **Runner 反向连接**(Runner 主动连 Gateway) | 工位电脑在 NAT/防火墙后,无需开放入站端口 |
+
+### 1.1 核心挑战
+
+将 LLM 变成一个可靠的编码代理,需要解决以下根本性问题:
+
+| 挑战 | 问题本质 | 系统应对 |
+|------|----------|----------|
+| **LLM 输出不稳定** | 同样的 Prompt,不同模型(甚至同一模型的不同请求)可能产出完全不同的工具调用策略和代码质量 | Provider 归一化 + Compact 保持上下文一致性 |
+| **工具执行具有副作用** | 模型决定执行 `rm -rf` 或修改关键配置文件,后果不可撤销 | Security Engine 四层防御 + Checkpoint 自动快照 |
+| **上下文窗口有限** | 模型的 context window 有硬上限(4K–200K tokens),长对话和大代码库必然超限 | Context 模块两级 Compact 策略(MicroCompact / Full Compact) |
+| **多轮任务需要状态管理** | 一次任务可能跨越数十轮推理,中间包含工具调用、审批暂停、错误重试,状态必须一致 | Session 持久化 + Runtime 集中管理会话状态 |
+| **多端接入的一致性** | TUI、Web、Desktop、飞书、CI 脚本需要用统一协议接入,且行为一致 | Gateway 作为唯一 RPC 边界 + JSON-RPC 2.0 标准协议 |
+
+---
+
+## 2. 一次完整的请求
+
+跟随一次典型的用户请求,边走边讲各组件如何协作。场景:用户输入 *"帮我在 auth.go 的 Login 函数加登录失败次数限制"*。
+
+### 2.1 请求进入
+
+用户输入通过客户端(TUI/Web/Desktop/飞书)发送到 Gateway。
+
+**Gateway 为什么存在。** 系统需要支持五种客户端类型。如果每个客户端直连 Runtime,认证逻辑要写五遍,流式事件推送要写五遍,安全漏洞要修五处。Gateway 将五条路径收敛为一条——所有客户端只需发 JSON-RPC 请求。
+
+Gateway 做三件事:**认证**(谁在请求)、**路由**(请求应该交给哪个 Runtime 操作)、**流中继**(把 Runtime 的异步事件推回给客户端)。它对客户端一视同仁——TUI 和飞书 Bot 在 Gateway 看来是完全相同的 JSON-RPC 调用方。
+
+```mermaid
+sequenceDiagram
+ participant Client as 客户端
+ participant Gateway as Gateway
+ participant Runtime as Runtime
+
+ Client->>Gateway: gateway.authenticate
+ Gateway-->>Client: subject_id = "local_admin"
+ Client->>Gateway: gateway.run {text: "帮我在 auth.go 加..."}
+ Gateway->>Runtime: Run(sessionID, userInput)
+```
+
+Gateway 对外暴露三个端点:JSON-RPC(请求/响应)、SSE(服务端推送事件流)、WebSocket(双向消息,供 Runner 使用)。客户端通过 JSON-RPC 发送指令,通过 SSE 或 WebSocket 接收流式事件。
+
+### 2.2 推理循环
+
+Runtime 收到请求后,进入 ReAct 循环——推理(Reasoning)和行动(Acting)交替进行。
+
+以下 flowchart 展示了 ReAct 循环的完整判断逻辑和退出条件。注意:模型的 `end_turn` **不等于真正结束**——它只是一个 candidate final,必须通过 Completion Gate 和 Verifier Gate 的验收才能被系统接受:
+
+```mermaid
+flowchart TD
+ A["用户输入"] --> B["Context 构建上下文"]
+ B --> C["Provider 推理(流式)"]
+ C --> D{"模型输出类型?"}
+ D -->|"tool_call"| E["Security Engine 安全检查"]
+ E --> F{"安检结果?"}
+ F -->|"allow"| G["Tools 执行工具"]
+ F -->|"deny"| H["生成拒绝结果"]
+ F -->|"ask"| I["暂停,等待用户审批"]
+ I -->|"批准"| G
+ I -->|"拒绝"| H
+ G --> J["结果回灌到消息历史"]
+ H --> J
+ J --> B
+
+ D -->|"end_turn(candidate final)"| CG["Completion Gate\nTodo 是否收敛?"]
+ CG --> VG["Verifier Gate\n按 VerificationProfile 运行 verifier"]
+ VG --> AS{"AcceptanceService\n汇总裁决"}
+ AS -->|"accepted"| K["输出结果,循环结束"]
+ AS -->|"continue(soft_block / todo 未收敛)"| HINT["注入 continue hint\n告知模型哪些验收未通过"]
+ HINT --> B
+ AS -->|"failed(verifier fail)"| FAIL["终止循环 + 报告失败原因"]
+ AS -->|"incomplete(hard_block / 无进展超限)"| FAIL
+
+ D -->|"解析异常"| L["构造错误信息回灌"]
+ L --> B
+ C -->|"达到 max_turns"| M["强制终止循环"]
+ C -->|"用户取消 gateway.cancel"| M
+ C -->|"Token 预算耗尽"| M
+ M --> FAIL
+
+ style K fill:#34d399,stroke:#34d399,color:#0f172a
+ style FAIL fill:#fb7185,stroke:#fb7185,color:#0f172a
+ style CG fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style VG fill:#a78bfa,stroke:#a78bfa,color:#0f172a
+ style AS fill:#fbbf24,stroke:#fbbf24,color:#0f172a
+```
+
+**Verifier Engine 为什么存在。** 模型说"我做完了"不等于真的做完了。Verifier Engine 是系统对模型输出进行客观验收的机制——它不依赖模型自述,而是通过实际检查(文件是否存在、代码是否编译通过、测试是否通过、Todo 是否收敛)来判断任务是否真正完成。
+
+**验收流程三阶段:**
+
+1. **Completion Gate**:检查 Todo 收敛状态。如果还有 required todo 未完成,直接阻塞,不运行后续 verifier。
+2. **Verifier Gate**:按 Session 持有的 `VerificationProfile`(如 `edit_code` → `todo_convergence + git_diff + build + test + typecheck`)解析出 verifier 列表,通过 Orchestrator 顺序执行,首个非 pass 结果短路。
+3. **AcceptanceService**:汇总 Completion Gate、Verifier Gate 和 Decider 的信号,产出唯一的终态裁决。
+
+**四种裁决结果:**
+
+| 裁决 | 条件 | 系统行为 |
+|------|------|----------|
+| **accepted** | Completion + Verification 全部通过 | 循环正常结束,发出 `run_done` |
+| **continue** | 存在 `soft_block`(Todo 未收敛、verifier 未通过但可修复) | 注入 continue hint(包含 verifier 证据和缺失事实),强制模型继续工作 |
+| **incomplete** | `hard_block`(需要外部条件)或无进展超过 `max_no_progress` 阈值 | 终止循环,报告未完成原因 |
+| **failed** | verifier 返回 `fail`(如编译失败、测试失败) | 终止循环,报告验证失败原因和 `ErrorClass` |
+
+**循环退出条件(四类):**
+
+| 退出条件 | 触发方式 | 结果 |
+|----------|----------|------|
+| **验收通过** | Completion Gate + Verifier Gate 全部 pass | Runtime 发出 `run_done`(`accepted`) |
+| **验收终止** | verifier 返回 fail 或 hard_block / 无进展超限 | Runtime 发出 `run_done`(`failed` / `incomplete`) |
+| **强制终止** | 达到 `max_turns` 上限(配置项)或 Token 预算耗尽 | Runtime 发出 `run_done` + 终止原因 |
+| **用户取消** | 客户端发送 `gateway.cancel` | Runtime 收到取消信号,停止当前循环 |
+
+**第一步:构建上下文。** Runtime 把当前会话状态(消息历史、Todo 列表、激活的 Skills、已批准的 Plan)交给 Context 模块。Context 按固定顺序组装 System Prompt——核心行为准则、工具能力列表、项目规则、当前任务状态、Plan 上下文——然后返回给 Runtime。
+
+**Runtime 为什么不自己拼 Prompt。** Prompt 的组装逻辑是一个独立的关注点。上下文压缩(Compact)的策略——什么时候触发、用 MicroCompact 还是 Full Compact、哪些消息不能裁剪——需要在 Context 模块内独立演进。如果 Runtime 内嵌了 Prompt 拼接,修改压缩策略就需要改推理循环,两者耦合。
+
+**第二步:调用模型。** Runtime 把组装好的 Prompt 交给 Provider。Provider 是模型厂商的抽象层——它唯一的职责就是把不同厂商的 API 归一化为两个操作:估算 Token 数、发起流式推理。
+
+**Provider 为什么只有 2 个方法。** 接口越大,实现新 Provider 的成本越高,厂商差异泄漏到 Runtime 的风险越大。当前已接入 Anthropic、OpenAI、Gemini、DeepSeek、MiniMax、Mimo 六家厂商,以及通过 OpenAI 兼容协议接入的 Qwen、GLM 等。每接入一家,Runtime 和 Gateway 零改动。
+
+```mermaid
+sequenceDiagram
+ participant Runtime as Runtime
+ participant Context as Context
+ participant Provider as Provider
+
+ Runtime->>Context: Build(session)
+ Context-->>Runtime: [SystemPrompt + Messages]
+ Runtime->>Provider: Generate(prompt)
+ Provider-->>Runtime: [StreamEvent: text_delta, tool_call...]
+ Runtime-->>Gateway: emit(run_progress)
+ Gateway-->>Client: [SSE/WS 事件]
+```
+
+Provider 通过 Go channel 推送流式事件:`text_delta`(增量文本,用户看到 AI "打字")、`tool_call_start/args/end`(模型决定调用工具)、`usage`(Token 消耗统计)。Runtime 消费这些事件,转成统一的 `RuntimeEvent`,发给 Gateway 的事件中继器。
+
+### 2.3 工具执行与安全审批
+
+模型在推理过程中可能决定调用工具。比如读 `auth.go`、搜索代码库中的 `Login` 函数、编辑文件、执行 `go build`。
+
+**所有工具调用经过同一个入口。** Tools Manager 是系统中最敏感的模块——它是唯一被允许执行文件 I/O、Bash 命令、网络请求和 MCP 外部工具的组件。任何模型可调用的能力必须在此注册,Runtime 不直接执行工具。
+
+**每次调用先过安检。** Security Engine 位于工具执行的关键路径上,不可跳过。它做两阶段检查:
+
+1. **策略引擎**:按优先级匹配规则。规则可以按工具名、路径前缀、域名、敏感文件类型等条件命中。决策有三种:`allow`(直接放行)、`deny`(直接拒绝)、`ask`(暂停等用户审批)。
+
+2. **工作区沙箱**:校验目标路径是否在工作目录内。阻断 `../` 穿越和 Symlink 逃逸。检测到越界时,不直接拒绝——而是计算一个 safe 候选路径(工作目录内的等价路径),供上层决定。
+
+```mermaid
+sequenceDiagram
+ participant Runtime as Runtime
+ participant Tools as Tools
+ participant Security as Security Engine
+ participant Gateway as Gateway
+ participant Client as 客户端
+
+ Runtime->>Tools: Execute(toolCall)
+ Tools->>Security: Check(action)
+ alt allow / deny
+ Security-->>Tools: 直接执行或拒绝
+ else ask
+ Security-->>Tools: ask
+ Tools-->>Runtime: 暂停,等待审批
+ Runtime->>Gateway: emit(permission_request)
+ Gateway-->>Client: [审批提示]
+ Client->>Gateway: resolve_permission
+ Gateway->>Runtime: allow_once / allow_session / reject
+ end
+```
+
+**敏感路径自动检测。** Security Engine 内置了敏感文件特征库,不需要用户配置:`.env`、`*.secret`、`*.token`、`*.key`、`*.pem`、`id_rsa`、`id_ed25519` 等。命中敏感路径的操作**强制 `deny`**——即使 PolicyRule 中没有显式配置,即使用户选了 `allow_session`。
+
+**回滚安全网。** 每次写操作前(`pre_write`)、每轮结束时(`end_of_turn`)、上下文压缩前(`compact`),系统自动创建 Checkpoint。如果 AI 改坏了代码,可以恢复到上一个快照。Checkpoint 与 Git 并存——有 `.git` 时优先用 Git 追踪,无 `.git` 时 Checkpoint 提供独立的安全网。
+
+**异常处理路径。** ReAct 循环中可能发生三类异常,每类都有明确的处理策略:
+
+| 异常类型 | 场景 | 系统行为 |
+|----------|------|----------|
+| **工具执行失败** | `go build` 超时、文件写入权限不足、网络请求失败 | 将错误信息封装为 Tool Result 回灌给 LLM,模型根据错误决定下一步(重试、换方案、放弃) |
+| **LLM 输出解析失败** | 模型返回无法解析的 tool_call JSON、引用不存在的工具名、参数格式不合法 | 构造格式化错误消息回灌给 LLM,提示其修正输出格式;连续解析失败超过阈值时终止循环 |
+| **模型拒绝或异常** | Provider 返回 HTTP 4xx/5xx、模型因安全策略拒绝响应、网络超时 | Provider 将错误映射为统一的错误类型,Runtime 根据错误类型决定是否重试(可重试错误自动重试,不可重试错误终止循环并通知用户) |
+
+关键原则:**错误不吞没,错误即数据。** 工具执行失败和 LLM 输出异常不会直接终止循环——它们被当作信息回灌给模型,让模型有机会自我修正。只有在异常持续累积(超过重试阈值)或不可恢复时,才强制终止。
+
+### 2.4 结果回传
+
+Runtime 在执行过程中持续发出事件。Gateway 的 StreamRelay 是一个 pub/sub 机制——客户端通过 `bindStream` 订阅特定的 Session/Run 的事件流,Gateway 把 Runtime 事件广播到所有匹配的订阅连接。
+
+```mermaid
+sequenceDiagram
+ participant Runtime as Runtime
+ participant Gateway as Gateway
+ participant Client as 客户端
+
+ loop 推理循环中
+ Runtime-->>Gateway: emit(run_progress)
+ Gateway-->>Client: [SSE/WS: text_delta / tool_call / usage]
+ end
+ Runtime-->>Gateway: emit(run_done)
+ Gateway-->>Client: [SSE/WS: run_done + 结果摘要]
+```
+
+**事件驱动的价值。** AI 推理是流式的——token 逐个产出,可能持续数十秒到数分钟。事件驱动模型让客户端可以:
+- **实时看到 AI "打字"**(`text_delta` 事件逐个推送)
+- **中途取消**(发送 `gateway.cancel`,Runtime 收到后停止循环)
+- **查看 Token 消耗**(每次循环的 input/output/cache 用量实时透出)
+- **接受权限审批**(`permission_request` 暂停循环,等待用户回复)
+
+事件通道是 Go channel,StreamRelay 是进程内的 pub/sub——没有引入消息队列。这是刻意的:外部消息中间件违反零依赖部署约束。
+
+### 2.5 Runner:跨越物理机的工具执行
+
+Runner 是系统中唯一可以运行在不同物理机上的组件。场景:你在手机上通过飞书发指令,工位电脑上的 Runner 执行代码修改。
+
+```mermaid
+sequenceDiagram
+ participant Gateway as Gateway
+ participant Runner as Runner
+ participant Tools as Tools
+
+ Gateway->>Runner: WS: tool_exec_request {cap_token}
+ Runner->>Runner: 校验 Capability Token
+ Runner->>Tools: toolMgr.Execute()
+ Tools-->>Runner: [结果]
+ Runner->>Gateway: WS: tool_exec_result
+ loop 每 10s
+ Gateway->>Runner: heartbeat
+ Runner->>Gateway: ack
+ end
+```
+
+Runner 主动连接 Gateway(反向连接),不开放入站端口。这意味着 Runner 可以在 NAT/防火墙后运行。Gateway 发给 Runner 的每个工具执行请求中携带 Capability Token——这是一个 HMAC-SHA256 签名的令牌,限定允许的工具列表、路径范围和有效期。
+
+### 2.6 数据流全景
+
+以下图展示了数据从用户输入到最终输出的完整流转路径,以及每一步的数据形态变换:
+
+```mermaid
+flowchart LR
+ subgraph 客户端
+ A["用户输入
纯文本"]
+ end
+
+ subgraph Gateway
+ B["JSON-RPC Request
{method, params, id}"]
+ end
+
+ subgraph Runtime
+ C["Session Messages
[{role, content, tool_calls}]"]
+ end
+
+ subgraph Context
+ D["完整 Prompt
[SystemPrompt + History + Rules]"]
+ end
+
+ subgraph Provider
+ E["厂商 API Request
Anthropic/OpenAI/Gemini 格式"]
+ F["StreamEvent
{text_delta, tool_call, usage}"]
+ end
+
+ subgraph Tools
+ G["Tool Call
{name, arguments}"]
+ H["Tool Result
{output, is_error}"]
+ end
+
+ subgraph 回传
+ I["RuntimeEvent
{type, payload}"]
+ J["SSE/WS Event
客户端渲染"]
+ end
+
+ A --> B --> C --> D --> E --> F
+ F -->|"tool_call"| G --> H --> C
+ F -->|"text_delta"| I --> J
+
+ style A fill:#60a5fa,stroke:#60a5fa,color:#0f172a
+ style J fill:#34d399,stroke:#34d399,color:#0f172a
+```
+
+**数据形态变换要点:**
+
+| 阶段 | 输入形态 | 输出形态 | 关键变换 |
+|------|----------|----------|----------|
+| Gateway 接收 | 纯文本 + 元数据 | JSON-RPC Request | 认证注入 `subject_id`,路由到目标 Session |
+| Context 组装 | Session 消息历史 + 规则文件 | 完整 Prompt(Messages 数组) | 按固定顺序拼接 SystemPrompt;若 Token 超预算,触发 Compact |
+| Provider 转换 | 统一 Messages 数组 | 厂商特定格式 | Anthropic 用 `content blocks`,OpenAI 用 `messages`,差异在 Provider 内消化 |
+| 流式输出 | 厂商特定 SSE 格式 | 统一 StreamEvent | Provider 将厂商事件归一化为 `text_delta` / `tool_call_start` / `usage` |
+| 事件中继 | RuntimeEvent | SSE/WS 帧 | Gateway 的 StreamRelay 按 Session/Run 过滤,广播到匹配的订阅连接 |
+
+**上下文裁剪(Compact)。** 当消息历史的 Token 数接近模型窗口上限时,Context 模块自动触发压缩:
+
+- **MicroCompact**:移除较早的工具调用细节,保留摘要。优先裁剪输出最长的 Tool Result。
+- **Full Compact**:调用 LLM 对整段历史生成摘要,替换原始消息列表。旧消息删除和新摘要插入在同一个 SQLite 事务中完成,保证原子性。
+
+数据回流发生在两处:**工具结果回灌**(Tool Result 写入 Session Messages,供下一轮推理使用)和 **Compact 结果回写**(压缩后的摘要替换原始历史)。
+
+---
+
+## 3. 架构决策
+
+以下六条决策定义了 NeoCode 的基本形态。每条说明面对什么问题、选择了什么方案、付出了什么代价。
+
+### 决策 1:强边界单体
+
+**问题:** 系统需要在单机单用户场景下运行,但也要支持五人并行开发、模块独立演进。
+
+**方案:** 所有核心模块(Gateway、Runtime、Provider、Tools、Session)运行在同一进程中,通过 Go interface 解耦。模块之间只依赖接口契约,不依赖具体实现。这既不是微服务(单机场景下序列化开销和运维复杂度是净成本),也不是纯单体(模块之间直接调用会阻止独立演进)。当某个模块确实需要跨越物理机时——比如 Runner——才拆分为独立进程。
+
+**代价:** 无法独立扩缩容单个模块(当前不需要);模块间耦合只能靠接口契约约束,无法用网络隔离强制执行。
+
+### 决策 2:进程内事件驱动
+
+**问题:** AI 推理是流式的、可能持续数十秒、需要在中途暂停等待用户审批。同步调用会让客户端在推理完成前完全黑屏。
+
+**方案:** Provider 通过 Go channel 推送流式事件,Runtime 消费并转为统一的 `RuntimeEvent`,Gateway 的 StreamRelay 广播到订阅客户端。暂停-恢复语义通过事件实现:`permission_request` 事件发出后,Runtime 等待 `resolve_permission` 回复,不阻塞其他 goroutine。
+
+**代价:** 客户端需要支持 SSE 或 WebSocket 长连接,相比纯 HTTP 请求-响应多了连接管理的复杂度。
+
+### 决策 3:Gateway 作为唯一 RPC 边界
+
+**问题:** 五种客户端(TUI/Web/Desktop/飞书/CI)需要在不同场景下接入 Agent。如果各自直连 Runtime,认证和流式推送要重复实现五次。
+
+**方案:** Gateway 是系统对外的唯一入口。它不做业务逻辑——只做认证、路由和流中继。客户端只需实现 JSON-RPC 客户端 + SSE/WS 事件消费,就可以完整接入。TUI 和飞书 Bot 在 Gateway 视角完全相同。
+
+**代价:** Gateway 成为单点故障。缓解手段:本地模式下客户端自动拉起 Gateway(auto-spawn);网络模式下可部署多实例。
+
+### 决策 4:Provider 插件化,仅 2 个方法
+
+**问题:** AI 模型市场快速变化,系统需要随时接入新模型而不修改上层代码。
+
+**方案:** `Provider` interface 仅定义 `EstimateInputTokens` 和 `Generate` 两个方法。所有厂商特定的请求组装、流式格式解析、错误映射都在 Provider 实现内部消化。当前支持 Anthropic、OpenAI、Gemini、DeepSeek、MiniMax、Mimo,以及通过 OpenAI 兼容协议接入的 Qwen、GLM 等。
+
+**代价:** 无法深度利用特定厂商的高级特性(如 Anthropic 的 thinking 预算粒度控制、OpenAI 的 response_format)。这些特性需要统一抽象层来表达,当前暂不支持。
+
+### 决策 5:SQLite 持久化
+
+**问题:** 会话数据需要可靠持久化,但不能引入外部数据库运维负担。
+
+**方案:** SQLite 通过 modernc 纯 Go 实现链接到二进制。它提供 ACID 事务——Compact 替换消息列表时,旧消息删除和新摘要插入在同一个事务中完成,不会出现"消息丢了但 SessionHead 没更新"的半状态。单文件存储,备份只需复制 `session.db`。
+
+**代价:** SQLite 是单 writer,同会话的并发写必须显式串行化(sessionLock)。不同会话可以并行,单用户场景下不构成实际瓶颈。
+
+### 决策 6:JSON-RPC 2.0 + SSE/WebSocket
+
+**问题:** 第三方客户端需要用最简单的协议接入。飞书适配器是 Python 写的,CI 脚本是 Bash curl,不应该要求它们安装 protobuf 编译器。
+
+**方案:** 请求/响应用 JSON-RPC 2.0——一个 method 字符串 + params JSON + id 就能完成一次调用。流式事件用 SSE 或 WebSocket 推送——不需要额外的协议握手。这个组合让任何能发 HTTP POST 的环境都能成为 NeoCode 客户端。
+
+**代价:** 没有 gRPC 的强类型 schema 和自动代码生成。错误格式需要自行规范化(Gateway 的 `FrameError` 和 `GatewayRPCError` 做统一包装)。
+
+---
+
+## 4. 安全边界
+
+安全模型分四层。每层独立校验,不依赖上层假设下层已经"安全了"。
+
+```
+客户端 ──▶ [1] Gateway · 认证 ──▶ [2] Gateway · ACL ──▶ [3] Security Engine ──▶ [4] OS 约束
+```
+
+**第 1 层:认证。** 所有客户端统一调用 `gateway.authenticate` 获取身份。本地 loopback 场景下没有配置 Authenticator,Gateway 自动授予 `local_admin`。网络场景下 Authenticator 校验 Token 后分配 `subject_id`。`subject_id` 在整个连接生命周期内不变,作为后续所有操作的审计主体。
+
+**第 2 层:ACL。** Gateway 为每个连接维护 method × source 白名单。未授权的 method 直接拒绝,不进 Runtime。
+
+**第 3 层:Security Engine。** 这是防御的核心。两个组件协同工作:PolicyEngine 按优先级匹配策略规则(allow/deny/ask),WorkspaceSandbox 校验路径边界(阻断穿越、检测 Symlink、生成 safe 候选)。每次工具执行前必须经过这两道检查,不可跳过。
+
+**第 4 层:OS 约束。** 系统进程以当前用户权限运行。文件系统权限即 OS ACL。
+
+**贯穿所有层的保护:**
+- **密钥不入磁盘。** `api_key_env` 仅存环境变量名,真实密钥在 Provider 发起 HTTPS 请求前才从环境变量读取。密钥不出现在配置文件、日志、Gateway 传输中。
+- **敏感路径自动检测。** Security Engine 内置敏感文件特征(`.env`、`*.key`、`id_rsa` 等),命中即拒绝——不依赖用户配置策略规则。
+- **Capability Token。** Runner 的每个工具执行请求附带 HMAC-SHA256 签名令牌,限定工具白名单、路径白名单和有效期。
+
+---
+
+## 5. 部署视图
+
+**产物:** 一个 `neocode` 二进制(含 CLI、TUI、Gateway、Runner、Daemon、Web UI),通过 `CGO_ENABLED=0` 静态编译,支持 Linux/macOS/Windows × amd64/arm64。另有独立的 `neocode-gateway` 二进制用于服务器常驻。
+
+**部署拓扑:**
+- **单机:** TUI/Web/Desktop 通过本地 loopback RPC 连接 Gateway,Gateway 和 Runtime 同进程或独立 Daemon。
+- **分布:** Runner 在工位电脑上通过 WebSocket 主动连接 Gateway(云/服务器),客户端通过 Gateway 的 HTTP 端点接入。
+
+**数据目录:** `~/.neocode/`(可通过 `NEOCODE_HOME` 环境变量覆盖)。内含 `config.yaml`、`session.db`、Checkpoint 文件、Skills 缓存。
+
+---
+
+## 6. 风险
+
+| 风险 | 为什么是风险 | 当前缓解 |
+|------|-------------|----------|
+| Gateway 单点故障 | 所有客户端依赖 Gateway 入口 | 本地 auto-spawn;网络模式可部署多实例 |
+| 模型行为不可预测 | 切换模型时,同样的 Prompt 可能产生不同的工具调用策略 | Provider 2 方法接口限制差异扩散;验收测试抽样验证 |
+| 上下文窗口天花板 | 即使有 Compact,模型的 context window 有硬上限 | Compact 两级策略最大化利用窗口;`max_turns` 硬上限 |
+| SQLite 单 writer | 同会话并发写必须串行化 | 不同会话可并行;单用户场景不构成瓶颈 |
+| TOCTOU 路径竞态 | 安全检查与实际文件操作之间存在微小时间窗口 | `O_NOFOLLOW` 缓解;本地单用户攻击面极小 |
+
+---
+
+## 7. 可扩展性
+
+系统设计了五个主要扩展点。每个扩展点遵循同一原则:**新增能力不修改已有模块的代码**。
+
+### 7.1 Provider:接入新模型
+
+**扩展方式:** 实现 `Provider` 接口的 2 个方法。
+
+```go
+type Provider interface {
+ // EstimateInputTokens 估算输入 Token 数,用于 Compact 决策
+ EstimateInputTokens(messages []Message) (int, error)
+ // Generate 发起流式推理,通过 channel 返回 StreamEvent
+ Generate(ctx context.Context, params GenerateParams) (<-chan StreamEvent, error)
+}
+```
+
+**接入步骤:**
+1. 在 `internal/provider/` 下新建厂商目录
+2. 实现 `Provider` 接口,将厂商特定的请求组装、流式格式解析、错误映射封装在实现内部
+3. 在 Provider 注册表中注册新实现
+4. 在 `config.yaml` 中添加对应的 provider 配置项
+
+**边界:** 厂商差异不泄漏到 Runtime 或 Gateway。所有厂商特定的字段、错误码、流式格式在 Provider 内部消化。
+
+### 7.2 Tool:新增可被模型调用的能力
+
+**扩展方式:** 定义 Tool Schema + 实现 Execute 方法。
+
+每个 Tool 需要提供:
+- **Schema**:JSON Schema 格式的参数定义,描述工具名称、用途、输入参数及其类型约束。模型根据 Schema 决定何时调用、传什么参数。
+- **Execute**:接收经过 Schema 校验的参数,执行操作,返回结果。
+
+**当前内置工具(示例):**
+
+| 工具 | 能力 | 安全约束 |
+|------|------|----------|
+| `read_file` | 读取文件内容 | 工作区沙箱限制路径 |
+| `write_file` | 写入/创建文件 | 工作区沙箱 + Checkpoint 快照 |
+| `bash` | 执行 Shell 命令 | 超时限制 + 输出长度限制 + 禁止交互式命令 |
+| `web_fetch` | 抓取网页内容 | 协议范围限制 + 响应大小限制 |
+| `search_code` | 代码库搜索 | 工作区沙箱 |
+
+**接入步骤:**
+1. 在 `internal/tools/` 下新建工具文件
+2. 定义 Schema(名称、描述、参数的 JSON Schema)
+3. 实现 Execute 函数(参数校验 → 权限检查 → 执行 → 输出裁剪 → 返回结果)
+4. 在 Tools Manager 中注册
+
+**边界:** 所有可被模型调用的能力必须经过 `internal/tools` 注册。不允许在 Runtime 或 TUI 中内嵌工具逻辑。每个工具的执行都经过 Security Engine 的安全检查,不可跳过。
+
+### 7.3 Context:扩展上下文源
+
+**扩展方式:** Context 模块按固定顺序组装 System Prompt,每个组装阶段是独立的构建步骤。
+
+**当前上下文源:**
+1. 核心行为准则(System Identity)
+2. 工具能力列表(Tool Schemas)
+3. 项目规则(`.agents/` 目录下的规则文件)
+4. 当前任务状态(Todo 列表、Plan 上下文)
+5. Skills 上下文(激活的 Skill 指令)
+6. 消息历史(Session Messages)
+
+**如何扩展:**
+- 新增上下文源时,在 Context Builder 的构建流程中添加对应的构建步骤
+- 每个构建步骤独立负责内容生成和 Token 预算控制
+- Compact 策略由 Context 模块统一管理,新增的上下文源自动参与 Token 预算核算
+
+**边界:** Context 只负责 Prompt 构建与上下文裁剪,不处理运行时决策。Compact 的触发时机由 Runtime 决定,Compact 的执行策略由 Context 决定。
+
+### 7.4 Security:扩展安全策略
+
+**扩展方式:** Security Engine 的策略引擎支持按优先级匹配的规则列表。
+
+**规则结构:**
+- **匹配条件**:工具名、路径前缀 / Glob、域名、文件类型
+- **决策**:`allow`(直接放行)、`deny`(直接拒绝)、`ask`(暂停等用户审批)
+- **优先级**:数值越小优先级越高,首个匹配的规则生效
+
+**如何扩展:**
+- 通过配置文件添加自定义策略规则
+- 内置的敏感路径检测(`.env`、`*.key`、`id_rsa` 等)作为最高优先级硬编码规则,不可被配置覆盖
+- WorkspaceSandbox 的路径边界校验独立于策略规则,始终生效
+
+### 7.5 客户端:接入新的前端
+
+**扩展方式:** 实现 JSON-RPC 2.0 客户端 + SSE/WebSocket 事件消费。
+
+任何能发送 HTTP POST 的环境都可以成为 NeoCode 客户端。接入新前端不需要修改 Gateway 或 Runtime 的任何代码——只需要:
+
+1. 调用 `gateway.authenticate` 获取身份
+2. 通过 JSON-RPC 发送指令(`gateway.run`、`gateway.cancel` 等)
+3. 通过 SSE 或 WebSocket 订阅并消费事件流
+
+**已有实现:** TUI(Go)、Web UI(嵌入式)、飞书适配器(Python)、CI 脚本(Bash curl)。
+
+---
+
+## 附录 A:术语
+
+| 术语 | 含义 |
+|------|------|
+| **ReAct Loop** | 推理→工具调用→结果回灌→继续推理,直到产出最终文本 |
+| **Compact** | Token 预算接近阈值时,自动压缩/摘要化历史消息 |
+| **StreamRelay** | Gateway 内部的 pub/sub,将 Runtime 事件广播到订阅客户端 |
+| **Checkpoint** | AI 写操作前的自动文件快照,支持回滚 |
+| **Human-in-the-Loop** | 危险操作暂停执行,等待人类审批 |
+| **Capability Token** | Runner 执行工具时携带的 HMAC 签名令牌,限定能力和范围 |
+
+## 附录 B:架构决策索引
+
+| ADR | 决策 | 详见 |
+|-----|------|------|
+| ADR-001 | Gateway 作为唯一 RPC 边界 | [architecture-v1.md §15](architecture-v1.md) |
+| ADR-002 | Provider 2 方法接口 | [architecture-v1.md §15](architecture-v1.md) |
+| ADR-003 | 事件驱动异步执行 | [architecture-v1.md §15](architecture-v1.md) |
+| ADR-004 | 强边界单体 | [architecture-v1.md §15](architecture-v1.md) |
+| ADR-005 | SQLite 持久化 | [architecture-v1.md §15](architecture-v1.md) |
+| ADR-006 | JSON-RPC 2.0 + SSE/WS | [architecture-v1.md §15](architecture-v1.md) |
+| ADR-007 | Runner 反向连接 | [architecture-v1.md §15](architecture-v1.md) |
+| ADR-008 | Checkpoint 本地快照 | [architecture-v1.md §15](architecture-v1.md) |
+
+## 附录 C:相关文档
+
+| 文档 | 路径 |
+|------|------|
+| v1 完整架构(详细流程、模块描述) | [architecture-v1.md](architecture-v1.md) |
+| 产品定位与竞品分析 | [../product/positioning.md](../product/positioning.md) |
+| Gateway RPC API 参考 | [../reference/gateway-rpc-api.md](../reference/gateway-rpc-api.md) |
+| 安装、告警与诊断 | [../guides/operations.md](../guides/operations.md) |
+| 已知局限与技术债 | [../tech-debt.md](../tech-debt.md) |
+| 未来演进路线图 | [../roadmap.md](../roadmap.md) |
+| 项目开发规范 | [../../AGENTS.md](../../AGENTS.md) |
diff --git a/docs/architecture/diagrams/system-context.svg b/docs/architecture/diagrams/system-context.svg
new file mode 100644
index 00000000..75c8a37f
--- /dev/null
+++ b/docs/architecture/diagrams/system-context.svg
@@ -0,0 +1,176 @@
+
diff --git a/docs/architecture/diagrams/system-context@2x.png b/docs/architecture/diagrams/system-context@2x.png
new file mode 100644
index 00000000..b47ac541
Binary files /dev/null and b/docs/architecture/diagrams/system-context@2x.png differ
diff --git a/docs/guides/operations.md b/docs/guides/operations.md
new file mode 100644
index 00000000..c162c7e4
--- /dev/null
+++ b/docs/guides/operations.md
@@ -0,0 +1,34 @@
+# NeoCode 运维指南
+
+### 12.3 安装与分发
+
+| 渠道 | 说明 |
+|------|------|
+| **Shell 脚本** | `curl -fsSL /install.sh \| bash`(macOS/Linux),支持 `--flavor full\|gateway` |
+| **PowerShell** | `irm /install.ps1 \| iex`(Windows) |
+| **自更新** | `neocode update` 命令通过 `go-selfupdate` 拉取最新 GitHub Release,校验 checksum 后原地替换二进制 |
+| **Electron 桌面端** | 通过 `electron-builder` 打包为 `.dmg`(macOS)/ `.exe` installer(Windows)/ `.AppImage`(Linux) |
+| **手动下载** | GitHub Releases 页面下载对应平台的 `.tar.gz` / `.zip` |
+
+
+### 14.5 告警建议
+
+基于 Gateway 暴露的 Prometheus 指标,推荐配置以下告警规则:
+
+| 告警 | 条件 | 严重度 |
+|------|------|--------|
+| 认证失败率异常 | `rate(gateway_auth_failures_total[5m]) > 0.1` | Warning |
+| ACL 拒绝突增 | `rate(gateway_acl_denied_total[5m]) > 5` | Warning |
+| 流连接数接近上限 | `gateway_connections_active > max * 0.8` | Warning |
+| 流连接异常剔除 | `rate(gateway_stream_dropped_total[5m]) > 0` | Critical |
+| Gateway 不可达 | `gateway.ping` 无响应或 `/healthz` 非 200 | Critical |
+
+### 14.6 运维诊断工具
+
+| 工具 | 用途 |
+|------|------|
+| `neocode diag` | Shell 诊断代理:自动获取终端最近一次命令的异常输出,调用 LLM 分析原因并给出建议 |
+| `neocode daemon status` | 查看 HTTP Daemon 运行状态与自启动安装状态 |
+| `neocode gateway --http-listen ` | 显式指定 Gateway HTTP 监听地址,供调试时暴露到非 loopback 接口 |
+| Session Log Viewer | Runtime 内部将关键会话事件写入 `log-viewer/` 目录,供离线排查 |
+
diff --git a/docs/product/positioning.md b/docs/product/positioning.md
new file mode 100644
index 00000000..b90aca9c
--- /dev/null
+++ b/docs/product/positioning.md
@@ -0,0 +1,78 @@
+## 2. 系统背景与目标
+
+
+### 2.1 核心定位
+
+NeoCode 是一个**本地优先、架构解耦、可被随时唤醒和编排的 AI Coding Agent 基础设施**。
+
+2025–2026 年,AI 编码工具已经从"代码补全"进化到"Agent 自主行动"——Claude Code、Codex CLI、OpenCode 等终端 CLI 工具已经证明了开发者不需要换 IDE 就能获得 Agent 级的 AI 辅助。MCP 和 Skills/Hooks 机制已成为 Agent 扩展生态的通用语言。多模型接入也不再是新鲜事。
+
+在这个背景下,NeoCode 的定位不是"发明一个新品类",而是在已有的 Agent 基础设施共识之上,**将这些能力按照自己的设计哲学重新组装**——追求**更强的架构解耦**、**更多的客户端形态**、**更开放的多模型自由**,并通过 Gateway 统一 RPC 边界将这些能力暴露给任何想接入的客户端。
+
+### 2.2 NeoCode 的设计信念
+
+NeoCode 的设计基于以下几条核心判断:
+
+1. **AI Agent 不应该是编辑器的附属功能。** 它应该是一个独立的"结对编程进程"——在你写代码时安静运行在终端或后台,在你离开工位时仍然可以通过 IM 唤醒。所以 NeoCode 选择**"旁路架构"**而非"IDE 插件架构"(这一判断与 Claude Code、Codex CLI、OpenCode 一致——它们是 CLI 工具,不是 IDE 插件。但 NeoCode 进一步将**"独立进程"**推到极致:提供独立的 Gateway Daemon、独立的 Runner,以及可被第三方适配器接入的 RPC 接口)。
+
+2. **开发者不应该为 AI 体验而被锁定在一个模型或一个厂商上。** 多模型支持已是行业标配(Claude Code 支持多模型、Codex 原生多模型、OpenCode 也支持切换 provider)。NeoCode 的做法是让 Provider 成为架构层面的**一等公民**——不是"配置项切换",而是**独立的插件化接口层**,新增模型的改动严格收敛在 Provider 包内,上层零改动。
+
+3. **AI Agent 的能力边界应该由使用者决定。** MCP 和 Skills/Hooks 是 Codex、Claude Code 等行业先行者开创的扩展机制。NeoCode 完整支持这些开放协议,并进一步将它们**整合**到 Gateway 安全边界内——所有工具(包括 MCP 挂载的外部工具)**统一经过** Security Engine 的权限裁决,确保扩展能力不侵蚀安全底线。
+
+4. **客户端形态应该自由演化。** 终端 TUI 是核心体验(与 Claude Code/Codex CLI/OpenCode 同类),但不应是唯一入口。NeoCode 的 Gateway 将 Agent 能力通过标准 JSON-RPC/SSE/WebSocket 暴露,使得 Web 端、桌面端、飞书 Bot、CI/CD 脚本都是**对等的一等公民客户端**——不需要"终端优先再做 Web 适配"。
+
+### 2.3 目标用户
+
+| 用户角色 | 核心场景 | 是否独创 | NeoCode 的思考 |
+|----------|----------|----------|---------------|
+| 追求编辑器自由的独立开发者/资深工程师 | 习惯 Neovim/JetBrains/Emacs,不愿为 AI 迁移到特定 IDE | 人有我有:Claude Code、Codex CLI、OpenCode 均已解决"不换 IDE 用 AI" | 旁路架构与它们一致。NeoCode 的不同:Gateway 作为一等公民设计——TUI/Web/Desktop 完全对等,不是"先有 CLI 再补 Web";多模型切换是架构级的 Provider 插件化,不是配置切换 |
+| 需要随时响应代码问题的敏捷/分布式团队 | 通勤或开会时遇到线上问题,快速查阅和修改代码 | 创意集成,做的更好:Claude Code 有 headless 模式可做基础集成;NeoCode 将 IM 接入作为一等公民设计 | Local Runner 反向连接 + 飞书 Adapter 原生集成:Runner 主动连 Gateway(无需公网 IP),飞书 Bot 作为对等客户端接入 Gateway RPC。这不是"CLI 工具加了个 IM 通知",而是 IM 就是一个完整的 Agent 交互界面 |
+| DevOps 工程师与自动化工作流构建者 | 需要把 AI 接入 CI/CD,通过 RPC 驱动代码库操作 | 人有我有:Codex/Claude Code 可做脚本集成 | NeoCode 的 Gateway 从设计第一天就是独立的 RPC 服务(`neocode gateway` 子命令),不是 CLI 的附属模式。JSON-RPC 协议使得 Python/Bash/Node.js 脚本都能平等接入 |
+
+### 2.4 与同类产品的差异化
+
+NeoCode 不声称自己发明了 AI Coding Agent 的基础范式——ReAct 循环、MCP 扩展、流式推理、上下文压缩这些都是行业的共同财富。以下按照"行业现状"和"NeoCode 的差异化设计"两层来对比。
+
+**行业现状(2026 年 AI 编码工具概览):**
+
+| 产品 | 类型 | 已有能力 |
+|------|------|----------|
+| **Claude Code** | CLI Agent(闭源) | ReAct Agent、MCP、Skills/Hooks、多模型、上下文压缩、Plan Mode、终端 TUI |
+| **Codex CLI** | CLI Agent(开源) | ReAct Agent、MCP、多模型、Skills、沙箱执行、终端 TUI |
+| **OpenCode** | CLI Agent(开源) | ReAct Agent、MCP、多模型、终端 TUI、可自定义 provider |
+| **Cursor / Windsurf** | IDE 分叉(闭源) | IDE 深度集成、Agent 模式、代码补全、内联编辑 |
+| **GitHub Copilot** | IDE 插件 | 代码补全、Agent 模式(Copilot Chat)、MCP |
+
+**NeoCode 的差异化:不是"别人没有我有",而是"别人有,我按自己的设计哲学重新组装,并在几个方向上做得更深"。**
+
+| 能力维度 | 行业现状 | NeoCode 的设计选择 |
+|----------|----------|-------------------|
+| **架构模型** | Claude Code/Codex CLI/OpenCode 是 CLI 优先的单体 Agent | Gateway 作为独立的 RPC 服务层:Agent 能力通过 JSON-RPC/SSE/WS 对外暴露,所有客户端(包括 TUI)都通过同一套 RPC 协议接入。这使得"把 Agent 作为基础设施"从第一天就是架构事实,不是后期改造 |
+| **多模型支持** | Codex、OpenCode、Claude Code 均支持多模型切换 | Provider 是架构级的一等公民:不是"配置项",而是独立的插件化接口层(2 方法 interface)。新增模型不需要改 Runtime 或 Gateway 一行代码 |
+| **多客户端** | Claude Code 有 VS Code 扩展、Codex 有 Web UI | NeoCode 的 TUI/Web/Desktop 三者完全对等——没有"先做 CLI 再适配 Web"的技术债。第三方客户端(如飞书 Bot)通过适配器接入,与原生客户端在 Gateway 视角完全一致 |
+| **IM 接入** | Claude Code 可通过 API 做基础集成 | NeoCode 将飞书 Bot 作为一等公民客户端设计——完整的 Agent 交互(run、ask、permission_request、流式回复)都可以在 IM 中完成。Local Runner 反向连接使得 IM 指令能操作工位电脑的代码库 |
+| **安全模型** | Claude Code 有权限系统(ask/allow/deny) | NeoCode 在此基础上增加:策略引擎(按 Priority 排序的规则匹配)、工作区沙箱(路径穿越/Symlink 检测)、敏感路径自动检测(`.env`、`.ssh`、密钥文件)、Runner 的 Capability Token 签名——四层纵深防御 |
+| **部署形态** | Claude Code 为单二进制、Codex 需要 Node.js 运行时 | Go 静态编译单二进制(`CGO_ENABLED=0`),零运行时依赖。同一二进制提供 CLI、Gateway Daemon、Runner、HTTP Daemon 全部子命令 |
+| **可扩展性** | Claude Code/Codex 均有 MCP 和 Hooks/Skills | NeoCode 完整支持 MCP + Skills + Hooks,并明确区分三种扩展路径(有代码工具、零代码 MCP、零代码 Skills),在 §7.6 中集中定义了 7 个扩展点的接口契约和 4 条不可扩展边界 |
+
+### 2.5 核心痛点与 NeoCode 的方案
+
+以下三个痛点并非 NeoCode 独自发现——它们是 AI 编码工具行业公认的摩擦点。这里记录 NeoCode 针对每个痛点的**具体设计方案**。
+
+| 痛点 | 量化估算 | 行业中已有的解决思路 | NeoCode 的方案 |
+|------|----------|---------------------|---------------|
+| 终端→AI→编辑器频繁切换 | 每天 1–2 小时 | Claude Code/Codex CLI/OpenCode 均通过终端内 Agent 解决 | PTY Proxy 诊断代理:不只是"在终端里跑 AI",而是自动截获终端最近一次命令的异常输出(编译错误、运行时 panic),原地附加 AI 诊断,不需要离开终端 |
+| 非工位状态下的代码查阅与应急 | 单次切换耗时极大 | Claude Code 的 headless 模式可做基础集成 | Local Runner 反向连接 + 飞书 Adapter 原生集成:Runner 主动连 Gateway(无需公网 IP/入站端口),飞书 Bot 作为对等客户端接入,手机端发指令 → 工位电脑执行 → 结果回传 IM |
+| 将公司内部工具接入 AI 工作流 | 传统 AI 工具无法调用内网基建 | Claude Code/Codex/OpenCode 率先引入了 MCP 和 Skills 机制 | NeoCode **完整支持 MCP + Skills**(这是行业标准,不是 NeoCode 独创)。NeoCode 的增量在于:外部的 MCP 工具统一经过 Security Engine 的权限裁决(每次调用前经过 PolicyEngine + WorkspaceSandbox),确保"扩展能力"不变成"安全漏洞";Skills 的 project/global 双层加载 + 会话级激活,使其更易于在团队中管理和复用 |
+
+
+### 5.2 团队与组织约束
+
+| 约束项 | 说明 |
+|--------|------|
+| 团队规模 | 5 名核心开发者 |
+| 模块分工 | TUI/Gateway 适配层(1 人)、Provider/Runtime/上下文压缩/网站(1 人)、Tools/Security/Hook/飞书适配器(1 人)、Session/Context/Memo/PromptAsset/Web/App(1 人)、Gateway/URL Scheme/Shell诊断/CLI/CI/发布/安装脚本(1 人) |
+| 审查流程 | 组内 peer review,简单审查后合入 |
+| 发布节奏 | 按需发布,通过 goreleaser 自动构建 |
+| 代码规范 | 参见 `AGENTS.md`:严格 UTF-8 编码、Go 惯用风格、TAB 缩进、中文注释、单行约 120 字符 |
+
diff --git a/docs/roadmap.md b/docs/roadmap.md
new file mode 100644
index 00000000..fe608439
--- /dev/null
+++ b/docs/roadmap.md
@@ -0,0 +1,62 @@
+# NeoCode 未来演进路线图
+
+## 17. 未来演进
+
+以下演进方向的优先级判断基于一个核心问题:**"这项改进对 NeoCode 的独特价值(本地优先、多端接入、多模型自由、Human-in-the-loop 安全)有多大推动?"**
+
+### 17.1 短期(已在进行或立即需要的改进)
+
+| 方向 | 理由 | 优先级 |
+|------|------|--------|
+| **传输层全 HTTP 化** | 当前 `transport/` 中残留的 Unix socket / Named pipe 逻辑增加了双平台代码路径和维护负担。统一到 HTTP JSON-RPC 后:第三方客户端接入更简单(只需要发 HTTP POST,不需要理解 Unix socket 地址规则)、Windows 和 Linux/macOS 的客户端连接逻辑完全一致 | 高——正在进行 |
+| **Gateway 大文件拆分** | `bootstrap.go` 超 1600 行,包含帧路由、认证、session CRUD、RPC 处理、流绑定等所有 Gateway 逻辑。5 人团队每人负责不同模块,但 Gateway 的改动集中在同一大文件中 → 持续的合并冲突。按功能域拆分为 `auth_handler.go`、`session_handler.go`、`stream_handler.go` 后,各自改自己的文件 | 高——直接影响并行开发效率 |
+| **Runner 工具并行执行** | Runner 当前串行处理 Gateway 下发的工具请求。在"手机飞书下指令 → 工位 Runner 执行"场景中,模型经常一次产出多个独立的 tool call(如同时读 3 个文件),串行执行导致不必要的延迟。改为并行执行可显著改善远程场景的响应体验 | 中——核心差异化场景的性能瓶颈 |
+| **Compact 配置收敛** | MicroCompact 的 `MicroCompactConfig`、Full Compact 的 `CompactConfig`、预算阈值在 `RuntimeConfig` 中分散定义。调整上下文压缩策略时需要理解三个不同的配置入口,容易产生不一致的配置。收敛为单一 `CompactPolicy` 结构体 | 中——降低调优门槛 |
+
+### 17.2 中期(巩固和放大现有差异化优势)
+
+| 方向 | 理由 |
+|------|------|
+| **第三方客户端生态增强** | 飞书 Adapter 已证明"适配器接入 Gateway → 复用全栈 Agent 能力"的模式可行。下一步是降低第三方适配器的编写成本:提供官方 SDK(Go/Python/Node.js)封装 `gateway.authenticate` → `gateway.run` → SSE 事件消费的完整流程。这直接放大 NeoCode 最大的差异化优势——"任何客户端都能接入的 AI Agent 基础设施" |
+| **Skills 和 MCP 体验改善** | 当前 Skills 需要手动在目录中放置 `SKILL.md` 文件,MCP Server 需要手动编辑 JSON 配置。这些操作的受众是开发者,但不是所有开发者都愿意读 YAML。方向:`neocode skill add ` 一键安装 Skill;`neocode mcp add ` 自动生成 MCP 配置。降低扩展成本直接提升生态壁垒 |
+| **Checkpoint 可视化与选择性恢复** | Checkpoint 已在后台静默创建,但用户缺少手段查看"AI 在上一轮改了什么、为什么改"。方向:在 TUI/Web 端展示 `end_of_turn` Checkpoint 的 Diff 预览,支持用户选择"回滚到上一步"或"只回滚某个文件"。这增强 Human-in-the-loop 的安全信任感 |
+| **安全策略预置模板** | 当前 Security Engine 的策略规则完全由用户自定义(或使用默认 `ask` 兜底)。多数用户不会写策略规则。方向:预置 3 套模板("宽松——信任所有工作区操作"、"标准——敏感文件需确认"、"严格——任何写入操作需确认"),用户一键切换。安全能力如果门槛太高,等于没有 |
+| **模型切换体验深化** | Provider 零侵入接入已实现(ADR-002),但用户切换模型时的体验仍粗糙:不知道新模型在"代码修改"场景的实际表现、不知道它的上下文窗口和工具调用能力。方向:为每个 Provider 提供能力画像(context window、tool calling 支持、已知局限),在切换时展示 |
+
+### 17.3 长期(战略级方向)
+
+| 方向 | 理由 |
+|------|------|
+| **无头模式(Headless Agent)** | NeoCode 的核心能力(ReAct 推理 + 工具执行)当前主要通过交互式客户端消费。但对于 CI/CD 场景——"当 PR 被标记为 `neocode-review` 时自动运行代码审查 Agent"——需要一个无交互的批处理模式。技术上 Runtime 已支持,缺少的是:非交互式权限策略(`allow`/`deny` 无 `ask`)、简洁的结果输出格式。这是从"开发者工具"走向"基础设施"的关键一步 |
+| **Runner 能力谱系** | 当前 Runner 是一个"全有或全无"的远程执行代理——注册后就能执行所有工具。但不同场景需要不同权限:CI Runner 可能只需要 `bash`(跑测试);代码审查 Runner 可能只需要 `filesystem_read` + `codebase_search`。方向:Runner 注册时声明自己的能力谱系(tool list + path allowlist),Gateway 按需路由 |
+| **会话可移植性** | 当前会话数据绑定在本地 SQLite。如果开发者在工位电脑上开了一个长会话调试问题,回家后想在笔记本上继续,需要手动迁移 `session.db`。方向:可选的会话导出/导入(标准化格式),或可插拔的远程 Session Store 后端。这直接服务于"随时随地连线本地代码库"的价值主张 |
+
+### 17.4 刻意不做的方向
+
+以下方向经常被提及,但**故意不作为**演进目标:
+
+| 方向 | 不做理由 |
+|------|----------|
+| **自研模型或模型微调** | NeoCode 是 Agent 框架,不是模型厂商。见 §2.6 非目标 #2 |
+| **云端 SaaS 托管** | 代码留在本地是最核心的安全承诺。见 §2.6 非目标 #1 |
+| **重型 IDE 插件(Copilot 模式)** | 旁路架构是核心差异化。见 §2.6 非目标 #4 |
+| **微服务化拆分** | 单机场景下分布式是负资产。见 ADR-004 |
+| **引入消息队列(Kafka/RabbitMQ)** | 零外部依赖是强约束。见 ADR-005 的推理链 |
+| **图数据库 / 向量数据库** | 代码库理解(Tree-sitter AST + Grep + Glob)在代码领域远超向量检索的准确度,且不需要额外的数据库运维 |
+
+### 17.5 可替换模块
+
+以下模块在设计时就考虑了被替换的可能性——这是分层架构(§7.1)和接口优先原则(§5.4 原则 5)的直接成果:
+
+| 模块 | 可替换原因 | 替换成本 |
+|------|-----------|----------|
+| **Provider 实现** | 仅需实现 2 方法 interface | 低——新增 Go 包 + 配置即可 |
+| **Authenticator** | `TokenAuthenticator` interface | 低——实现验证逻辑即可 |
+| **工具(单个)** | `Executor` interface | 低——注册到 Registry 即可 |
+| **Skills 来源** | `SourceLayer` 机制 | 低——新增目录即可 |
+| **Web UI** | 独立于后端逻辑,纯 RPC 通信 | 中——需重写 UI 层,Gateway API 不变 |
+| **Session Store 后端** | `Store` interface | 中——理论上可替换为其他存储,但需重新评估 ADR-005 的零依赖约束 |
+| **Gateway 传输协议** | `transport.Listener` interface | 中——需实现新协议适配 |
+| **Runtime(整个)** | 通过 Gateway RPC 隔离 | 高——理论上可用非 Go 实现,但触及系统根基 |
+
+---
diff --git a/docs/tech-debt.md b/docs/tech-debt.md
new file mode 100644
index 00000000..4ace9ad1
--- /dev/null
+++ b/docs/tech-debt.md
@@ -0,0 +1,34 @@
+# NeoCode 已知局限与技术债
+
+### 16.1 架构风险
+
+| 风险 | 严重度 | 描述 | 缓解措施 |
+|------|--------|------|----------|
+| **Gateway 单点故障** | 中 | 所有客户端依赖 Gateway 作为唯一入口;Gateway 进程异常时整个系统不可用 | 客户端内置自动拉起(auto-spawn);本地 loopback 部署下 Gateway 与 CLI 同生命周期;网络模式下建议部署多个 Gateway 实例(当前未实现) |
+| **模型行为不可预测** | 高 | 底层模型升级或切换时,Agent 的行为可能发生微妙变化(推理深度、工具选择偏好、错误处理风格),且这种变化难以通过自动化测试捕获 | Provider 层契约极简(2 方法),限制厂商差异扩散;100% 覆盖率的框架层测试确保框架逻辑不受影响;实际模型行为通过验收测试(`runtime/acceptance/`)做抽样验证 |
+| **SQLite 写并发瓶颈** | 低 | 同会话的所有写操作(追加消息、更新状态、Compact 替换)串行执行;当需要跨多个会话做批量分析时单 writer 限制成为瓶颈 | 同会话并发写已通过 `sessionLock` 串行化,不同会话可并行;当前用户场景(单用户、顺序交互)下不构成实际瓶颈;若未来需要批量跨会话操作,可通过读写分离(读可并发)缓解 |
+| **上下文窗口天花板** | 中 | 即使有 Compact,模型原生的 context window 有硬限制(如 Claude 200K、GPT-4 128K);对于超长会话,最终仍会达到无法继续的临界点 | Compact 两级策略(Micro + Full)最大化利用现有窗口;`max_turns` 限制防止无限循环;长期来看需借助模型厂商的 context window 增长 |
+| **TOCTOU 路径竞态** | 低 | 文件系统操作在 Security Engine 校验通过后、实际读写前,目标路径的状态可能被外部进程改变(symlink 替换攻击) | 当前在校验时 resolve symlink,但存在微小的时间窗口;现代 OS 的 `O_NOFOLLOW` 等标志可进一步缓解;实际攻击面极小(本地单用户场景) |
+
+### 16.2 已知局限
+
+| 局限 | 影响 | 讨论 |
+|------|------|------|
+| **单机单用户模型** | 不支持多用户共享同一 NeoCode 实例 | 这是刻意的设计选择(见 ADR-004)。多用户场景可通过每个用户运行自己的 Gateway 实例 + 共享 Runner 来解决,不需要多租户 |
+| **无分布式追踪** | SessionID/RunID 仅在 NeoCode 内部可追踪,无法与外部的 APM(如 Datadog、Jaeger)关联 | 当前通过标准化日志格式(SessionID+RunID 前缀)做手动关联,未引入分布式追踪 SDK。如果未来部署复杂度提升,可在 Gateway 层注入 OpenTelemetry context |
+| **纯 Go 生态** | 工具和 Skill 的执行受限于 Go 生态;无法直接调用 Python/Node.js 库 | MCP 协议(stdio 子进程)提供了语言无关的扩展通道。Python/Node.js 工具可通过 MCP server 接入 |
+| **Web UI 嵌入分发** | Web 端 patch 只能随二进制更新,不支持独立热更新 | 这是单二进制部署的代价。对于需要频繁更新 UI 的场景,可将 Web 端独立部署(当前已支持 `neocode-gateway` 独立二进制 + 反向代理静态资源) |
+| **无插件市场/发现机制** | Skills 和 MCP server 的获取依赖用户手动配置,没有中心化的发现和安装渠道 | 当前的 Skills 设计优先保证离线可用性和零信任(文件即 Skill)。发现机制可在此基础上叠加 |
+
+### 16.3 技术债清单
+
+| 技术债 | 位置 | 影响 | 建议处理时机 |
+|--------|------|------|-------------|
+| **底层传输层 IPC 残留** | `internal/gateway/transport/` — Unix domain socket / Named pipe | 客户端连接路径复杂(需判断平台选 socket 类型),迁移到全 HTTP 后可消除 | 短期——已在迁移计划中 |
+| **`runtime/run.go` 单文件过长** | ReAct 主循环逻辑集中在 `run.go` (~400 行) 和 `runtime.go` (~540 行) | 新成员理解核心循环需要较长时间;修改风险集中在少数大文件中 | 中期——可按阶段拆分(pre-processing / loop body / termination) |
+| **Compact 策略配置分散** | MicroCompact 配置在 `MicroCompactConfig`,Full Compact 在 `CompactConfig`,部分阈值在 `RuntimeConfig` | 调整上下文管理策略需要理解三处配置 | 中期——收敛为统一的 `CompactPolicy` 结构体 |
+| **Gateway Bootstrap 单文件** | `bootstrap.go` 超过 1600 行,包含帧路由、认证、session CRUD、RPC 处理 | 单体文件难以定位和维护 | 中期——拆分为 `session_handler.go`、`rpc_handler.go`、`auth_handler.go` |
+| **Acceptance 测试耗时长** | `runtime/acceptance/` 的端到端测试依赖真实模型 API | CI 成本高、不稳定(网络波动导致 flaky) | 长期——增加录制/回放(VCR)模式,CI 中默认使用录制的 fixture |
+
+---
+