diff --git a/ARCHITECTURE_DESIGN.md b/ARCHITECTURE_DESIGN.md
index 73d32d7..bb4e16b 100644
--- a/ARCHITECTURE_DESIGN.md
+++ b/ARCHITECTURE_DESIGN.md
@@ -1,239 +1,913 @@
-# sundynix-agentix · 架构设计文档(当前完整版)
+# sundynix-agentix · 架构设计文档
-> 版本:2026-07-02(反映 T0–T2 全量 + T4.B/E 完成 + T4.F 部分后的现状)
-> 定位:**事件驱动的 AI Agent 平台**。以 NATS 为统一总线,服务经契约解耦,Eino 为编排核心,控制面热切换。
-> 配套文档:`ARCHITECTURE_REVIEW.md`(架构评审:优缺点/技术债)、`DEPTH_ROADMAP.md`(路线图)、`EINO_ADOPTION.md`(Eino 采纳)。
+> 版本:2026-07-26
+> 定位:**事件驱动的多租户 AI Agent 平台**。以 NATS 为统一总线,服务经契约解耦,Eino 为编排核心,控制面热切换;桌面端 JARVIS 既是语音入口,也是能操作用户电脑的中枢。
+>
+> **本文以代码为单一事实源。** `PROGRESS.md`(停更于 2026-06-19)与 `DEPTH_ROADMAP.md` 的汇总表已与代码脱节(详见 §9.14),仅作历史参考。
+>
+> 配套文档:`ARCHITECTURE_REVIEW.md`(架构评审)、`DEPTH_ROADMAP.md`(路线图)、`EINO_ADOPTION.md`(Eino 采纳)、`SAAS_DESIGN.md` / `SAAS_P2_DESIGN.md`(多租户与计量)、`SPACE_DESIGN.md`(共享工作区)、`PAYMENT_DESIGN.md`(支付)、`VOICE_DESIGN.md`(语音)、`JARVIS_BRAIN_DESIGN.md`(JARVIS 中枢)、`LOCAL_AGENT_DESIGN.md`(本地执行)、`DEPLOY.md`(部署)。
---
## 1. 系统概述
-sundynix-agentix 把「用户在画布上编排 Agent 图 → 平台调度执行 → 实时回流结果」做成一套可运维、可观测、可扩展的平台。核心特征:
+用户在桌面端搭一张编排图(或直接说话),任务经网关落库并发到 NATS;调度集群把 DSL 编译成 Eino compose 图执行,过程中自主调用工具(检索/联网/计算/操作用户电脑),Token 与执行轨迹实时流回界面;全程带计量计费、护栏、评测与链路追踪。
-- **图编排执行**:前端画布导出 DSL(节点+连线),后端编译为可执行图,支持分支、并行、多智能体、人工审批。
-- **工具即服务**:能力(RAG/记忆/历史/报告/沙箱)以独立 MCP 服务经 NATS 暴露,加工具零改调度代码。
-- **分层韧性**:模型 failover + 熔断 + 预算 + 输入护栏 + 输出脱敏 + 自动评测纠偏(「恒温器」治理层)。
-- **控制面热切换**:模型配置、提示词经 NATS 广播热下发,不重启即生效。
-- **流式原生**:token 流与执行轨迹经 NATS→Redis Stream→SSE 实时回流,支持断点重放。
+### 1.1 Monorepo 结构
+
+```
+sundynix-agentix/
+├── sundynix-shared/ 共享库:NATS 总线 / 契约 / 对象存储 / 密钥 / OTel / prompts
+├── sundynix-gateway/ 第 2 层 业务网关(HTTP + WS + 平台工具 + 后台常驻)
+├── sundynix-dispatcher/ 第 4 层 Agent 编排调度集群(无对外端口)
+├── sundynix-mcp-go/ 第 5 层 Go I/O 型工具服务(RAG / 记忆 / 报告 / 图表)
+├── sundynix-mcp-py/ 第 5 层 Python 算法型工具服务(沙箱执行 / 文档解析)
+├── sundynix-desktop/ 桌面端(Wails v3 + React 19)——主产品面
+├── sundynix-admin/ 官网 + 运维控制台(同一 SPA,go:embed 进 gateway)
+├── sundynix-web/ 薄 Web 面(租户自助:注册/组织/团队/账单)
+├── deploy/ 三机部署配置 + NATS 集群配置
+└── scripts/ 备份/恢复/RAG 评测
+```
+
+`go.work` 只纳入 4 个后端模块(shared / gateway / dispatcher / mcp-go)。
+**`sundynix-desktop` 刻意不入 workspace**(它是客户端,独立依赖),因此在该目录下跑 Go 命令必须 `GOWORK=off`。
+
+### 1.2 代码规模(实测)
+
+| 部分 | 源码 | 测试 |
+|---|---|---|
+| Go · gateway | 14,395 | 2,775 |
+| Go · dispatcher | 5,265 | 2,974 |
+| Go · mcp-go | 3,844 | 1,319 |
+| Go · shared | 2,173 | 681 |
+| Go · desktop | 697 | 271 |
+| TypeScript · desktop 前端 | 8,980 | 11 个前端测试文件 |
+| TypeScript · admin | 9,360 | (同上) |
+| TypeScript · web | 2,030 | (同上) |
+| Python · mcp-py | 520 | |
---
## 2. 分层架构总览
-```
-┌── 客户端层 ───────────────────────────────────────────────┐
-│ 桌面端 Wails(:5173,用户工作产品) 管理端 React(:5174,运维控制台) │
-└──────────────┬───────────────────────────┬────────────────┘
- │ HTTP / SSE │ HTTP
-┌── 接入层 ─────┴───────────────────────────┴────────────────┐
-│ gateway (gin, :8080) │
-│ JWT鉴权 · 路由 · 输入护栏 · 限流(按用户) · 审计 · SSE回流 · 导出 │
-└──────────────────────────┬─────────────────────────────────┘
- │
-┌── 总线层 ─────────────────┴─────────────────────────────────┐
-│ NATS + JetStream ——「万物总线」 │
-│ 任务 · 工具RPC · token流 · 执行轨迹 · 控制面广播 · 心跳 · 持久队列 │
-└──┬──────────────────────┬──────────────────────┬────────────┘
- │ │ │
-┌──┴────────┐ ┌────────┴────────┐ ┌────────┴────────┐
-│ dispatcher │ │ mcp-go │ │ mcp-py │
-│ 编排核心 │ │ Go I/O 工具服务 │ │ Python 算法工具 │
-│ Eino+harness│ │ RAG/记忆/历史/报告│ │ 沙箱/解析 │
-└──┬────────┘ └────────┬────────┘ └─────────────────┘
- │ LLM providers │
- │ (OpenAI 兼容) │
-┌──┴────────────────────────┴─────────────────────────────────┐
-│ 数据层:PostgreSQL(关系) · Redis(缓存/流/限流) · Milvus(向量) │
-│ Neo4j(图谱) · MinIO(对象/正文) · Jaeger(OTel 追踪) │
-└──────────────────────────────────────────────────────────────┘
+```mermaid
+flowchart TB
+ subgraph CLIENT["客户端层"]
+ DESK["sundynix-desktop
Wails v3 + React 19
编排画布 · JARVIS · 本地 runner"]
+ ADMIN["sundynix-admin
官网 / + 控制台 /admin"]
+ WEB["sundynix-web
租户自助柜台"]
+ end
+
+ subgraph GW["第 2 层 · gateway(唯一对外入口)"]
+ HTTP["HTTP API + SSE(gin)"]
+ WS["WebSocket
语音 /voice/stream
本地执行器 /local/runner"]
+ PLAT["平台工具提供方
platform_* / local_*"]
+ BG["后台常驻
配置控制面 · 持久消费者
入库 worker 池 · 3 个 ticker"]
+ end
+
+ BUS{{"NATS + JetStream
统一总线(8MB payload)"}}
+
+ subgraph WORK["执行层"]
+ DISP["第 4 层 · dispatcher
Eino compose 编排
LLM 双池 + failover + 熔断
harness 治理"]
+ MGO["第 5 层 · mcp-go
RAG 三路 / 记忆 / 报告 / 图表"]
+ MPY["第 5 层 · mcp-py
Docker 沙箱 / 文档解析"]
+ end
+
+ subgraph STORE["存储层"]
+ PG[("PostgreSQL 16
29 张表")]
+ RDS[("Redis 7")]
+ MLV[("Milvus 2.4.13")]
+ BLV[("Bleve 全文")]
+ NEO[("Neo4j 5")]
+ OSS[("MinIO")]
+ end
+
+ LLM["LLM Provider
OpenAI 兼容 · DeepSeek"]
+ VOLC["火山引擎
ASR / TTS"]
+
+ DESK --> HTTP
+ ADMIN --> HTTP
+ WEB --> HTTP
+ DESK <--> WS
+ HTTP --> BUS
+ WS --> VOLC
+ BG <--> BUS
+ PLAT <--> BUS
+ BUS <--> DISP
+ BUS <--> MGO
+ BUS <--> MPY
+ DISP --> LLM
+ HTTP --> PG
+ HTTP --> RDS
+ HTTP --> OSS
+ MGO --> MLV
+ MGO --> BLV
+ MGO --> NEO
+ MGO --> OSS
+ DISP --> BUS
```
-**分层原则**:服务间**互不 import**,只依赖 `shared/contract`(数据契约)+ `shared/bus`(NATS 封装)。任何跨服务通信都过 NATS。
+### 2.1 分层职责
----
-
-## 3. 组件详细设计
-
-### 3.1 gateway(接入层,gin)
-唯一对外 HTTP 入口,不含业务编排。职责:
-- **鉴权**:JWT 无状态(`owner` = 雪花 user.id);`RequireAuth`(登录)/ `RequireAdmin`(管理面,白名单 `ADMIN_USER_IDS`)。
-- **中间件链**(顺序):Recovery → OTel → RequestID → Observe(指标+日志) → CORS → **Auth** → **RateLimit(按 uid,未认证按 IP)** → **Guardrail(输入护栏+命中落库)**。
-- **DSL 拓扑校验**:`ParseAndAssemble` 前置拦截重复/空节点 id、悬挂边(防坏图进编排后被 compose 静默跳过)。
-- **SSE 回流**:`/tasks/:id/stream`(token 流)、`/tasks/:id/exec`(执行轨迹)、`/kb/ingest/:id/stream`(入库进度);优先读 Redis Stream(可断点续传),降级 live NATS。
-- **报告导出**:`/reports/:id/export?format=docx|md` → 经 NATS 调 mcp-go 现渲染 → `c.File` 流回。
-- **控制面 API**(`/admin/*`,RequireAdmin):模型 CRUD、计价、系统状态探活、系统聚合 overview、审计流、护栏事件流。
-- **审计**:`middleware.Audit(db)` 对变更类请求(POST/PUT/DELETE)best-effort 落库。
-
-### 3.2 dispatcher(编排核心)
-消费 NATS 任务,用 Eino 执行编排图 + harness 治理。详见 §5、§6。
-
-### 3.3 mcp-go(Go 工具服务)
-MCP 协议端点,订阅 `sundynix.tools.go.>`(queue group `mcp-go-workers`)。工具注册表是**单一事实源**(每工具声明 `cn/desc/agent/params/inject/handler`):
-- **RAG**:`kb_search`(三路混合) / `wiki_search` / `kb_graph` / `kb_ingest` / `kb_delete`(级联删)。三路 = Milvus 向量 + Bleve 全文(落盘) + Neo4j 图谱,RRF 融合 + rerank。
-- **记忆**:`memory_get/upsert/delete/list`(用户长期偏好,软删)。
-- **历史**:`history_get/append`(会话历史,Redis)。
-- **报告**:`report_store`(存源) / `report_render`(渲染 docx 落盘) / `report_export`(按需导出)。
-- **元工具**:`list_tools`(自省,供 dispatcher 动态发现) / `health`(Milvus/Neo4j 就绪)。
-
-### 3.4 mcp-py(Python 算法工具)
-订阅 `sundynix.tools.py.>`。承载 CPU 密集/生态依赖的算法:沙箱代码执行、文档解析等。**注:算法层目前为桩,调用链路已做真。**
-
-### 3.5 shared(跨服务共享库)
-- **bus**:NATS/JetStream 封装(Publish/Subscribe/Request-Reply、控制面广播、心跳、持久队列)。
-- **contract**:Task/ToolCall/ToolResult/ModelConfig/报告路径 等跨服务契约。
-- **prompts**:提示词注册表(内置默认 + 运行期覆盖)。
-- **secrets**:API Key AES-256-GCM 端到端加密(`SUNDYNIX_SECRET_KEY` 三服务须一致)。
-- **otel**:OTel 初始化(NATS 跨总线传播 traceparent)。
-
----
-
-## 4. NATS 总线设计(架构中枢)
-
-NATS 不只是消息队列,而是承载 **5 类通信**:
-
-| 类型 | 模式 | Subject / 机制 | 用途 |
+| 层 | 组件 | 职责 | 对外端口 |
|---|---|---|---|
-| 任务提交 | Publish | `sundynix.tasks.*` | gateway → dispatcher |
-| 工具调用 | Request-Reply | `sundynix.tools.go.` / `.py.` | dispatcher/gateway → mcp-*(queue group 负载均衡) |
-| token 流 | Publish/Sub | `sundynix.streams.` | dispatcher → gateway → SSE |
-| 执行轨迹 | Publish/Sub | exec 事件 | 运行·观测面板 |
-| 控制面广播 | Publish | 模型配置 / 提示词激活集 | 热下发 dispatcher/mcp-go(不重启) |
-| 心跳探活 | Request-Reply | `sundynix.health.dispatcher` 等 | 管理端服务状态 |
-| 持久队列 | JetStream | 入库工作队列(durable consumer) | 崩溃重投 / 幂等 / 背压 / AckWait 续租 |
+| 1 客户端 | desktop / admin / web | 交互与呈现 | — |
+| 2 接入 | **gateway** | 鉴权、租户/空间上下文、限流、护栏、审计、任务落库与发射、SSE/WS 回流、平台工具、后台常驻 | **8080**(生产 3000) |
+| 3 总线 | **NATS + JetStream** | 任务队列、回流、工具 RPC、控制面广播、KV checkpoint | 4222 |
+| 4 编排 | **dispatcher** | DSL→compose 图执行、ReAct 自主工具、多智能体、HITL 中断、评测纠偏 | 无(仅探针 8091) |
+| 5 工具 | **mcp-go / mcp-py** | I/O 型与算法型能力,队列组水平扩 | 无(仅探针 8092) |
-**⚠️ 运维要点**:单点 NATS(集群为 T3);本地开发禁止同时开 `devnats` 与 docker NATS(会脑裂)。
+**关键设计**:dispatcher 与 mcp-\* 都**没有对外端口**,只通过 NATS 通信 —— 攻击面收敛到 gateway 一个进程。
---
-## 5. 编排引擎设计(Eino compose)
+## 3. 服务详解
-**Eino 只在 dispatcher 里用,是编排引擎地基。**
+### 3.1 gateway —— 业务网关 / 统一接入层
-### 5.1 DSL → compose 图
-前端画布导出 `{version, nodes[{id,kind,label,config}], edges[{source,target,sourceHandle}]}`,dispatcher 编译为 Eino `compose.Graph`(`compose_compiler.go`),支持拓扑 + 连线 + 分支剪枝 + DAG 并行调度。**自研 graph.go 解释器已退役,单 compose 引擎。**
+`github.com/sundynix/sundynix-gateway` · Go 1.25.8 · 入口 `cmd/server/main.go`
-### 5.2 节点类型(执行器)
-- `input`:用户输入
-- `retriever`:RAG 检索(Eino Retriever 包 mcp-go `kb_search`)
-- `agent`:模型流式推理(拼消息 → token 流)
-- `tool`:调 MCP 工具(编排直连 NATS)
-- `branch`:条件路由(true/false 边标签 + **default/else 兜底** + 未匹配收口 END)
-- `map`:并行 fan-out(有界并发撰写;**子项失败传播 + 全失败置 fatalErr**)
-- `coordinator`:多智能体(专家=agent-as-tool,lead 分解→定制简报→并行派发→综合;**专家超时跳过**)
-- `approval`:HITL 人工审批中断(暂停→waiting→批准回 running / 拒绝 rejected,checkpoint 落盘)
-
-### 5.3 ReAct 自主调用(`agent:true` 工具)
-`agentTools()` 经 `list_tools` 动态发现 mcp 工具 → 包成 Eino `InvokableTool`(`mcpTool`)→ 模型 function-calling → ToolsNode 分发 → `InvokableRun` 转 NATS RPC。运行时注入 `user_id/session_id/kb`(不暴露给模型)。**加工具只改 mcp-go 注册表,dispatcher 零改动。**
-
-### 5.4 harness 治理层(「恒温器」)
-- **评测**:综合分(规则+LLM质量+RAG忠实度)+ 分级(ok/warn/poor),低分**自动纠偏**重生成。
-- **输入护栏**:注入检测(网关 Tier1)+ LLM 分类器(dispatcher Tier2 灰区裁决)。
-- **输出脱敏**:有状态流式脱敏(跨分片缓冲,杜绝密钥被切断漏检)。
-- **预算**:单任务 token 计量 + 封顶(默认 `TASK_TOKEN_BUDGET`,触顶中止全图)。
-- **熔断**:后端连续失败→断开→冷却半开探测→恢复(编排层门控 + **model 层每模型熔断**)。
-
----
-
-## 6. LLM 接入设计
-
-- **接入策略**:开发期接第三方在线 API(OpenAI 兼容),不拉本地 Ollama(但支持 Ollama/vLLM 占位 key)。
-- **LLM Pool**(`llm/pool.go`):经 Eino ChatModel 组件;配置热更新、降级桩(未配置时)。
-- **Failover 链**(`llm/failover.go`):active=主 + 其余=按序备用,串成 `ToolCallingChatModel`,compose/ReAct/Chat 全路径透明。**每模型带熔断器**:主持续失败→熔断→跳过主直连备用;冷却半开探测自动恢复;`WithTools` 重包共享 breakers。
-- **输出缓存**(`llm/cache.go`):包在 failover 外层,缓存 Generate(非流式),键=模型+工具+消息哈希。
-- **控制面热切换**:admin 改模型 → gateway 写 DB → NATS 广播 → dispatcher `SetConfig` 热重建 pool。
-
----
-
-## 7. 数据存储设计
-
-| 存储 | 角色 | 关键内容 |
-|---|---|---|
-| **PostgreSQL** | 关系事实源 | 用户/任务/评测/模型/计价/提示词/知识库元/文档/双链/编排/审计/护栏事件(表名 `sundynix_` 前缀,AutoMigrate) |
-| **Redis** | 缓存/流/限流 | token 用量计数、限流、会话历史、Redis Stream(token/exec 回放) |
-| **Milvus** | 向量库 | 文档向量(语义检索),键 file_id |
-| **Neo4j** | 图数据库 | 知识图谱三元组(实体 kb+name 共享,关系打 file_id) |
-| **MinIO** | 对象存储 | 文档正文(大文件正文一律落 MinIO) |
-| **Jaeger** | 追踪 | OTel span(节点/工具/LLM,NATS 跨总线传播) |
-
-**大文件入库生产化**:正文 MinIO + 切片 + 向量并发分批 + 图谱窗口化 + **JetStream 持久工作队列**(崩溃重投/幂等/背压),全 live 验证。
-
----
-
-## 8. 关键数据流
-
-**① 任务生命周期**:桌面端 POST DSL → gateway 解析+拓扑校验 → NATS `tasks.*` → dispatcher 编译 compose 图执行 → token 流 + 轨迹经 NATS→Redis Stream→SSE 回流 → FSM 状态机落库(submitted/running/done/failed/timeout/waiting/rejected)。
-
-**② 工具调用(两条路)**:
-- 编排直连:`o.tools.CallTool()` 直接 NATS→mcp-go(报告写文件走这条,**绕开 Eino**)。
-- Eino ReAct:模型 function-call → ToolsNode → `mcpTool.InvokableRun` → NATS→mcp-go。
-- 真正执行永远在 mcp-*;**Eino 把工具当黑盒(吃 JSON→吐字符串),不碰文件系统**。
-
-**③ 控制面热切换**:admin 改配置 → gateway 写 DB → NATS 广播激活集 → dispatcher/mcp-go `ApplyOverrides` 热更新。
-
-**④ 报告导出/写文件**:mcp-go `report_render` `os.WriteFile` 到 `SUNDYNIX_REPORTS_DIR`(默认 `$TMPDIR/sundynix-reports/{id}.docx`) → gateway `c.File(路径)` 流回 → 桌面端 Wails `SaveReportAs` 原生另存为落盘。**mcp-go 写、gateway 读须共享该目录。** PDF 目前靠前端打印(无后端 PDF 渲染)。
-
----
-
-## 9. 安全与治理
-
-- **鉴权**:JWT 无状态;owner 隔离(`owner_id`,单租户假设)。
-- **API Key 加密**:AES-256-GCM 端到端密文(PG + NATS 均密文)。
-- **输入护栏**:Tier1 正则/黑名单(网关,命中即拦 + 落库 `guardrail_event`)+ Tier2 LLM 分类(dispatcher 灰区)。
-- **审计**:敏感操作(改模型/密钥/激活 prompt/审批)经 `audit_log` 留痕,`/admin/audit` 可查。
-- **限流**:按登录用户(未认证按 IP),Redis 会话级。
-- **CORS**:开发 `*`,生产未显式配置则不放行任意源。
-
----
-
-## 10. 可观测性
-
-- **OTel 全链路**:节点/工具/LLM span,NATS 跨总线传播 traceparent,Jaeger(:16686)看瀑布。
-- **执行轨迹**:ExecEvent → 前端"运行·观测"面板(工具/专家调用、分支决策、审批等)。
-- **管理端**:`/status`(基建+服务探活+MCP 工具注册)、`/dashboard`(系统级 overview)、`/audit`(审计+安全事件)。
-- **缺口(待补)**:failover/熔断的**运行时态**只在日志、admin UI 不可见(T4.F 🔴)。
-
----
-
-## 11. 前端设计
-
-**双前端,严格独立、绝不合并**:
-- **桌面端**(Wails 原生窗口 + React):用户工作产品——画布编排/任务运行/知识库/报告/记忆。含 Wails Go 绑定(`app.go`)提供原生能力:另存为/系统应用打开/文件读写/通知。
-- **管理端**(React,Vite):运维控制台——模型/计价/数据源/提示词/服务状态/评测/租户/护栏/审计。已接 vitest。
-
----
-
-## 12. 部署形态与配置
-
-- **基建**:docker compose(PG/Redis/NATS/Milvus+etcd+MinIO/Neo4j/Jaeger)。
-- **应用**:Go 服务本地编译二进制 / `go run`;启动序 = gateway → dispatcher/mcp-go(mcp-go 必须在 Milvus 后)→ mcp-py。
-- **关键配置对齐**(多进程/多机须一致):`SUNDYNIX_SECRET_KEY`、`NATS_URL`、`POSTGRES_DSN`、`SUNDYNIX_REPORTS_DIR`;`ADMIN_USER_IDS`、`CORS_ALLOW_ORIGIN`(生产)、`TASK_TOKEN_BUDGET`、`RATE_LIMIT_PER_MIN` 等。
-
----
-
-## 13. 当前能力矩阵(干到哪一步)
-
-**✅ 已建(live 验证)**
-编排引擎(compose 单引擎,分支/并行/HITL)· 多智能体协调 · RAG 三路混合 + 评测台 · 大文件入库生产化(MinIO+JetStream)· 模型 failover + 每模型熔断 · 输出缓存 · 评测纠偏闭环 · 输入护栏 + 输出脱敏 + 预算 · prompt 版本化 + DB 控制面热切换 · API Key 加密 · OTel 全链路 · **审计可溯源(audit_log + guardrail_event + admin 审计页)** · **系统级 admin overview** · **DSL 拓扑校验** · admin 控制台(含 vitest)
-
-**🔶 进行中(T4.F 健壮性收口)**
-拆残骸/CORS/限流已做;**剩** KB 级联删事务化 · 关键 DB 写失败上浮 5xx · 审批 checkpoint 落盘重试 · 🔴模型健康/熔断态上 admin · 分页 · 配置化
-
-**⬜ 规划(未动)**
-T4.A 多租户/RBAC(无 tenant_id,L)· T4.C 真实计费(L)· T4.D AI 核心(记忆 Consolidate / prompt 灰度% / mcp-py 算法去桩 / 报告原生 PDF)· T3 生产硬化 ⏸(NATS 集群 / DB HA / K8s / TLS / 备份 DR,等真实流量)
-
----
-
-## 14. 技术栈
-
-| 层 | 技术 |
+| internal 包 | 职责 |
|---|---|
-| 编排/后端 | Go · gin · **Eino(cloudwego)** · NATS/JetStream · gorm |
-| LLM | OpenAI 兼容 API(DeepSeek 等)· eino-ext openai 组件 |
-| 工具服务 | Go(mcp-go) · Python(mcp-py) |
-| 前端 | React 19 · Vite · Tailwind · Wails(桌面端) · vitest |
-| 数据 | PostgreSQL · Redis · Milvus · Neo4j · MinIO |
-| 可观测 | OpenTelemetry · Jaeger · Prometheus 指标 |
+| `router` | Gin 装配:路由 + 中间件链 + CORS + admin SPA 回退 |
+| `handler` | 30+ 文件:task/agent/kb/report/space/tenant/billing/payment/voice/jarvis/prompt/admin/wechat/local_runner/platform_tools |
+| `middleware` | RequestID · Observe · Auth 系列 · TenantContext · SpaceContext · RateLimit · Guardrail · Audit · Require\*Role |
+| `store` | Postgres(GORM) + Redis 全部访问;迁移、租户作用域插件、leader 选主 |
+| `auth` | 无状态 JWT 签发/校验 + bcrypt |
+| `dsl` | 前端 JSON DSL → `contract.Task` 解析组装 + 拓扑校验 |
+| `guardrail` | 输入护栏 Tier1(归一化 + 注入正则 + env 黑名单) |
+| `payment` | 渠道抽象 + manager + 微信支付 |
+| `wechat` | 公众号带参二维码扫码登录 + 事件回调 |
+| `voice` | 火山 V3 流式 ASR/TTS 客户端 + 二进制帧协议 + 攒句器 |
+| `webui` | `go:embed` admin 产物打进二进制 |
+| `nats` | shared/bus 薄封装 |
+
+**技术栈**
+
+| 用途 | 库 | 版本 |
+|---|---|---|
+| Web 框架 | `gin-gonic/gin` | v1.12.0 |
+| SSE | `gin-contrib/sse` | v1.1.1 |
+| ORM | `gorm.io/gorm` + `driver/postgres` | v1.31.1 / v1.6.0 |
+| 缓存 | `redis/go-redis/v9` | v9.20.0 |
+| 鉴权 | `golang-jwt/jwt/v5` + `x/crypto`(bcrypt) | v5.3.1 / v0.53.0 |
+| ID | `bwmarrin/snowflake` | v0.3.0 |
+| WebSocket | `gorilla/websocket` | v1.5.3 |
+| 指标 | `prometheus/client_golang` | v1.23.2 |
+| 追踪 | `otelgin` + otel | v0.69.0 / v1.44.0 |
+| 支付 | `wechatpay-apiv3/wechatpay-go` | v0.2.21 |
+| 测试 DB | `glebarez/sqlite`(纯 Go 无 CGO,仅测试) | v1.11.0 |
+
+**后台常驻组件**
+
+| 组件 | 作用 |
+|---|---|
+| `ServeConfig` ×3 | 模型配置控制面应答(kind = chat / embedding / voice) |
+| `ServePrompts` | 激活 prompt 集下发 |
+| `ConsumeTaskStatus` | 任务状态落库 + **报告完成时主动语音播报** |
+| `ConsumeEval` / `ConsumeUsage` | 评测结果 upsert / 用量落库计费 |
+| `StartIngestWorkers` | JetStream 入库作业 worker 池(有界并发背压) |
+| `ServePlatformTools` | gateway 自己作为 MCP 工具提供方(见 §5.4) |
+| `StartReconcile` / `StartSubscriptionTicker` / `StartScheduleTicker` | 微信掉单补偿 / 订阅周期发放 / JARVIS 定时任务 |
+
+三个 ticker 均带 **PG advisory lock 选主**(`store/leader.go`),多副本下只有一个实例真正扫。
+
+**辅助 CLI**:`cmd/localsim`(模拟桌面本地执行器)、`cmd/voicesim`(免麦端到端语音链路模拟)、`cmd/voiceconfig`、`cmd/voicecheck`。
+
+### 3.2 dispatcher —— Agent 编排调度集群
+
+`github.com/sundynix/sundynix-dispatcher` · Go 1.25.8 · **无 HTTP 业务端口**
+
+| internal 包 | 职责 |
+|---|---|
+| `eino` | 编排引擎全部:orchestrator · compose_compiler/graph/callbacks · react_agent · coordinator · checkpoint · memory_extract · report |
+| `harness` | 治理五件套:budget · circuitbreaker · eval · jailbreak · output |
+| `llm` | pool(热更新) · failover(主备链) · cache(输出缓存) |
+| `dsl` | DSL 图 → 对话计划编译 |
+| `nats` | shared/bus 薄封装 |
+
+**技术栈**:`cloudwego/eino v0.9.12` + `eino-ext/components/model/openai v0.1.13`(OpenAI 兼容协议)、otel v1.44.0。
+另有 `cmd/loadtest`(阶梯并发压测器)。
+
+### 3.3 mcp-go —— Go I/O 型工具服务
+
+core NATS request-reply,订阅 `sundynix.tools.go.>`,队列组 `mcp-go-workers`,探针 `:8092`。
+
+**技术栈**:`blevesearch/bleve/v2 v2.4.2`(CJK 分词)、`milvus-sdk-go/v2 v2.4.1`、`neo4j-go-driver/v5 v5.24.0`、`go-redis/v9`、`gorm.io/gorm`。
+
+> ⚠️ `internal/office/unioffice.go` **名字有误导性**:并不引任何第三方 Office 库,而是用标准库 `archive/zip` + 内联 OOXML/WordprocessingML XML 手工拼 `.docx`。
+
+**工具注册表**(`internal/mcp/gateway.go` 的 `buildRegistry()` 是唯一事实源,dispatcher 经 `list_tools` 动态发现,加工具零改调度代码)
+
+暴露给自主 agent(10 个):`wiki_search`(知识检索) · `memory_get`→`recall_user_memory` · `memory_upsert`→`remember_user_fact` · `history_get` · `web_search` · `web_fetch` · `calculator` · `current_datetime` · `sql_query`(仅 SELECT/WITH) · `chart`(bar/line/pie)
+
+内部/流水线(13 个):`kb_ingest` · `kb_delete` · `kb_search` · `kb_graph` · `report_render` · `report_store` · `report_export` · `external_api`(带 SSRF 校验) · `memory_delete` · `memory_list` · `history_append` · `health` · `echo`
+
+### 3.4 mcp-py —— Python 算法型工具服务
+
+Python 3.11 · hatchling · **无 Web 框架**(纯 asyncio + `nats-py`),订阅 `sundynix.tools.py.>`,队列组 `mcp-py-workers`。
+
+依赖:`nats-py>=2.7.0` · `python-docx` · `openpyxl` · `pypdf` · `docker>=7.1.0`
+
+| 工具 | agent 暴露 | 说明 |
+|---|---|---|
+| `run_code` | ✅ | Docker 沙箱 256m/10s |
+| `secure_sandbox` | ❌ | 更严档 128m/5s |
+| `parse_document` | ❌ | txt/md/csv 直读;docx/xlsx/pdf 按扩展名路由 |
+| `echo` | ❌ | |
+
+两层防护:`sandbox.py` AST 静态守卫(拒 os/sys/subprocess/socket/ctypes/pickle 与 eval/exec/open)+ `interpreter.py` Docker 真隔离(禁网 / 非 root / 丢能力 / 限资源 / 一次性)。
+`mineru.py`(多模态解析)目前为桩。
+
+### 3.5 shared —— 共享库
+
+| 包 | 作用 |
+|---|---|
+| `bus` | NATS/JetStream 封装:流声明、任务收发、Token/Exec 回流、工具 RPC、5 条持久流、控制面、KV checkpoint;`trace.go` 把 W3C traceparent 塞进 NATS 头实现**跨总线链路串联**;消费侧解密 api_key |
+| `contract` | 三方共享契约:subject 常量、Task/ToolCall/ToolResult/各类 Event、入库 claim-check、报告对象键 |
+| `blob` | MinIO 封装;`cli==nil` 即降级回退本地盘,不阻断启动 |
+| `secrets` | **AES-256-GCM**,密钥由 `SUNDYNIX_SECRET_KEY` 经 SHA-256 派生;密文 `enc:1:`+base64url(nonce‖ct);无前缀原样返回(兼容旧明文) |
+| `otelx` | OTel 启动器(W3C 传播器 + OTLP/HTTP → Jaeger)+ 带 trace_id 的结构化 slog |
+| `prompts` | 受管提示词注册表(内置默认 + `PROMPTS_FILE` 覆盖 + 控制面热下发) |
+| `health` | 给无 HTTP 端口的服务起极小探针服务 |
+| `cmd/devnats` | 内嵌 nats-server,本地开发免装 |
---
-*本文档描述当前架构的「设计」;对该设计的优缺点评价、技术债与生产化建议见 `ARCHITECTURE_REVIEW.md`。*
+## 4. NATS 总线契约
+
+### 4.1 任务主链(JetStream 持久)
+
+| 流 / Subject | 值 | 用途 |
+|---|---|---|
+| `SUNDYNIX_TASKS` | `sundynix.tasks.` | 任务队列,消费者 `dispatchers`(队列组负载均衡) |
+
+### 4.2 回流(core NATS,即时不持久)
+
+| Subject | 用途 |
+|---|---|
+| `sundynix.streams.` | Token 流,结束用消息头 `X-Stream-End: 1` |
+| `sundynix.exec.` | 结构化执行节点事件(seq/node/kind/phase/label/ms) |
+| `sundynix.voice.event.` | JARVIS 语音事件(navigate / announce) |
+
+### 4.3 工具调用(request-reply + 队列组)
+
+| Subject | 队列组 | 提供方 |
+|---|---|---|
+| `sundynix.tools.go.` | `mcp-go-workers` | mcp-go |
+| `sundynix.tools.py.` | `mcp-py-workers` | mcp-py |
+| `sundynix.tools.platform.` | `platform-tools-workers` | **gateway 自己** |
+| `sundynix.local.exec.` | — | 桌面端 runner(无订阅 = 离线,明确报不可用) |
+
+### 4.4 回写(JetStream 持久 + 落库幂等 → at-least-once 重投安全)
+
+| 流 | 消费者 | Subject | 用途 |
+|---|---|---|---|
+| `SUNDYNIX_STATUS` | `gateway-status` | `sundynix.status.task` | 任务生命周期状态 |
+| `SUNDYNIX_USAGE` | `gateway-usage` | `sundynix.usage.task` | token 用量(计费凭据) |
+| `SUNDYNIX_EVAL` | `gateway-eval` | `sundynix.eval.task` | 自动评测结果 |
+| `SUNDYNIX_APPROVALS` | `approval-resumers` | `sundynix.approval.` | HITL 审批决定(抗离线) |
+| `SUNDYNIX_INGEST` | `ingest-workers` | `sundynix.ingest.` | 入库作业队列(claim-check:大文件先落 MinIO,消息只带 StageKey) |
+
+> ⚠️ 状态流 subject **必须在 `sundynix.tasks.>` 之外**,否则会被任务流捕获成「幽灵任务」自我放大。
+
+**KV**:`SUNDYNIX_CHECKPOINTS`(TTL 24h)—— 键 `task_id` 存 compose checkpoint,键 `pending:task_id` 存 resume 记录。
+
+### 4.5 控制面
+
+`sundynix.config..get` / `.updated`(kind = chat / embedding / voice)· `sundynix.prompts.get` / `.updated` · `sundynix.health.dispatcher`(心跳)。网关侧共用队列组 `gateway-workers`。
+
+### 4.6 Task.Meta 约定
+
+`user_id` · `tenant_id` · `session_id` · `safety_check` · `token_budget` · `model_profile`(=`voice`) · `intent`(=`report`) · `topic` · `kb`
+
+状态机:`submitted → running → done|failed|timeout`,HITL 分支 `waiting → running|rejected`。
+评测分级:`ok`(≥0.75) / `warn`(0.5~0.75) / `poor`(<0.5)。
+
+---
+
+## 5. 编排引擎
+
+### 5.1 执行路径
+
+`Orchestrator.Handle` → `executeGraph` → `runComposeGraph` → **`execComposeGraph`**(`internal/eino/compose_compiler.go`,唯一引擎):
+
+1. `dsl.Parse` + `dsl.Compile` → 建 `board`(黑板,进 compose 本地状态)
+2. 无图/空图 → 退化为 compose 单轮对话
+3. 建 `compose.Graph`:**边只传占位信号 `flowSignal`,真实数据全走黑板**(注册 no-op merge 支持 fan-in);DAG 触发让无依赖节点自动并行
+4. `branch` 节点走 `AddBranch`;`approval` 节点在有 checkpoint 后端时编译为 `approvalInterruptLambda`(`compose.Interrupt` 落盘并释放 goroutine)
+5. 编译失败 → 降级回自研 `graph.go`(已退役,保留作安全网)
+
+### 5.2 节点类型(12 种)
+
+| kind | 作用 |
+|---|---|
+| `input` | 输入/查询 |
+| `memory` | 记忆召回 |
+| `retriever` | RAG 检索 |
+| `tool` | 显式工具调用 |
+| `agent` | LLM 推理;`autonomous: true` → 走 **ReAct 自主工具循环** |
+| `coordinator` | 多智能体:agent-as-tool 派给专家 + 并行 fan-out + 综合 |
+| `aggregate` | 汇聚 |
+| `approval` | **HITL 人工审批**(中断落盘) |
+| `render` | 渲染(报告等) |
+| `map` | 并行 fan-out |
+| `output` | 输出 |
+| `branch` | 条件分支(建图阶段单独处理,支持 else/default 兜底) |
+
+### 5.3 ReAct 自主工具
+
+`react_agent.go` 用 Eino `react.NewAgent`,工具集经 `list_tools` 从**三个提供方**动态发现(mcp-go / mcp-py / gateway platform)。
+
+- `MaxStep` 默认 12(`REACT_MAX_STEP` 可调)
+- `StreamToolCallChecker` 扫描**整段流**判定工具调用(默认只看首片段,deepseek 等常先吐文本再给 tool call 会漏判)
+- `inject` 参数(user_id / session_id / task_id / kb / tenant_id)服务端运行时绑定,**不暴露给模型**
+- 工具可自报 `timeout_sec` 突破默认 3s(本地执行类要等用户点确认框)
+
+### 5.4 平台工具族(gateway 提供,11 个)
+
+平台操作的权威(提交关卡、归属校验、计费)都在 gateway,工具就长在权威所在地。
+
+| 工具 | 作用 |
+|---|---|
+| `platform_recent_tasks` / `platform_task_status` | 查任务列表 / 单任务状态与输出 |
+| `platform_gen_report` | 派发报告任务(**走 preflightCore 同一关卡**:预算/暂停/积分硬拦截) |
+| `platform_open_view` | 切换客户端界面(navigate 白名单) |
+| `platform_schedule_create` / `_list` / `_cancel` | 定时任务增删查 |
+| `local_list_dir` / `local_read_file` | 看/读用户电脑(只读) |
+| `local_write_file` / `local_exec` | 写文件 / 执行命令(三道闸,见 §8.3) |
+
+**安全铁律**:一律 `inject user_id` + 服务端归属校验(越权查他人任务一律回「不存在」,不泄露存在性);会烧钱的提交必须过 `preflightCore`。
+
+### 5.5 harness 治理层
+
+| 组件 | 作用 |
+|---|---|
+| `budget.go` | token 预算估算(CJK≈1 tok/字),触顶中止整图 |
+| `circuitbreaker.go` | 三态熔断(阈值 3 次连续失败 / 冷却 20s / 半开 1 次探测) |
+| `eval.go` | 规则 + LLM-as-judge 评测,异步 off 热路径;低分触发自动纠偏 |
+| `jailbreak.go` | Tier2 越狱分类(severity ≥0.7 才拦) |
+| `output.go` | 发射层逐片脱敏(sk-\* / AKIA\* / JWT / Bearer),跨分片不漏检 |
+
+---
+
+## 6. LLM 治理
+
+```
+cachingModel(输出缓存)
+ └─ failoverModel(主备链,每模型独立熔断器)
+ ├─ 主模型(active)
+ └─ 备用模型(其它 enabled chat 模型)
+```
+
+- **双池**:工作主力 `pool`(chat) + JARVIS 语音 `voicePool`(voice),语音池空则**透明回落**工作池
+- **热更新**:经 NATS 配置控制面(`SubscribeModelConfigUpdated` + 启动时 `FetchModelConfigWithRetry`)
+- **接入方式**:`eino-ext/openai`,OpenAI 兼容协议(当前用 DeepSeek 在线 API,不拉本地 Ollama)
+- 单次请求超时 120s;`LLM_FORCE_STUB=1` 走降级桩(压测用)
+- 暴露 `ModelHealth`(provider/model/role/state/fails)供 admin 展示
+- **已知局限**:Stream 仅在建流同步报错时切备,已开始回流 token 的中途失败不切
+- **输出缓存**:`respCache` TTL 60s(`LLM_CACHE_TTL_S`,0=关)、容量 512(`LLM_CACHE_MAX`),key = sha256
+
+**Prompt 版本化**:`shared/prompts` 内置默认 → `PROMPTS_FILE` 覆盖 → `sundynix_prompt` 表 + admin 热切换(含 diff 与撤销),不重编译即可改。
+Known key:`graph.extract` · `eval.quality` · `eval.refine` · `guard.jailbreak` · `coordinator.lead` · `memory.extract`
+
+---
+
+## 7. 数据存储
+
+### 7.1 中间件职责
+
+| 中间件 | 版本 | 用途 |
+|---|---|---|
+| NATS + JetStream | 2-alpine(max_payload 8MB) | 统一总线(见 §4) |
+| PostgreSQL | 16-alpine | 主业务库,29 张表 |
+| Redis | 7-alpine | 会话 / 限流 / 任务输出缓存(TTL 48h) / 扫码 ticket;有内存降级兜底 |
+| Milvus | v2.4.13 standalone | RAG 向量路 |
+| etcd | v3.5.14 | 仅 Milvus 元数据依赖 |
+| MinIO | RELEASE.2023-03-20 | 文档正文 blob、报告源/产物(bucket `sundynix-docs`)+ Milvus 段存储 |
+| Neo4j | 5-community | RAG 图谱路(三元组) |
+| Jaeger | all-in-one 1.60 | OTLP 收集 + trace UI |
+| **Bleve** | 进程内库(非容器) | RAG 全文路,scorch 落盘 `BLEVE_PATH` —— **唯一需要给 mcp-go 挂持久卷的原因** |
+
+### 7.2 数据表全清单(29 张)
+
+命名:`TablePrefix: sundynix_` + `SingularTable: true`。公共基类 `BaseModel` = 雪花字符串 id + created/updated + 软删。
+
+| # | 模型 | 表 | 职责 |
+|---|---|---|---|
+| 1 | `User` | `sundynix_user` | 平台用户 |
+| 2 | `Task` | `sundynix_task` | 一次提交的编排任务(DSL);业务 id `task_xxx` 单列供 NATS subject |
+| 3 | `Eval` | `sundynix_eval` | 自动评测结果,按 task_id upsert |
+| 4 | `LLMModel` | `sundynix_model` | 模型后端配置,每 kind 同时刻仅一条 Active |
+| 5 | `KB` | `sundynix_kb` | 知识库,`(space_id,name)` 唯一,分区键 `space_id/name` |
+| 6 | `Doc` | `sundynix_doc` | 入库文档主表(Obsidian 式文库) |
+| 7 | `Agent` | `sundynix_agent` | 编排定义,`(space_id,name)` 唯一 |
+| 8 | `DocLink` | `sundynix_doc_link` | `[[双链]]` 索引,供反链/关系图 |
+| 9 | `Pricing` | `sundynix_pricing` | 模型计价(每 1K token 输入/输出单价) |
+| 10 | `Prompt` | `sundynix_prompt` | 受管提示词版本,`(key,version)` 唯一 |
+| 11 | `AuditLog` | `sundynix_audit_log` | 敏感操作留痕,只增不改 |
+| 12 | `GuardrailEvent` | `sundynix_guardrail_event` | 输入护栏命中事件 |
+| 13 | `Tenant` | `sundynix_tenant` | 租户(计费/隔离单位),含物化余额列 |
+| 14 | `TenantMember` | `sundynix_tenant_member` | 用户↔租户成员关系 + 角色 |
+| 15 | `TenantInvite` | `sundynix_tenant_invite` | 可复用邀请码(扫码入组) |
+| 16 | `Space` | `sundynix_space` | 共享工作区(资源容器) |
+| 17 | `SpaceMember` | `sundynix_space_member` | 空间成员 + 空间内角色 |
+| 18 | `UsageEvent` | `sundynix_usage_event` | 用量明细,task_id 唯一 → 幂等 |
+| 19 | `CreditLedger` | `sundynix_credit_ledger` | 积分账本(append-only),余额 = SUM |
+| 20 | `UsageRollup` | `sundynix_usage_rollup` | 用量按租户/天聚合快照 |
+| 21 | `Setting` | `sundynix_setting` | 平台级键值配置 |
+| 22 | `CreditPack` | `sundynix_credit_pack` | 积分包商品 |
+| 23 | `PaymentOrder` | `sundynix_payment_order` | 充值订单(兑换码也写一行) |
+| 24 | `RedeemCode` | `sundynix_redeem_code` | 兑换码 |
+| 25 | `SubscriptionPlan` | `sundynix_sub_plan` | 订阅套餐 |
+| 26 | `Subscription` | `sundynix_subscription` | 已购订阅(到期即 expired,不自动续) |
+| 27 | `UserJarvis` | `sundynix_user_jarvis` | 每用户 JARVIS(名字/人设/自带火山 key,密文入库) |
+| 28 | `Schedule` | `sundynix_schedule` | 定时任务 |
+| 29 | `SchemaMigration` | `sundynix_schema_migration` | 已应用的版本化迁移记录 |
+
+### 7.3 迁移机制
+
+整段迁移在 **PG advisory lock**(key `20260721`,60s 超时兜底)内串行:
+`legacy(默认关) → AutoMigrate(29 模型) → 版本化 schemaSteps`
+
+只有 AutoMigrate 失败才返回 error;版本化步骤失败只记日志下次重试。
+
+**4 个版本化步骤**:账本 grant/adjust 的**部分唯一索引**(支付入账与退款的幂等闸)· 回填租户物化余额 · 微信 openid 唯一索引。
+部分唯一索引不写在 struct tag 里 —— AutoMigrate 早于回填会撞车,必须回填后显式建。
+
+破坏性 legacy 迁移需 `ALLOW_LEGACY_SCHEMA_MIGRATION=1` 显式开启(雪花 id 改造、双链改按 Doc.ID 关联)。
+
+---
+
+## 8. 关键链路
+
+### 8.1 任务提交 → 编排 → 回流
+
+```mermaid
+sequenceDiagram
+ participant C as 桌面端
+ participant G as gateway
+ participant N as NATS
+ participant D as dispatcher
+ participant M as mcp-go
+ participant L as LLM
+
+ C->>G: POST /tasks (DSL)
+ G->>G: 鉴权 → 租户/空间上下文 → 限流 → 护栏
+ G->>G: preflight:预算/暂停/计费租户/积分硬拦截
+ G->>G: launch:落库 + 起录像器
+ G->>N: publish sundynix.tasks (JetStream)
+ G-->>C: 202 task_id
+ C->>G: GET /tasks/:id/stream (SSE, token 走 query)
+
+ N->>D: 消费任务
+ D->>D: DSL 编译为 compose.Graph
+ loop ReAct 循环
+ D->>L: 推理(failover + 熔断 + 缓存)
+ L-->>D: tool_call
+ D->>N: request sundynix.tools.go
+ N->>M: 队列组分发
+ M-->>D: ToolResult
+ end
+ D-->>N: Token 流 sundynix.streams
+ N-->>G: 订阅回流
+ G-->>C: SSE 逐字推送
+ D->>N: status / usage / eval(JetStream 持久)
+ N->>G: 幂等落库
+```
+
+### 8.2 语音 JARVIS 全双工
+
+```mermaid
+sequenceDiagram
+ participant U as 用户
+ participant C as 桌面端
+ participant G as gateway
+ participant V as 火山 ASR/TTS
+ participant D as dispatcher
+
+ U->>C: 按住空格说话(PTT)
+ C->>G: WS 二进制帧:PCM 16k 上行
+ G->>V: 流式 ASR(X-Api-Key 鉴权)
+ V-->>G: 转写(部分/最终)
+ G-->>C: transcript
+ U->>C: 松开 → end
+ G->>G: trySubmit:转写 → 组 DSL → 同一提交关卡
+ G-->>C: task_id
+ G->>D: 提交任务(model_profile=voice → 走快模型)
+ D-->>G: Token 流
+ G-->>C: reply(打字机,早于音频)
+ G->>V: 攒句 → 双向流 TTS
+ V-->>G: PCM 24k
+ G-->>C: speaking + 音频帧 → tts_end
+ C->>U: 无缝播放
+```
+
+**要点**
+- ASR 与 TTS 是**不同帧族**(ASR 简帧无事件号;TTS V3 事件族带 event/session/gzip)
+- 下行**先订阅 token 流再建 TTS 会话** —— core NATS 无持久,订阅晚于产出会丢开头
+- 客户端播放按 `nextStart` 预约到未来时刻,收到 `tts_end` 时**不能立即停**(合成远快于语速,停了只剩前几个字)
+
+### 8.3 本地执行(JARVIS 操作用户电脑)
+
+```mermaid
+sequenceDiagram
+ participant D as dispatcher
+ participant G as gateway
+ participant R as 桌面 Go host
+ participant U as 用户
+
+ Note over R,G: 登录后注册:WS /local/runner
+ R->>G: 上线(携带授权目录白名单)
+ G->>G: 队列组订阅 sundynix.local.exec
+
+ D->>G: 调 local_exec(timeout_sec=160)
+ G->>R: WS 转发 tool + args
+ R->>R: 闸一:独立开关校验
+ R->>R: 闸二:硬黑名单(14 条正则,命中不弹框直接拒)
+ R->>U: 闸三:原生确认框(默认按钮=拒绝,60s 无应答即拒)
+ U-->>R: 允许 / 本次会话都允许
+ R->>R: 沙箱内执行(cwd 锁授权目录,60s 超时,输出 16KB 截断)
+ R-->>G: 结果
+ G-->>D: ToolResult
+```
+
+**超时链必须外松内紧**:dispatcher 160s > gateway 150s > runner 转发 140s > 桌面端(审批 60s + 执行 60s)。
+任一层比内层短,用户还在看确认框就会被判超时。
+
+---
+
+## 9. 功能实现状态
+
+图例:**✅ 已完成(live 验证)** · **🟡 部分** · **❌ 未做**
+
+### 9.1 多租户 / 空间 / RBAC
+
+| 功能 | 状态 |
+|---|---|
+| Tenant/TenantMember + 注册自动建默认租户 + 存量回填 | ✅ |
+| **gorm 租户隔离插件**(查询/更新/删除自动加 tenant_id,创建自动填) | ✅ |
+| 租户角色 RBAC(owner/admin/member/viewer)+ 路由级校验 | ✅ |
+| 租户邀请码(二维码扫码入组) | ✅ |
+| Space 共享工作区(KB/Agent 按空间共享 + 空间角色 + 全员空间) | ✅ |
+| 用户 role 字段 + 角色表(把 `RequireAdmin` 从白名单升级为角色校验) | ❌ |
+| 用户管理接口(列举/禁用/改角色) | ❌ |
+
+### 9.2 计量 / 计费 / 支付
+
+| 功能 | 状态 |
+|---|---|
+| 计价配置 + usage_event 计量 + credit_ledger 账本 + daily rollup | ✅ |
+| 余额硬拦截(`CREDIT_ENFORCE`) | ✅ |
+| 支付渠道抽象 + 微信 Native(**真环境实测通过**) | ✅ |
+| 兑换码 / 人工核销 | ✅ |
+| 对账 + 退款(adjust 负分录 + 回退余额 + 审计) | ✅ |
+| 订阅套餐(周期发放 + 到期失效) | ✅ |
+| 发票 / Stripe | ❌ |
+
+### 9.3 知识库 / RAG
+
+| 功能 | 状态 |
+|---|---|
+| **三路混合检索**(Bleve 全文 + Milvus 向量 + Neo4j 图谱,RRF k=60 融合 + rerank) | ✅ |
+| 中文分词修复(CJK bigram) | ✅ |
+| 离线检索评测(recall@k / MRR,hybrid vs 单路) | ✅ |
+| 大文件生产化(MinIO 正文 + 并发 embed + 窗口化图谱 + JetStream 持久队列,kill -9 续跑验证) | ✅ |
+| KB 级联删事务化(三库 + MinIO 先删、PG 最后)+ MinIO 孤儿 GC | ✅ |
+| Obsidian 式文库(Markdown + 双链 + 反链 + 关系图) | ✅ |
+| 检索持久化治理 / 列表分页 | 🟡 |
+| 多模态解析(MinerU/PaddleOCR) | 🟡 骨架,`mineru.py` 为桩 |
+
+### 9.4 报告
+
+| 功能 | 状态 |
+|---|---|
+| 报告编排(规划 → 分章并行 → 汇聚 → 存源) | ✅ |
+| Word(.docx) 渲染(自建零依赖 OOXML) | ✅ |
+| Markdown 导出 | ✅ |
+| PDF 导出 | 🟡 走 webview 打印;后端原生 PDF 未做 |
+| 分章 map 错误传播与汇总 | ✅ |
+
+### 9.5 记忆
+
+| 功能 | 状态 |
+|---|---|
+| memory CRUD + Profile 表 | ✅ |
+| P1 异步攒批 Consolidate(每 3 轮 LLM 对账 ADD/UPDATE/DELETE/NOOP + 软删) | ✅ |
+| P2 Score(Recency + Importance) 排序 + 衰减 + top30 截断 | ✅ |
+| P3 Relevance(语义相关性) | ✅ |
+| 会话历史 history_get/append | ✅ |
+
+### 9.6 编排引擎
+
+| 功能 | 状态 |
+|---|---|
+| Eino Phase A/B/C/D 全部(组件 → ReAct → compose 全图 → FSM) | ✅ |
+| compose 为唯一引擎(`graph.go` 已退役作降级网) | ✅ |
+| HITL 人工审批中断(checkpoint 落盘 + NATS 决定回传 + 抗离线) | ✅ |
+| 多智能体 coordinator(agent-as-tool + 定制 brief + 并行 fan-out + 专家超时) | ✅ |
+| Branch else/default 兜底 · DSL 拓扑校验 · 工具动态发现 | ✅ |
+| handoff / adk 可中断多智能体 | ❌ |
+| 编译图缓存 | ❌ 判定为 premature(实测编译 ~13µs) |
+| 审批 checkpoint 落盘失败重试(现只 log → 任务永卡 waiting) | ❌ |
+
+### 9.7 模型治理
+
+| 功能 | 状态 |
+|---|---|
+| 模型路由 + Fallback + 每模型三态熔断 | ✅ |
+| 模型健康/熔断态 surface 到 admin | ✅ |
+| 输出缓存 | ✅ |
+| Prompt 版本化 v1(注册表)+ v2(DB 热切换 + diff + 撤销) | ✅ |
+| 工作模型与 JARVIS 语音模型分离 + 用量按实际模型计量 | ✅ |
+| Prompt 灰度 % A/B | ❌ |
+
+### 9.8 评测 / 护栏
+
+| 功能 | 状态 |
+|---|---|
+| 自动化评测(规则 + LLM 裁判,异步 off 热路径) | ✅ |
+| 裁判校准 + 低分自动纠偏闭环(live 真触发) | ✅ |
+| 输入护栏(注入检测 + 归一化 + 超大体拦截)+ 事件落库 | ✅ |
+| 输出护栏(跨分片密钥脱敏) | ✅ |
+| HITL 审批决定明细(理由)落库 | ❌ 现仅 who/when/status |
+| 前端评测质量面板 | ❌ 后端 `/tasks/:id/eval` 已有 |
+
+### 9.9 语音 / JARVIS 中枢
+
+| 功能 | 状态 |
+|---|---|
+| 火山 ASR + 双向流 TTS 全双工(新版 API Key 鉴权) | ✅ |
+| 语音触发任务(复用同一提交关卡) | ✅ |
+| PTT 按住说话 + 打断 + 连续对话 + 打字机文本流 | ✅ |
+| 每用户 JARVIS(名字/人设/自带豆包配置回落,语音不串主记忆) | ✅ |
+| 全屏钢铁侠 HUD(接真实音频电平) | ✅ |
+| **P1 平台工具族**(查任务/派报告,含越权拒绝与积分硬拦截验证) | ✅ |
+| **P2 动作通道**(语音让界面切页,三层白名单) | ✅ |
+| **P3 主动播报**(任务终态主动开口,正朗读则排队不抢麦) | ✅ |
+| 声纹 / 唤醒词 / 音色克隆 / 多语种 / ASR-TTS failover | ❌ 本期不做 |
+| P5 常驻 companion session | ❌ 暂缓(现靠 session history 串联已够用) |
+
+### 9.10 本地执行
+
+| 功能 | 状态 |
+|---|---|
+| **只读**:`local_list_dir` / `local_read_file` + runner 注册 + 沙箱(逃逸单测全拦) | ✅ |
+| **能动的手**:`local_write_file` / `local_exec` + 三道闸(独立开关 + 14 条黑名单 + 原生审批框) | ✅ |
+| 多目录白名单沙箱 + 空 path 自发现授权目录 | ✅ |
+| 离线优雅降级(runner 不在线明确报不可用,不挂起) | ✅ |
+| ToolPolicy 服务端策略下推 | 🟡 已有审批框 + 黑名单,下推未做 |
+| **档 B**:agent 循环下沉客户端(内环不过网) | ❌ 有决策门,未做 |
+| gateway LLM 代理端点(档 B 的地基) | ❌ |
+
+### 9.11 定时任务
+
+| 功能 | 状态 |
+|---|---|
+| `sundynix_schedule` + leader 锁 ticker(30s) + create/list/cancel 工具 | ✅ |
+| 存自然语言指令,到点走同一关卡执行 + 主动播报 | ✅ |
+| 先推进后提交防重复烧钱;停机错过的**不补跑** | ✅ |
+
+### 9.12 可观测 / 运维
+
+| 功能 | 状态 |
+|---|---|
+| Prometheus `/metrics`(路由模板低基数)+ 结构化日志 + X-Request-ID | ✅ |
+| `/healthz` `/readyz` 探针 + 依赖聚合健康 | ✅ |
+| **OTel 全链路**(otelgin + 跨 NATS traceparent 传播 → Jaeger) | ✅ |
+| admin 观测面(overview/status/tasks/spaces/usage/evals/datasources/orders/审计/护栏) | ✅ |
+| 检索试验台(跨租户 + 单路 mode 对比) | ✅ |
+| panic 进 trace span · TTFT/token-s 指标 | ❌ |
+| K8s / DB HA / TLS / DR 演练 | ❌(**例外:NATS 集群已落地**) |
+
+### 9.13 客户端
+
+| 端 | 状态 |
+|---|---|
+| desktop(编排画布 · ⌘K · SSE 轨迹 · 文库 · 知识图谱 · 记忆面板 · JARVIS HUD · 本地 runner · 服务器地址运行时可配) | ✅ |
+| admin(官网 + 控制台,go:embed 进 gateway) | ✅ |
+| web(租户自助:注册/组织/团队/账单) | ✅ |
+| 前端测试 | 🟡 11 个测试文件,集中在 lib 纯函数;视图层基本不测 |
+
+### 9.14 ⚠️ 已知的文档记账偏差
+
+以下 4 处**文档与代码不符,一律以代码为准**:
+
+1. `PROGRESS.md` 停在 2026-06-19,其中「计费未做」「多租户未做」「Relevance 待 P3」均已被后续代码推翻。
+2. `DEPTH_ROADMAP.md` 进度表写「T4 后端做实 0/6 组」,但正文里 T4.A/B/E 大量条目已勾 ✅。
+3. `DEPTH_ROADMAP.md` Tier 3 写「NATS 集群未做」,实际三节点集群已在 128 落地。
+4. `PAYMENT_DESIGN.md` 标题写「不做订阅」,但订阅套餐全套(表 + ticker + admin 页)已实现。
+
+---
+
+## 10. 安全与治理
+
+### 10.1 中间件链(顺序有意义)
+
+```
+Recovery → otelgin → RequestID → Observe → cors → Auth → TenantContext → SpaceContext → RateLimit → Guardrail
+```
+
+**Auth 必须前置于 RateLimit** —— 否则无法按用户限流(企业网多人共享出口 IP 会互相拖累)。
+
+### 10.2 鉴权
+
+- **JWT 无状态**(`internal/auth`),owner = 雪花 user.id;生产默认密钥 fail-fast
+- `Auth()` 非阻断解析 → `RequireAuth()` / `RequireAdmin()`(当前为 `ADMIN_USER_IDS` 白名单)
+- **`AuthFromHeaderOrQuery()`**:WS 与 SSE 带不了 Bearer 头,走 `?token=` —— 用于 `/tasks/:id/stream`、`/tasks/:id/exec`、`/kb/ingest/:id/stream`、`/reports/:id/export`、`/voice/stream`、`/local/runner`
+- 注册/登录各带 10/min 限流;微信公众号扫码登录独立通道
+- **支付回调例外**:`/billing/callback/:channel` 无 Bearer,渠道验签是唯一的门
+
+### 10.3 密钥加密
+
+`shared/secrets`:**AES-256-GCM**,密钥由 `SUNDYNIX_SECRET_KEY` 经 SHA-256 派生 32 字节;密文格式 `enc:1:` + base64url(nonce‖ciphertext),带版本前缀便于轮换。
+
+**全链路**:gateway 保存时 Encrypt 落 PG → 密文原样过 NATS → dispatcher/mcp-go 在 bus 层 Decrypt。**api_key 在磁盘与线缆上都非明文**,仅构建 LLM 客户端时内存短暂还原。三服务的 `SUNDYNIX_SECRET_KEY` 必须一致。
+
+微信支付商户私钥不落库不进镜像 —— 宿主目录只读挂载。
+
+### 10.4 租户隔离
+
+`store/tenant_scope.go`:`tenantScopedMarker` 空接口(小写方法,只有本包模型能标记)+ 4 个 gorm callback(query/update/delete 前自动加 `tenant_id = ?`,create 前自动填)。
+
+**两个必须记住的旁路**:系统级读(admin 聚合)与跨租户写(对账)都要 `WithoutTenant(ctx)` —— 漏了会出回归或对账崩。
+
+### 10.5 限流与审计
+
+- **限流**:Redis 为主后端 + **进程内固定窗口 fail-safe 兜底**(Redis 挂时不再 fail-open,改宽松本地限流);已认证按 uid、未认证按 IP
+- **审计**:`Audit(db)` 只审计变更类(POST/PUT/DELETE/PATCH),best-effort 不拖垮主流程;挂在整个 `/admin` 组、prompt 激活/撤销、HITL 审批、租户成员变更、充值兑换
+- **护栏事件**:命中落 `GuardrailEvent`(actor/kind/reason/signals/path/ip)→ admin 审计页
+
+---
+
+## 11. 客户端形态
+
+**三个独立产品面,绝不合并**:
+
+| 端 | 定位 | 技术栈 | dev 端口 | 路由 |
+|---|---|---|---|---|
+| desktop | **用户工作产品** | Wails v3.0.0-alpha2.117 + React 19 + TS 5.6 + Tailwind 3.4 + React Flow 12 | 9245 (wails3) / 5173 (纯 vite) | 无路由,`useState` |
+| admin | 官网(`/`) + 平台超管控制塔(`/admin`) | React 19 + react-router-dom 7 | 5174 | **BrowserRouter** |
+| web | 租户客户自助柜台 | React 19 + react-router-dom 7 | 5175 | **HashRouter**(纯静态托管即可深链) |
+
+**desktop 页面**(`ViewKey`):`home` 工作台 · `studio` 编排 · `kb` 知识库 · `runs` 运行 · `report` 报告 · `memory` 记忆 · `usage` 用量
+
+**admin 页面**(17 条路由):仪表盘 / 服务状态 / 任务观测 / 自动评测 / 审计安全 / 模型配置 / 登录设置 / 语音设置 / 数据源RAG / 提示词 / 支付(配置·订阅·订单对账) / 租户用户 / 微信用户 / 空间 / 安全护栏
+
+三端共用**自建 UI 组件**(`src/ui/`:Badge/Button/Card/Dialog/Input/Table/Tabs/Toast + cn),**未引任何组件库**。
+测试统一 Vitest 4 + jsdom + Testing Library。
+
+---
+
+## 12. 部署拓扑
+
+### 12.1 三机内网生产
+
+```mermaid
+flowchart LR
+ USER["用户桌面端"]
+ FRP["frp 映射"]
+
+ subgraph M132["192.168.100.132 · 应用机"]
+ GW["gateway 3000→8080
内嵌 admin UI"]
+ DP["dispatcher"]
+ MG["mcp-go"]
+ MP["mcp-py"]
+ end
+
+ subgraph M128["192.168.100.128 · 基建机 + CI runner"]
+ N1["NATS 三节点集群
4222/4223/4224
REPLICAS=3"]
+ PG2[("PostgreSQL")]
+ RD[("Redis")]
+ ML[("Milvus + etcd")]
+ NJ[("Neo4j")]
+ JG["Jaeger"]
+ end
+
+ M126[("192.168.100.126
业务 MinIO
bucket sundynix-docs")]
+ TX["162.14.122.200
微信 token 中控
静态 IP"]
+
+ USER --> FRP
+ FRP --> GW
+ GW --> N1
+ DP --> N1
+ MG --> N1
+ MP --> N1
+ GW --> PG2
+ GW --> RD
+ GW --> M126
+ MG --> ML
+ MG --> NJ
+ MG --> M126
+ GW --> JG
+ DP --> JG
+ GW --> TX
+```
+
+**要点**
+- **对外只暴露 132:3000**(gateway:API + admin UI + 语音 WS + 本地 runner WS),其余全部内网
+- NATS 三节点 `cluster.name: sundynix-cluster`,routes 互指 6222;`NATS_STREAM_REPLICAS=3` 走 Raft quorum;三节点 `max_payload: 8MB` 必须一致
+- 128 上的 Redis/Milvus/NATS **无认证**,靠防火墙只放行 132/126 网段
+- 132 只读挂载两个宿主目录:微信支付商户私钥、微信域名校验文件(不进镜像、不进 git)
+- 备份 `scripts/backup.sh`(PG/Neo4j/Milvus/MinIO 卷),建议 cron 每日异机存档
+
+### 12.2 单机一体化
+
+`docker-compose.prod.yml` 一条命令拉起应用 4 服务 + 全套基建(要求 Docker 24+/Compose v2、~8GB 内存)。
+基建端口**一律不对宿主暴露**,只留 gateway 与可选 Jaeger UI。密钥用 YAML 锚点 `${SUNDYNIX_SECRET_KEY:?}` 强制 .env 必填。
+
+### 12.3 密钥模型
+
+| 类别 | 内容 | 存放 |
+|---|---|---|
+| 引导密钥 / 基建凭据 | `SUNDYNIX_SECRET_KEY` · `JWT_SECRET` · PG/Neo4j/MinIO 密码 | `.env`,部署时填一次 |
+| 业务模型 key | LLM api_key · 语音 key · 支付配置 | **不进 .env**,登录 admin 配,AES 加密存 PG |
+
+丢失主密钥 = 已存业务 key 全部失效。
+首次管理员:注册第一个账号 → 取 user id → 填 `ADMIN_USER_IDS` → 重启 gateway。
+
+---
+
+## 13. CI / CD
+
+### 13.1 GitHub Actions(质量门,push main + PR)
+
+| Job | 内容 | 红门 |
+|---|---|---|
+| `go` | 4 模块 `build + vet + test -race` | ✅ 一票否决 |
+| `lint` | golangci-lint × 4 模块,`only-new-issues`(存量约 42 处不拦) | ✅ 仅新问题 |
+| `security` | `govulncheck`(advisory 不阻断)+ **`gitleaks` 扫提交历史(命中即失败)** | 部分 |
+| `web` | 三前端 `npm ci` + `tsc --noEmit` + `vitest` | ✅ |
+| `desktop` | macOS runner,`GOWORK=off`,先出前端产物供 go:embed | ✅ |
+| `py` | Python 3.11 pytest(含沙箱守卫测试) | ✅ |
+
+Go 1.25 / Node 20。所有 job 带 `if: !contains(github.server_url, 'sundynix.cn')` 避免内网 Gitea 误跑。
+
+### 13.2 Gitea Actions(内网真实 CD)
+
+push main → 128 runner:**不用 `actions/checkout`**(内网连不上 github.com,改 `git init + fetch --depth 1`)→ 构建 4 镜像 → `docker save | gzip` scp 到 132 → `docker load` + `up -d --no-build` → **健康检查门**(循环 20 次 curl `/healthz`,失败打日志并 exit 1)。
+
+132 上的 `.env` 手工预放、**部署绝不覆盖**。
+
+> ⚠️ **CD 无任何测试门** —— 测试只在 GitHub 侧跑,内网推送直接部署。
+
+### 13.3 Release
+
+tag `v*` → wails3 构建 macOS universal(lipo 合并)+ Windows amd64 → GitHub Release。旧版 App 启动查 `/releases/latest` 提示更新。
+
+---
+
+## 14. 技术栈总表
+
+| 领域 | 选型 |
+|---|---|
+| 后端语言 | Go 1.25(4 模块 workspace)+ Python 3.11(算法工具) |
+| Web 框架 | Gin v1.12.0 |
+| 编排引擎 | **CloudWeGo Eino v0.9.12** + eino-ext/openai |
+| 消息总线 | NATS 2 + JetStream(持久流 + KV) |
+| 主库 | PostgreSQL 16 + GORM v1.31.1(雪花 id + 软删 + 租户插件) |
+| 缓存 | Redis 7(+ 进程内降级) |
+| 向量 | Milvus v2.4.13 |
+| 全文 | Bleve v2.4.2(进程内,CJK bigram) |
+| 图谱 | Neo4j 5-community |
+| 对象存储 | MinIO(minio-go v7.2.0) |
+| LLM | OpenAI 兼容协议(DeepSeek 在线 API) |
+| 语音 | 火山引擎豆包 · 流式 ASR + 双向流 TTS v3 |
+| 可观测 | Prometheus + OpenTelemetry v1.44 + Jaeger 1.60 |
+| 桌面端 | Wails v3.0.0-alpha2.117(Go host + WKWebView) |
+| 前端 | React 19 + TypeScript 5.6 + Vite 5 + Tailwind 3.4 + React Flow 12 |
+| 前端测试 | Vitest 4 + jsdom + Testing Library |
+| 支付 | 微信支付 APIv3(Native 扫码) |
+| 密钥 | AES-256-GCM(`enc:1:` 版本化密文) |
+
+---
+
+## 15. 已知缺口
+
+按优先级归类,均为**明确未做**而非遗漏:
+
+**架构演进**
+- 本地 agent 档 B(循环下沉客户端,内环不过网)+ 其地基 gateway LLM 代理端点
+- ToolPolicy 服务端策略下推
+- JARVIS 常驻 companion session(现靠 session history 串联)
+
+**治理补全**
+- 用户 role 字段与角色表(`RequireAdmin` 仍是 env 白名单)
+- HITL 审批决定理由落库
+- 审批 checkpoint 落盘失败重试(现只 log,任务会永卡 waiting)
+- 预算硬顶兜底(budget ≤0 即无限)
+
+**生产硬化(Tier 3,等真实流量)**
+- DB HA · K8s 编排 · TLS 终止 · DR 演练 · 备份自动化
+- panic 进 trace span · TTFT/token-s 细粒度指标
+
+**产品功能**
+- 报告后端原生 PDF(现走 webview 打印)
+- 多模态文档解析去桩(MinerU/PaddleOCR)
+- Prompt 灰度 A/B
+- 前端评测质量面板(后端接口已有)
+- 语音:唤醒词 / 声纹 / 音色克隆 / ASR-TTS failover
+
+**文档债**
+- `architecture.md`(小写)是历史重复文件,内容早于本文,建议删除或改为指向本文的跳转
+- `PROGRESS.md` / `DEPTH_ROADMAP.md` 汇总表需按 §9.14 校正