docs: complete Chinese project documentation

This commit is contained in:
hailin
2026-07-27 19:08:08 +08:00
parent b02d18d3b9
commit 78a70ee7c2
20 changed files with 3441 additions and 654 deletions

View File

@@ -0,0 +1,154 @@
# 开发指南
本文定义 AI 工单平台的代码边界、领域约束、异步任务、迁移、测试和提交规则。环境安装见
[本地开发环境](local-setup.md),产品行为以[项目蓝图](../product/blueprint.md)为准。
## 1. 仓库与技术栈
```text
backend/
apps/ Django 业务应用
config/ 设置、URL、Celery 和 WSGI/ASGI
tests/ 跨应用测试配置
frontend/
src/app/ 路由与应用壳
src/components/ 通用 UI 和项目级 App 组件
src/features/ 按业务领域组织的页面、API 和类型
infra/ Compose、Nginx、监控和恢复工具
docs/ 产品、开发、前端、运维和验收文档
```
- 后端:Python 3.12、Django、Django Ninja、PostgreSQL、pgvector、Celery。
- 前端:React、TypeScript、Vite、Tailwind CSS、shadcn/ui。
- 存储与安全:MinIO、ClamAV、Fernet 凭据加密。
- 工具链:pytest、Ruff、Vitest、ESLint、pnpm。
## 2. 后端应用边界
| 应用 | 职责 |
|---|---|
| `accounts` | 用户、权限、菜单、企业身份与组织映射 |
| `tickets` | 工单聚合、受理、材料、支持分析、回复与评估 |
| `solutions` | 解决方案和工单权威解决结果 |
| `knowledge` | 知识、排查方案、文档、索引、检索、治理与蒸馏 |
| `agents` | Agent 版本、步骤、运行、事件和产物 |
| `modelhub` | 模型渠道、部署、加密凭据和调用记录 |
| `tools` | Tool/MCP 目录、授权、调用和风险确认 |
| `channels` | 企业渠道端点、会话、消息和回执 |
| `workitems` | 任务中心、活动任务去重和 SLA |
| `audit` | 业务操作审计 |
| `system` | 健康、指标和蓝图退出报告 |
API 层负责鉴权、参数解析和响应序列化,不承载跨实体业务事务。复杂业务必须进入对应
`services.py` 或明确命名的领域模块。
## 3. 领域不变量
### 3.1 工单
- 工单创建、字段更新、状态流转、解决和归档必须通过 `apps.tickets.services`。
- Agent、Celery、渠道和 Tool 不得直接修改 `Ticket` 状态或受保护字段。
- 每次状态变化必须记录 `TicketEvent`,Agent 事件关联 `agent_run_id`。
- 人工修改的业务字段默认受保护;Agent 建议字段保留来源和证据,但不自动获得保护。
- `TicketResolution` 是权威解决结果,旧展示字段不得成为新的写入来源。
### 3.2 智能受理
- 问题描述是自动建单的唯一门槛;其他缺失字段使工单进入 `pending_info`。
- 同一受理记录和 Agent 重试只能关联一张正式工单。
- 对象复制、附件记录、字段证据和建单事件必须处于受控事务;临时对象只在提交后删除。
- 模型、扫描、解析或存储失败必须保留原始材料并提供人工接管路径。
- `revision` 是受理记录的乐观锁,客户端不得忽略冲突后直接覆盖。
### 3.3 支持、知识和自动化
- Agent 只能引用启动运行时冻结的知识、方案和历史工单候选。
- 未发布、范围不匹配或未进入引用快照的内容不能成为可信结论。
- 知识资产发布需要独立审核;提交人不能审核自己的版本。
- 索引刷新通过 `transaction.on_commit` 触发,避免读取未提交业务版本。
- 自动解决同时要求 Agent 授权、全局开关、置信度、风险和操作人权限。
### 3.4 Tool、渠道和身份
- Tool 有效权限是用户权限、用户/用户组授权、Agent 动作和 Agent 授权的交集。
- 高风险 Tool 必须由非申请人独立确认。
- MCP 和渠道 URL 只允许无内嵌凭据的 HTTP(S) 地址;真实网络还需由部署层限制出口。
- 渠道入站、出站和回执必须使用外部 ID 或幂等键去重。
- OIDC 账号以提供方和稳定 `subject` 关联;显示名不得作为身份主键。
- 外部组织映射只管理显式配置的业务组,不删除不属于该提供方管理范围的组。
## 4. 异步任务与失败处理
- 在数据库事务内创建业务记录,使用 `transaction.on_commit` 投递 Celery。
- Celery 任务必须允许重复执行,进入任务时先检查业务终态或幂等键。
- Agent 运行使用有序 `AgentRunEvent.sequence`;SSE 客户端以 `Last-Event-ID` 或 `after`
续传并忽略重复序号。
- 模型调用使用总时间预算和有限重试,不把渠道原始错误或凭据写入普通审计。
- 单个材料或目录记录失败不得把整个批次伪装成成功,也不应删除可供排查的原始数据。
## 5. API 与前端约定
- API 路径统一以 `/api` 开头,内部 MCP 单独使用 `/internal-mcp`。
- Django Ninja Schema 只描述传输结构,业务合法性仍由领域服务验证。
- 前端 API 请求集中在功能目录的 `api.ts` 或明确命名的 API 模块。
- 页面使用项目级 `AppPage`、`AppSection`、`AppDataTable`、`AppField` 和语义状态组件。
- 表单只提交发生变化的字段;时间在浏览器转换为带时区 ISO 8601。
- 用户可见文案以中文为主,后端字段名和 TypeScript 标识符保持英文。
前端视觉和组件规则见[前端设计系统](../frontend/design-system.md)。
## 6. 数据库迁移
1. 先修改模型,再执行 `python manage.py makemigrations <app>`。
2. 检查迁移依赖、约束名称、反向操作和数据迁移的幂等性。
3. 数据迁移使用历史模型,不导入当前业务模型。
4. 向量维度、唯一约束、非空字段等高风险变化需要单独说明升级与回滚方案。
5. 运行:
```powershell
python manage.py migrate
python manage.py makemigrations --check --dry-run
```
禁止修改已经进入共享历史且可能在其他环境执行过的迁移。
## 7. 注释与文档
- 核心模块使用中文模块 docstring 说明职责和边界。
- 公共编排函数说明事务、幂等、信任或失败语义。
- 行内注释只解释代码无法直接表达的“为什么”,例如提交回调、行锁、降级或安全判断。
- 不为普通 CRUD、简单序列化、测试、迁移、脚本或直观 JSX 添加逐行注释。
- 行为、接口、部署变量或质量基线变化时同步 README 和对应产品/运维文档。
## 8. 测试分层
- 领域单元测试:状态机、字段保护、授权、验证和指标计算。
- API 测试:权限、输入错误、脱敏和响应兼容。
- 集成测试:数据库事务、对象存储、Celery、SSE、MCP 和渠道。
- 前端测试:关键页面恢复、自动跳转、失败降级、重复提交和权限状态。
- 真实验收:只使用脱敏真实案例和目标环境服务,不以 Mock 或哈希回退代替。
提交前执行:
```powershell
cd backend
pytest
ruff check .
python manage.py check
python manage.py makemigrations --check --dry-run
cd ..\frontend
pnpm test:run
pnpm typecheck
pnpm lint
pnpm build
```
## 9. Git 提交
- 使用英文 Conventional Commit:`feat:`、`fix:`、`test:`、`docs:`、`ops:`、`refactor:`。
- 一个提交表达一个可说明的功能边界,测试和迁移随功能提交。
- 暂存前检查 `git diff`,暂存后检查 `git diff --cached` 和
`git diff --cached --check`。
- 不提交 `.env`、凭据、运行数据、对象卷、数据库卷、备份、构建产物或本地缓存。
- 不使用破坏性重置清理他人改动;不在未经授权时推送或改写历史。

View File

@@ -1,115 +1,334 @@
# Local Setup
# 本地开发环境
## Prerequisites
本文说明 Windows 和 Linux/macOS 上的本地配置、三种启动方式、数据库初始化、质量检查及
常见问题。生产环境请使用[生产部署与恢复手册](../operations/production-runbook.md)。
## 1. 前置环境
- Python 3.12
- Node.js 22
- Docker Desktop
- Node.js 22 或更高版本
- pnpm 11.9.0
- Docker Desktop,或 Docker Engine + Compose
- Git
## First Run
建议通过 Corepack 启用仓库声明的 pnpm:
```bash
corepack enable
corepack prepare pnpm@11.9.0 --activate
```
检查版本:
```bash
python --version
node --version
pnpm --version
docker compose version
```
## 2. 初始化配置
在项目根目录复制环境变量模板:
```powershell
Copy-Item .env.example .env
python -c "import base64,secrets; print(base64.urlsafe_b64encode(secrets.token_bytes(32)).decode())"
```
将输出写入 `.env` 的 `AI_CREDENTIAL_ENCRYPTION_KEY`。该值缺失时,系统会拒绝保存模型渠道凭证;已经保存凭证后不要随意更换主密钥。
Linux/macOS:
完整应用(PostgreSQL、Redis、MinIO、Django、Celery worker、Celery Beat、React):
```bash
cp .env.example .env
```
生成稳定的 Fernet 主密钥:
```bash
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
```
把结果写入 `.env` 的 `AI_CREDENTIAL_ENCRYPTION_KEY`。已经保存模型、MCP、渠道或 OIDC
凭据后不要直接更换主密钥,否则历史密文将无法解密。
本地至少检查:
- `DJANGO_SECRET_KEY`
- `DJANGO_SUPERUSER_PASSWORD`
- `POSTGRES_PASSWORD`
- `MINIO_ROOT_USER`、`MINIO_ROOT_PASSWORD`
- `MINIO_ACCESS_KEY`、`MINIO_SECRET_KEY`
- `AI_CREDENTIAL_ENCRYPTION_KEY`
- `INTERNAL_MCP_TOKEN`
- `METRICS_TOKEN`
`.env` 已被 Git 忽略,不得把真实值写回 `.env.example`。
## 3. 启动方式
### 3.1 完整 Docker 环境
适合第一次启动和端到端联调:
```powershell
cd infra
docker compose --env-file ../.env up --build
docker compose -f infra/docker-compose.yml --env-file .env up --build
```
只启动本地基础设施、在宿主机运行前后端时:
包含 PostgreSQL、Redis、MinIO、ClamAV、Django、Celery Worker、Celery Beat 和 React。
后端入口会等待依赖服务、执行数据库迁移并初始化治理数据。
访问地址:
- 前端:<http://localhost:5173>
- API 文档:<http://localhost:8000/api/docs>
- 存活探针:<http://localhost:8000/api/system/health/live>
- 就绪探针:<http://localhost:8000/api/system/health/ready>
- MinIO 控制台:<http://localhost:9001>
停止环境:
```powershell
cd infra
docker compose -f docker-compose.local.yml --env-file ../.env up -d
docker compose -f infra/docker-compose.yml --env-file .env down
```
首次启动时,backend 容器会自动等待 PostgreSQL、执行数据库迁移,并初始化企业后台治理数据。
不要随意添加 `-v`,该参数会删除本地数据库和对象存储卷。
Backend:
### 3.2 Docker 基础设施 + 宿主机应用
- API: http://localhost:8000/api/docs
- Health: http://localhost:8000/api/system/health
适合频繁调试后端和前端:
Frontend:
```powershell
docker compose -f infra/docker-compose.local.yml --env-file .env up -d
```
- App: http://localhost:5173
- 局域网访问: `http://<宿主机局域网 IP>:5173`
宿主机进程需要把容器服务名覆盖为本机地址:
前端默认通过同源 `/api` 代理后端:宿主机直接运行 Vite 时代理到
`http://localhost:8000`,Docker Compose 中通过 `API_PROXY_TARGET` 代理到
`http://backend:8000`。因此局域网访问时无需把浏览器 API 地址配置为
```env
POSTGRES_HOST=localhost
CELERY_BROKER_URL=redis://localhost:6379/0
CELERY_RESULT_BACKEND=redis://localhost:6379/1
MINIO_ENDPOINT=localhost:9000
CLAMAV_HOST=localhost
API_PROXY_TARGET=http://localhost:8000
```
安装并启动后端:
```powershell
cd backend
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
python manage.py migrate
python manage.py bootstrap_governance
python manage.py runserver 0.0.0.0:8000
```
Linux/macOS 激活虚拟环境:
```bash
source .venv/bin/activate
```
另开终端启动异步进程:
```powershell
cd backend
.\.venv\Scripts\Activate.ps1
python -m celery -A config.celery worker -l info -P solo
```
```powershell
cd backend
.\.venv\Scripts\Activate.ps1
python -m celery -A config.celery beat -l info
```
安装并启动前端:
```powershell
cd frontend
pnpm install --frozen-lockfile
pnpm dev
```
前端通过同源 `/api` 代理后端,局域网访问时无需把浏览器 API 地址写成
`localhost:8000`。
默认管理员:
### 3.3 Windows 后端辅助脚本
- 账号: `admin`
- 密码: `admin12345`
- 可通过 `.env` 中的 `DJANGO_SUPERUSER_USERNAME`、`DJANGO_SUPERUSER_PASSWORD`、`DJANGO_SUPERUSER_EMAIL` 修改。
基础设施已启动时,可在项目根目录执行:
## Backend Tests
```bash
cd backend
python -m pip install -e ".[dev]"
pytest -v
```powershell
.\start-backend.ps1
```
## Frontend Checks
脚本校验 `.env` 和 Fernet 主密钥,分别启动 Django、Celery Worker 和 Celery Beat。
它不会启动 Docker、前端或执行迁移。修改 `.env` 后使用:
```bash
```powershell
.\start-backend.ps1 -Restart
```
## 4. 数据库与初始数据
创建或更新迁移:
```powershell
cd backend
python manage.py makemigrations
python manage.py migrate
python manage.py bootstrap_governance
```
提交前必须确认没有遗漏迁移:
```powershell
python manage.py makemigrations --check --dry-run
```
开发环境默认管理员为 `admin / admin12345`,可通过 `.env` 中的
`DJANGO_SUPERUSER_*` 修改。生产环境禁止使用默认密码。
## 5. AI 能力初始化
### 5.1 模型、Skill 和 Agent
1. 使用管理员进入 `#/modelhub/providers`,创建 OpenAI-compatible 渠道和模型部署。
2. 文本步骤使用 `text_chat`;包含图片时使用 `vision_chat`,并单独批准图片出境。
3. 在 `#/skills` 管理 Skill 草稿和发布版本。
4. 在 `#/agents` 配置步骤、模型、输入映射和授权动作。
5. 在 `#/agent-runs` 查看冻结配置、步骤轨迹、调用尝试、Token 和耗时。
发布可信建单 Agent:
```powershell
cd backend
python manage.py publish_trusted_ticket_intake --deployment-id 1
```
发布支持分析 Agent:
```powershell
python manage.py publish_support_analysis --deployment-id 1
```
发布知识蒸馏 Agent:
```powershell
python manage.py publish_knowledge_distillation --deployment-id 1
```
### 5.2 混合检索
在模型中心创建 `embedding` 部署,可选创建 `rerank` 部署,并配置:
```env
KNOWLEDGE_EMBEDDING_DEPLOYMENT_ID=<Embedding 部署 ID>
KNOWLEDGE_EMBEDDING_DIMENSIONS=1536
KNOWLEDGE_EMBEDDING_ALLOW_HASH_FALLBACK=false
KNOWLEDGE_RERANK_DEPLOYMENT_ID=<可选重排部署 ID>
```
维度变更必须同时提供数据库迁移。重建现有索引:
```powershell
python manage.py rebuild_knowledge_embeddings
```
生产环境使用 PostgreSQL 全文和 pgvector HNSW。哈希向量回退只允许测试或明确的本地开发。
### 5.3 自动解决
自动解决默认关闭。启用前需要同时满足:
- Agent 发布版本包含自动解决授权。
- 发起人具有 `ticket.resolve` 权限。
- 结果通过引用、风险和置信度校验。
- `TICKET_AUTO_RESOLVE_ENABLED=true`。
- 匹配分数达到 `TICKET_AUTO_RESOLVE_MIN_SCORE`。
## 6. 质量检查
后端:
```powershell
cd backend
pytest
ruff check .
python manage.py check
python manage.py makemigrations --check --dry-run
```
前端:
```powershell
cd frontend
npm install
npm run test:run
npm run lint
npm run typecheck
npm run build
pnpm install --frozen-lockfile
pnpm test:run
pnpm typecheck
pnpm lint
pnpm build
```
## AI Platform Demo
当前完整基线为后端 217 项、前端 73 项。更详细的测试分层和提交规范见
[开发指南](development-guide.md)。
1. 使用管理员账号打开 `#/modelhub/providers`,创建 OpenAI-compatible 渠道和文本模型,并执行异步连通测试。
2. 取得模型配置 ID 后创建预置草稿:
## 7. 固定验收入口
- 智能建单真实文本闭环:
```powershell
python manage.py verify_ticket_intake --username admin
```
- 阶段 2 报告:
```powershell
python manage.py report_stage2_acceptance
```
- 阶段 3 报告:
```powershell
python manage.py report_stage3_acceptance
```
- 统一蓝图报告:
```powershell
python manage.py report_blueprint_readiness `
--evidence ../docs/product/acceptance/blueprint-external-evidence.template.json
```
合成案例只能用于开发回归,不得替代真实业务验收。
## 8. 常见问题
### 前端提示 esbuild 构建被忽略
确认使用 pnpm 11.9.0,并检查 `pnpm-workspace.yaml` 中 `allowBuilds.esbuild` 为 `true`,
然后重新执行 `pnpm install --frozen-lockfile`。
### 材料上传后扫描失败
确认 ClamAV 已健康:
```powershell
cd backend
python manage.py seed_ai_demo --deployment-id 1
docker compose -f infra/docker-compose.local.yml ps clamav
```
3. 在 `#/skills` 检查、编辑并发布三个 Skill。
4. 在 `#/agents` 编辑技术支持分析 Agent 的模型、步骤和输入映射,先运行草稿沙箱,再发布并运行正式版本。
5. 在 `#/agent-runs` 查看执行脊柱、每步输入输出、调用尝试、Token、耗时和配置快照。
ClamAV 首次启动需要下载病毒库。扫描失败只影响对应材料,原件会保留。
完整验收步骤见 [AI 平台配置演示版验收](ai-platform-demo-acceptance.md)。
### MinIO 附件不可用
## Trusted Ticket Intake
宿主机运行后端时确认 `MINIO_ENDPOINT=localhost:9000`;容器内后端应使用
`MINIO_ENDPOINT=minio:9000`。
1. 在模型中心配置并启用一个文本模型。
2. 发布预置建单 Skill 与单步 Agent:
### Agent 一直处于 queued
```powershell
cd backend
python manage.py seed_ticket_intake --deployment-id 1
```
检查 Redis、Celery Worker 和 Beat 是否运行,并确认 Django 与 Celery 使用同一份 `.env`
和 `AI_CREDENTIAL_ENCRYPTION_KEY`。
3. 打开 `#/tickets/create`,输入自然语言描述,审核结构化字段并明确确认。
4. 可运行固定真实文本验收脚本;脚本会保留草稿、AgentRun、产物、审计和一张验收工单:
### 修改模型凭据后 Celery 仍报解密失败
```powershell
python manage.py verify_ticket_intake --username admin
```
宿主机直接运行时要确保已加载根目录 `.env` 中的凭证主密钥,并把容器服务主机名覆盖为本机地址。缺少主密钥时脚本会安全失败,不会读取或替换渠道凭证。
图片代码要求 MinIO 可用;只有 `vision_chat` 模型且渠道已由管理员授权图片出境时才允许分析图片。当前真实视觉渠道验收仍待完成。
## Stage 1 API Smoke Tests
- Tickets: `GET http://localhost:8000/api/tickets`
- Ticket export: `GET http://localhost:8000/api/tickets/export`
- Solutions: `GET http://localhost:8000/api/solutions`
重启 Django 和所有 Celery 进程。禁止通过替换 Fernet 主密钥来“修复”单条凭据。

View File

@@ -1,80 +1,132 @@
# Frontend Design System
# 前端设计系统
## Principles
## 1. 设计原则
- Build product screens from shadcn/ui primitives and project-owned App components.
- Keep operational pages dense, quiet, and optimized for repeated use.
- Use semantic status colors for ticket state, priority, audit, AI, and system feedback.
- User-facing frontend text must be Chinese-first. Internal TypeScript names and API field names may stay English.
- Business pages must not create one-off table, filter, detail, status, or priority patterns.
- Admin UI should feel calm and enterprise-grade: clear hierarchy, restrained surfaces, compact actions, and no decorative marketing-style layout.
- 使用 shadcn/ui 基础组件和项目自有 App 组件构建业务页面。
- 运营页面保持紧凑、克制,优先服务高频重复操作。
- 工单状态、优先级、审计、AI 和系统反馈使用统一语义色。
- 用户可见文案以中文为主;TypeScript 标识符和 API 字段可保持英文。
- 列表、筛选、详情、状态和优先级不得创建一次性样式。
- 管理端强调清晰层级、有限表面和紧凑操作,不使用营销页式装饰布局。
- 亮色和暗色主题必须同时可用,业务页面不自行硬编码主题颜色。
## Tokens
## 2. 设计令牌
Theme tokens live in `frontend/src/styles/globals.css` and are exposed through Tailwind in
`frontend/tailwind.config.ts`.
主题令牌位于 `frontend/src/styles/globals.css`,通过
`frontend/tailwind.config.ts` 暴露给 Tailwind。
Core tokens:
核心令牌:
- `background`, `foreground`, `surface`, `border`
- `muted`, `muted-foreground`
- `primary`, `success`, `warning`, `danger`, `info`, `ai`
- `sidebar`, `sidebar-foreground`, `sidebar-primary`, `sidebar-accent`, `sidebar-border`
- `background`、`foreground`、`surface`、`border`
- `muted`、`muted-foreground`
- `primary`、`success`、`warning`、`danger`、`info`、`ai`
- `sidebar`、`sidebar-foreground`、`sidebar-primary`、`sidebar-accent`、
`sidebar-border`
Theme behavior:
主题行为:
- `AppThemeProvider` uses `next-themes` with `light`, `dark`, and `system`.
- `AppThemeToggle` is rendered in `AppTopbar` and exposes Chinese options: `亮色`, `暗色`, `跟随系统`.
- Light and dark mode values must both be defined in `frontend/src/styles/globals.css`; do not add one-off `dark:` color overrides in business pages.
- Sidebar colors must come from `sidebar*` tokens so the sidebar follows theme switching.
- `AppThemeProvider` 使用 `next-themes`,支持亮色、暗色和跟随系统。
- `AppThemeToggle` 位于顶部栏,用户选项统一为“亮色”“暗色”“跟随系统”。
- 亮色和暗色值都在全局样式中定义,业务页面不要新增零散的 `dark:` 颜色覆盖。
- 侧边栏必须使用 `sidebar*` 令牌,保证主题切换一致。
## Components
## 3. 组件层级
shadcn/ui primitives live in `frontend/src/components/ui` and should remain close to generated shadcn APIs:
### shadcn/ui 基础组件
- `Button`
- `Badge`
- `Card`, `CardHeader`, `CardContent`, `CardTitle`, `CardDescription`
- `Input`, `Textarea`, `Select`
位于 `frontend/src/components/ui`,尽量保持生成组件的标准 API:
- `Button`、`Badge`
- `Card`、`CardHeader`、`CardContent`、`CardTitle`、`CardDescription`
- `Input`、`Textarea`、`Select`
- `Table`
- `Dialog`, `Sheet`, `DropdownMenu`, `Tabs`, `Tooltip`, `Skeleton`, `Sonner`
- `Dialog`、`Sheet`、`DropdownMenu`、`Tabs`
- `Tooltip`、`Skeleton`、`Sonner`
Product App components live in `frontend/src/components/app` and are the preferred page-level API:
业务页面不要直接修改基础组件实现来满足单页需求,应通过属性、组合或 App 组件扩展。
- `AppSidebar`
- `AppTopbar`
- `AppThemeProvider`
- `AppThemeToggle`
- `AppPage`
- `AppPageHeader`
- `AppDataTable`
- `AppFilterBar`
- `AppDetailLayout`
- `AppSection`
### 项目级 App 组件
位于 `frontend/src/components/app`,是业务页面优先使用的页面 API:
- `AppSidebar`、`AppTopbar`
- `AppThemeProvider`、`AppThemeToggle`
- `AppPage`、`AppPageHeader`
- `AppDataTable`、`AppFilterBar`
- `AppDetailLayout`、`AppSection`
- `AppEmptyState`
- `AppStatusBadge`
- `AppPriorityBadge`
- `AppStatusBadge`、`AppPriorityBadge`
- `AppField`
Business pages should use:
使用约定:
- `AppDataTable` for repeated table/list surfaces.
- `AppFilterBar` for search and filter controls.
- `AppDetailLayout` for detail pages with main content and side panels.
- `AppStatusBadge` and `AppPriorityBadge` for ticket lifecycle and priority presentation.
- `AppField` for form labels and required state; direct page-level `Label` usage should be avoided.
- `SelectContent > SelectGroup > SelectItem` for every select menu.
- 列表和表格使用 `AppDataTable`。
- 搜索和筛选使用 `AppFilterBar`。
- 主内容加侧栏的详情页使用 `AppDetailLayout`。
- 状态和优先级使用语义 Badge 组件。
- 表单标签、必填态和说明使用 `AppField`,避免页面直接使用裸 `Label`。
- Select 统一采用 `SelectContent > SelectGroup > SelectItem`。
## Current Core Screens
## 4. 页面与交互规则
- Ticket center uses an operations-table layout: the first column combines ticket number, title, requester, and description; workflow state and priority are grouped together.
- Ticket detail uses `AppDetailLayout`, a ticket overview card, a real event timeline, and a side column for handling context, linked solutions, and AI analysis placeholder. Avoid repeating overview-card fields in the side column.
- Ticket status transitions use `TicketTransitionDialog`. Resolution and closure actions can carry a solution summary; non-resolution workflow actions still require a handling note.
- Ticket workflows are category-driven: business and operation issues support short closure paths, data issues use a medium path, and technical issues keep the standard support workflow.
- Linked solutions support search, recommendation-only linking, adoption with automatic ticket closure, and prefilled resolution text during later resolve/close actions.
- Knowledge pages use the same `AppPage`, `AppSection`, `AppDataTable`, `AppField`, and shadcn form primitives as ticket and system pages.
- Knowledge search results must show source type, title, score, and citable content snippets.
- System governance quick-create forms use `AppSection`, `FieldGroup`, and `AppField`.
### 工单
Preview page:
- 工单中心第一列组合工单号、标题、提出人和描述,状态与优先级作为独立运营信息。
- 工单详情使用总览、事件时间线和侧栏区域,不在多个面板重复同一字段。
- 状态流转统一使用 `TicketTransitionDialog`;需要备注或解决结果时由领域规则决定。
- 工单编辑只提交变化字段,避免把未修改的 Agent 字段误标为人工保护字段。
- `pending_info` 工单必须展示待补全字段、来源证据、原始材料和受理运行。
- 智能受理 SSE 断线后显示重连状态,终态查询失败时保留人工表单。
- `frontend/src/features/design-system/DesignSystemPreview.tsx`
### 知识与解决方案
- 知识、方案和治理页面沿用同一页面、表格和表单组件。
- 检索结果必须展示来源类型、标题、综合分数和可引用片段。
- 版本状态、审核人、发布时间和变更摘要应清晰可见。
- 发布、下线、回滚和高风险确认使用明确的确认对话框。
### Agent、Tool、渠道与系统治理
- 配置页先展示当前状态,再提供编辑或新建动作。
- 凭据只显示“已配置”或脱敏尾号,不回填明文。
- Agent 运行详情展示步骤、事件、调用尝试和冻结配置,但不在普通列表泄露敏感正文。
- 高风险 Tool 必须显示申请人、审核人、风险级别和当前确认状态。
- 渠道回复必须展示冻结回复版本及目标会话,不能允许任意自由文本绕过回复任务。
## 5. 状态与反馈
- 加载:使用 Skeleton 或页面级加载态,避免布局跳动。
- 空状态:使用 `AppEmptyState`,说明下一步可执行动作。
- 成功:使用简短 Toast,不重复页面已经明确显示的结果。
- 失败:错误消息保留在相关区域,并提供重试或人工降级动作。
- 权限不足:隐藏不可用主操作或明确禁用原因,不伪装成数据为空。
- 长任务:展示进度阶段、最近事件和连接状态,终态后刷新权威业务数据。
## 6. 可访问性与响应式
- 表单控件必须有可关联标签。
- 仅图标按钮必须提供 `sr-only` 文本或 `aria-label`。
- 状态不能只依赖颜色,应同时显示文本或图标。
- 焦点顺序与视觉顺序一致,Dialog 和 Sheet 使用标准焦点管理。
- 桌面优先的治理页面在移动端应明确限制,不压缩成不可操作布局。
- 时间使用 `<time>` 和 ISO `dateTime`,展示文本按用户时区格式化。
## 7. 开发检查
新增或修改页面后运行:
```powershell
cd frontend
pnpm test:run
pnpm typecheck
pnpm lint
pnpm build
```
预览入口:
```text
frontend/src/features/design-system/DesignSystemPreview.tsx
```
业务代码结构、注释和提交规则见[开发指南](../development/development-guide.md)。

View File

@@ -0,0 +1,335 @@
# 生产部署与恢复手册
本文适用于单机 Docker Compose 私有化部署,覆盖首次部署、升级、监控、备份、恢复和
故障处理。多节点、高可用数据库和企业 Kubernetes 部署需要在此基线之上另行设计。
## 1. 部署拓扑与前置条件
生产 Compose 包含:
- PostgreSQL 16 + pgvector
- Redis 7
- MinIO
- ClamAV
- Django + Gunicorn
- Celery Worker、Celery Beat
- Nginx 静态前端与 API 反向代理
- 可选 Prometheus、Alertmanager
最低前置条件:
- 64 位 Linux
- Docker Engine 与 Compose 插件
- 可持续运行的本地或挂载数据盘
- 企业 DNS 和 TLS 证书
- NTP 时间同步
- 独立备份目录和异地加密存储
试运行建议至少 4 核 CPU、8 GB 内存和 100 GB 可用磁盘;正式规格必须根据附件量、
模型并发、知识向量和保留周期压测确定。ClamAV 病毒库初始化和 PostgreSQL/MinIO 数据量
会显著影响内存与磁盘需求。
## 2. 目录、账号和权限
建议使用专用系统账号部署,例如 `ai-ticket`:
```text
/opt/ai-ticket-platform/ 应用代码和 .env
/var/lib/ai-ticket-backups/ 本机备份
/etc/ai-ticket/ 监控令牌和告警地址
```
要求:
- `.env`、监控令牌和告警 Webhook 仅部署账号可读。
- 备份账号只拥有 Docker 和备份目录所需权限。
- 不把 Docker Socket、PostgreSQL、Redis、MinIO 或 ClamAV 端口暴露到公网。
- `infra/secrets/*.example` 只是结构示例,不能作为生产凭据。
## 3. 生产配置
复制模板:
```bash
cp .env.example .env
chmod 600 .env
```
必须修改:
```env
DJANGO_DEBUG=false
DJANGO_SECRET_KEY=<高强度随机值>
DJANGO_ALLOWED_HOSTS=tickets.example.com
CORS_ALLOWED_ORIGINS=https://tickets.example.com
CSRF_TRUSTED_ORIGINS=https://tickets.example.com
FRONTEND_APP_URL=https://tickets.example.com
OIDC_CALLBACK_BASE_URL=https://tickets.example.com
DJANGO_SUPERUSER_PASSWORD=<首次登录后仍需立即轮换>
POSTGRES_PASSWORD=<数据库密码>
MINIO_ROOT_USER=<MinIO 管理账号>
MINIO_ROOT_PASSWORD=<MinIO 管理密码>
MINIO_ACCESS_KEY=<应用访问账号>
MINIO_SECRET_KEY=<应用访问密钥>
AI_CREDENTIAL_ENCRYPTION_KEY=<稳定 Fernet 密钥>
INTERNAL_MCP_TOKEN=<独立随机令牌>
METRICS_TOKEN=<独立随机令牌>
```
Fernet 密钥生成:
```bash
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
```
密钥一旦用于加密模型、MCP、渠道或 OIDC 凭据,必须进入企业密钥备份流程。直接替换会导致
历史密文不可解密。
生产建议:
- `KNOWLEDGE_EMBEDDING_ALLOW_HASH_FALLBACK=false`
- `TICKET_AUTO_RESOLVE_ENABLED=false`,完成真实案例验收后再按策略开启
- 使用正式 Embedding 部署并保持向量维度与数据库字段一致
- 根据数据保留政策设置 Agent 运行和临时受理保留周期
- 默认管理员仅用于初始化,随后创建实名管理员并停用或轮换默认账号
## 4. TLS 与网络边界
仓库 Compose 暴露 `${HTTP_PORT:-8080}` 的 HTTP 服务。生产环境应在其前方部署企业负载
均衡器或 TLS 反向代理:
- 外部只开放 443。
- HTTP 强制跳转 HTTPS。
- 保留 `Host`、`X-Forwarded-Proto` 和真实客户端 IP。
- 限制上传体积不低于平台总材料上限 100 MB。
- `/internal-mcp`、MinIO 控制台和监控端点只允许可信网络访问。
- 对模型、MCP、OIDC 和渠道出站目标使用网络白名单,应用层 URL 校验不能替代防火墙。
OIDC 回调地址固定为:
```text
https://<域名>/api/identity/auth/oidc/<provider-slug>/callback
```
## 5. 首次部署
先校验变量展开:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env config
```
构建并启动:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env up -d --build
docker compose -f infra/docker-compose.prod.yml --env-file .env ps
```
后端入口会等待 PostgreSQL、执行迁移并初始化治理数据。首次部署仍应检查日志:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env logs backend --tail 200
docker compose -f infra/docker-compose.prod.yml --env-file .env logs worker --tail 100
docker compose -f infra/docker-compose.prod.yml --env-file .env logs beat --tail 100
```
探针:
```bash
curl -fsS http://127.0.0.1:8080/api/system/health/live
curl -fsS http://127.0.0.1:8080/api/system/health/ready
```
`live` 只表示进程可响应;`ready` 同时检查数据库和缓存。部署完成后验证:
1. HTTPS、登录和权限菜单。
2. 创建、查询和状态流转一张测试工单。
3. 上传安全测试附件并下载。
4. 启动一次 Agent 运行并查看事件。
5. 如已配置渠道,执行入站、出站和回执。
6. 检查后台任务、指标和告警。
## 6. 监控与告警
创建仅运维账号可读的文件:
```bash
install -m 600 /dev/null /etc/ai-ticket/metrics-token
install -m 600 /dev/null /etc/ai-ticket/alert-webhook-url
```
写入与 `.env` 中 `METRICS_TOKEN` 一致的指标令牌,以及真实告警 Webhook。设置路径并启动:
```bash
export METRICS_TOKEN_FILE=/etc/ai-ticket/metrics-token
export ALERT_WEBHOOK_URL_FILE=/etc/ai-ticket/alert-webhook-url
docker compose -f infra/docker-compose.prod.yml --env-file .env \
--profile monitoring up -d
```
Prometheus 与 Alertmanager 默认只绑定宿主机回环地址。指标接口接受
`X-Metrics-Token` 或 Bearer Token。当前告警覆盖:
- 后端无法抓取
- 渠道失败或积压
- Agent/Tool 近期失败
- 任务中心积压
上线前必须触发一条测试告警,确认接收人、升级路径、静默策略和恢复通知。
## 7. 备份、校验和保留
Linux:
```bash
sh infra/scripts/backup.sh
sh infra/scripts/verify-backup.sh backups/<timestamp>
BACKUP_RETENTION_DAYS=30 sh infra/scripts/prune-backups.sh
```
Windows PowerShell:
```powershell
& infra/scripts/backup.ps1
& infra/scripts/verify-backup.ps1 -BackupDirectory backups/<timestamp>
```
备份包含:
- PostgreSQL 自定义格式转储
- 可枚举数据库结构清单
- MinIO 数据归档
- SHA-256 校验文件
- 备份元数据
默认流程会暂停运行中的 backend、worker 和 beat,并在对象卷归档期间停止 MinIO,
形成数据库与对象存储的一致静默窗口。只有确认没有常驻业务写入的隔离演练才允许使用
`BACKUP_SKIP_APPLICATION_SERVICES=true` 或 `-SkipApplicationServices`。
`infra/backup-cron.example` 是宿主机 cron 模板。安装前替换绝对路径和专用账号。校验成功的
备份必须复制到独立、加密、不可被应用主机直接删除且具有保留策略的异地存储。
备份成功不代表可恢复;至少按季度执行恢复演练,并在重大版本发布前再次执行。
## 8. 升级
升级前:
1. 确认当前 Git 版本和镜像标签可追溯。
2. 阅读迁移和配置变更。
3. 执行完整质量门和生产 Compose 校验。
4. 创建并验证一致性备份。
5. 记录维护窗口和回滚负责人。
构建新版本:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env build
docker compose -f infra/docker-compose.prod.yml --env-file .env up -d
```
观察:
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env ps
docker compose -f infra/docker-compose.prod.yml --env-file .env logs backend worker --tail 200
curl -fsS http://127.0.0.1:8080/api/system/health/ready
```
然后执行首次部署中的业务冒烟。迁移必须向后兼容时,才允许应用容器滚动替换;破坏性迁移
需要单独维护窗口和数据转换方案。
## 9. 回滚
应用回滚:
1. 停止写入或进入维护窗口。
2. 切回已验证的代码版本和镜像标签。
3. 使用相同 `.env` 启动旧版本。
4. 检查就绪探针和业务冒烟。
数据库迁移不能盲目反向执行。若新版本已写入旧版本不理解的数据,使用升级前的一致性备份
恢复数据库与 MinIO,而不是只恢复其中一侧。
## 10. 恢复
恢复会替换当前数据库和对象存储,只能在确认的维护窗口执行。
Linux:
```bash
RESTORE_CONFIRM=restore-ai-ticket-platform \
sh infra/scripts/restore.sh backups/<timestamp>
```
Windows PowerShell:
```powershell
& infra/scripts/restore.ps1 `
-BackupDirectory backups/<timestamp> `
-Confirm restore-ai-ticket-platform
```
脚本会先验证备份,在覆盖对象卷前停止 MinIO,并在 MinIO 恢复健康后再启动应用服务。
恢复后依次检查:
1. 就绪探针和登录。
2. 工单数量、抽样状态和解决结果。
3. 附件记录与 MinIO 对象。
4. Agent、任务中心和审计记录。
5. 渠道入站、出站和回执。
隔离自动演练:
```powershell
& infra/scripts/drill-restore.ps1
```
演练创建唯一 Compose 项目和独立数据卷,写入工单、附件及 MinIO 标记,执行备份、删除、
恢复和一致性检查,最后清理临时资源。最近一次证据见
[隔离恢复演练记录](recovery-drill-2026-07-27.md)。
## 11. 故障排查
### 就绪探针失败
```bash
docker compose -f infra/docker-compose.prod.yml --env-file .env ps
docker compose -f infra/docker-compose.prod.yml --env-file .env logs backend postgres redis --tail 200
```
重点检查数据库连接、Redis 地址、迁移状态和磁盘空间。
### Celery 任务积压
检查 worker、Redis 和模型服务连通性。不要通过重复点击绕过幂等控制;先确认任务是否已经
创建业务终态。
### 材料一直扫描失败
检查 ClamAV 健康和病毒库日志。不得为恢复业务而在生产关闭恶意文件扫描。
### 模型、MCP、渠道或 OIDC 凭据无法解密
确认 Django 与 Celery 使用同一 Fernet 主密钥。不要覆盖主密钥;从企业密钥备份恢复原值。
### 磁盘快速增长
分别检查 PostgreSQL、MinIO、ClamAV、Prometheus 和备份目录。先确认保留策略和备份可恢复,
不要直接删除 Docker 数据卷。
## 12. 上线安全检查表
- [ ] `DJANGO_DEBUG=false`,域名和可信来源仅包含生产地址。
- [ ] 默认管理员密码已替换,管理员使用实名账号。
- [ ] `.env`、Fernet、MCP、指标和告警凭据已纳入密钥管理。
- [ ] 外部只开放 HTTPS,内部端口受防火墙限制。
- [ ] 模型、MCP、OIDC 和渠道出口有网络白名单。
- [ ] 自动解决保持关闭,或已经通过真实案例和审批策略验收。
- [ ] 监控、真实告警接收方和升级路径已验证。
- [ ] 定时备份已安装,校验后复制到异地加密存储。
- [ ] 已完成隔离恢复演练并记录 RPO/RTO。
- [ ] 统一蓝图报告明确区分已通过和待真实环境验收门槛。

View File

@@ -0,0 +1,14 @@
{
"schema_version": 1,
"status": "passed",
"verified_at": "2026-07-27T09:24:21Z",
"compose_project": "ai-ticket-restore-drill-5124",
"backup_id": "20260727T092235Z",
"duration_seconds": 106.57,
"database_smoke": "ticket_and_attachment_restored",
"object_storage_smoke": "marker_restored",
"django_check": "passed",
"artifact_refs": [
"docs/operations/recovery-drill-2026-07-27.md"
]
}

View File

@@ -0,0 +1,62 @@
# 隔离恢复演练记录(2026-07-27)
## 结论
状态:**通过**
PostgreSQL 与 MinIO 已在独立 Docker Compose 项目中完成一致性备份、破坏和恢复。恢复后,
工单、附件元数据与对象内容均可读取,Django 系统检查通过。演练没有复用或修改现有开发
容器、网络和数据卷。
## 演练环境
- Docker Engine:29.6.1
- Docker Compose:5.3.0
- PostgreSQL:`pgvector/pgvector:pg16`
- MinIO:`minio/minio:latest`
- 归档辅助镜像:`alpine:3.21`
- 隔离 Compose 项目:`ai-ticket-restore-drill-5124`
- 备份编号:`20260727T092235Z`
- 总耗时:106.57 秒
## 执行步骤与证据
1. 启动独立 PostgreSQL 与 MinIO 数据卷,构建当前后端镜像。
2. 执行所有 Django 迁移与治理基线初始化。
3. 创建工单 `RESTORE-DRILL-001`、关联附件元数据和 MinIO 标记对象。
4. 生成 PostgreSQL custom-format dump、结构清单、MinIO 数据归档及 SHA-256 清单。
5. 删除演练工单与 MinIO 对象,确认进入破坏后状态。
6. 校验备份哈希,重建数据库并恢复对象存储数据。
7. 通过 Django ORM 验证工单及附件关系,通过 `mc cat` 验证对象内容。
8. 执行 `python manage.py check`,结果为 0 个问题。
9. 销毁本次演练的容器、网络、数据卷和临时后端镜像。
最终自动化结果:
```json
{
"status": "passed",
"backup_id": "20260727T092235Z",
"duration_seconds": 106.57,
"database_smoke": "ticket_and_attachment_restored",
"object_storage_smoke": "marker_restored",
"django_check": "passed"
}
```
## 演练中发现并修复的问题
- Windows PowerShell 缺少 `sh`,已增加与 Linux 脚本等价的备份、校验和恢复入口。
- Windows 原生命令参数可能改变多行脚本编码或引号,隔离演练改用无引号 UTF-8 字节表达式。
- 当前 MinIO 镜像不包含 `tar`,对象归档与恢复改由固定辅助容器挂载同一数据卷完成。
- 生产备份默认冻结当时正在运行的 backend、worker 与 beat,并在退出时恢复原运行集合,
避免 PostgreSQL 和 MinIO 分别快照期间继续发生跨存储写入。
- 对象卷归档和覆盖期间显式停止 MinIO,只有 MinIO 重新通过健康检查后才恢复业务服务,
避免从活跃数据卷读取或在运行进程下替换存储文件。
- Linux 恢复脚本增加跳过应用服务启停的隔离演练开关,避免演练误启动业务进程。
## 仍需生产执行
本记录证明当前代码和脚本能够恢复一致的数据库与对象数据,不替代生产环境的定期演练。
上线前仍需使用真实加密异地备份、正式告警接收方和业务账号执行完整登录、渠道、Agent
与附件下载冒烟,并记录生产 RTO/RPO。

View File

@@ -0,0 +1,82 @@
{
"schema_version": 1,
"gates": {
"stage3_retrieval": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"environment": "postgresql",
"embedding_deployment": "",
"rerank_deployment": "",
"sample_count": 0,
"thresholds_met": false,
"metrics": {
"recall_at_5": 0,
"p95_latency_ms": 0
},
"hnsw": {
"m": 0,
"ef_construction": 0,
"ef_search": 0
}
},
"stage4_distillation": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"sample_count": 0,
"independent_review": false,
"anonymization_review_passed": false,
"published": false,
"retrieved_after_publish": false,
"services": []
},
"stage4_documents": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"failure_recovery_verified": false,
"formats": [],
"services": []
},
"stage6_channel": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"provider": "",
"signature_verified": false,
"inbound_verified": false,
"outbound_verified": false,
"receipt_verified": false,
"idempotency_verified": false
},
"stage6_identity": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"oidc_provider": "",
"ldap_directory": "",
"oidc_login_verified": false,
"group_claim_verified": false,
"failure_fallback_verified": false,
"ldap_directory_sync_verified": false
},
"stage6_production_ops": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"alert_receiver": "",
"backup_schedule": "",
"offsite_storage": "",
"alerts_verified": false,
"backup_schedule_installed": false,
"offsite_encrypted_copy_verified": false
}
}
}

View File

@@ -0,0 +1,299 @@
{
"schema_version": 1,
"generated_at": "2026-07-27T09:32:44.783410+00:00",
"status": "not_ready",
"exit_ready": false,
"summary": {
"passed_gate_count": 1,
"total_gate_count": 9,
"remaining_gate_count": 8
},
"gates": [
{
"code": "stage2_intake",
"title": "阶段 2:脱敏真实案例智能建单",
"status": "not_ready",
"source": "database_evaluation",
"reasons": [
"尚未导入启用的脱敏真实案例。"
],
"evidence": {
"schema_version": 1,
"generated_at": "2026-07-27T09:32:44.780018+00:00",
"scope": "anonymized_real",
"status": "not_ready",
"exit_ready": false,
"reasons": [
{
"code": "missing_real_cases",
"message": "尚未导入启用的脱敏真实案例。"
}
],
"modality_coverage": {
"text_case_count": 0,
"image_case_count": 0,
"multi_image_case_count": 0,
"document_case_count": 0,
"mixed_text_image_case_count": 0,
"valid_input_case_count": 0,
"invalid_input_case_count": 0
},
"metrics": {
"include_synthetic": false,
"operational": {
"valid_input_count": 1,
"auto_created_count": 0,
"auto_creation_rate": 0.0
},
"evaluation": {
"enabled_case_count": 0,
"reviewed_case_count": 0,
"coverage_rate": null,
"valid_input_count": 0,
"auto_created_count": 0,
"auto_creation_rate": null,
"correct_field_count": 0,
"evaluated_field_count": 0,
"field_accuracy": null,
"evidence_covered_field_count": 0,
"evidence_field_count": 0,
"evidence_coverage_rate": null,
"correct_timeline_item_count": 0,
"evaluated_timeline_item_count": 0,
"timeline_accuracy": null,
"result_selection": "latest_per_case"
},
"targets": {
"auto_creation_rate": 0.7,
"field_accuracy": 0.9,
"coverage_complete": false,
"auto_creation_rate_met": null,
"field_accuracy_met": null
}
},
"case_results": []
}
},
{
"code": "stage3_support",
"title": "阶段 3:脱敏真实案例支持闭环",
"status": "not_ready",
"source": "database_evaluation",
"reasons": [
"阶段 3 验收数据不可读取,请先在目标环境执行最新数据库迁移"
],
"evidence": {
"status": "not_ready",
"exit_ready": false,
"metrics": {},
"reasons": [
{
"code": "database_schema_unavailable",
"message": "阶段 3 验收数据不可读取,请先在目标环境执行最新数据库迁移"
}
]
}
},
{
"code": "stage3_retrieval",
"title": "阶段 3:PostgreSQL 混合检索与重排",
"status": "not_ready",
"source": "external_evidence_manifest",
"reasons": [
"验收状态尚未标记为 passed",
"verified_at 必须是带时区的 ISO 8601 时间",
"缺少验收人 reviewer",
"artifact_refs 必须包含至少一个非空证据引用",
"thresholds_met 必须为 true",
"embedding_deployment 不能为空",
"rerank_deployment 不能为空",
"sample_count 必须大于 0"
],
"evidence": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"environment": "postgresql",
"embedding_deployment": "",
"rerank_deployment": "",
"sample_count": 0,
"thresholds_met": false,
"metrics": {
"recall_at_5": 0,
"p95_latency_ms": 0
},
"hnsw": {
"m": 0,
"ef_construction": 0,
"ef_search": 0
}
}
},
{
"code": "stage4_distillation",
"title": "阶段 4:真实模型知识蒸馏闭环",
"status": "not_ready",
"source": "external_evidence_manifest",
"reasons": [
"验收状态尚未标记为 passed",
"verified_at 必须是带时区的 ISO 8601 时间",
"缺少验收人 reviewer",
"artifact_refs 必须包含至少一个非空证据引用",
"independent_review 必须为 true",
"anonymization_review_passed 必须为 true",
"published 必须为 true",
"retrieved_after_publish 必须为 true",
"sample_count 必须大于 0",
"services 缺少: embedding, postgresql, rerank, text_model"
],
"evidence": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"sample_count": 0,
"independent_review": false,
"anonymization_review_passed": false,
"published": false,
"retrieved_after_publish": false,
"services": []
}
},
{
"code": "stage4_documents",
"title": "阶段 4:真实文档安全导入闭环",
"status": "not_ready",
"source": "external_evidence_manifest",
"reasons": [
"验收状态尚未标记为 passed",
"verified_at 必须是带时区的 ISO 8601 时间",
"缺少验收人 reviewer",
"artifact_refs 必须包含至少一个非空证据引用",
"failure_recovery_verified 必须为 true",
"formats 缺少: DOCX, LOG, PDF, PPTX, TXT, XLSX",
"services 缺少: clamav, embedding, minio, postgresql"
],
"evidence": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"failure_recovery_verified": false,
"formats": [],
"services": []
}
},
{
"code": "stage6_channel",
"title": "阶段 6:真实企业渠道",
"status": "not_ready",
"source": "external_evidence_manifest",
"reasons": [
"验收状态尚未标记为 passed",
"verified_at 必须是带时区的 ISO 8601 时间",
"缺少验收人 reviewer",
"artifact_refs 必须包含至少一个非空证据引用",
"signature_verified 必须为 true",
"inbound_verified 必须为 true",
"outbound_verified 必须为 true",
"receipt_verified 必须为 true",
"idempotency_verified 必须为 true",
"provider 不能为空"
],
"evidence": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"provider": "",
"signature_verified": false,
"inbound_verified": false,
"outbound_verified": false,
"receipt_verified": false,
"idempotency_verified": false
}
},
{
"code": "stage6_identity",
"title": "阶段 6:真实企业身份与目录",
"status": "not_ready",
"source": "external_evidence_manifest",
"reasons": [
"验收状态尚未标记为 passed",
"verified_at 必须是带时区的 ISO 8601 时间",
"缺少验收人 reviewer",
"artifact_refs 必须包含至少一个非空证据引用",
"oidc_login_verified 必须为 true",
"group_claim_verified 必须为 true",
"failure_fallback_verified 必须为 true",
"ldap_directory_sync_verified 必须为 true",
"oidc_provider 不能为空",
"ldap_directory 不能为空"
],
"evidence": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"oidc_provider": "",
"ldap_directory": "",
"oidc_login_verified": false,
"group_claim_verified": false,
"failure_fallback_verified": false,
"ldap_directory_sync_verified": false
}
},
{
"code": "stage6_production_ops",
"title": "阶段 6:生产告警、调度与异地备份",
"status": "not_ready",
"source": "external_evidence_manifest",
"reasons": [
"验收状态尚未标记为 passed",
"verified_at 必须是带时区的 ISO 8601 时间",
"缺少验收人 reviewer",
"artifact_refs 必须包含至少一个非空证据引用",
"alerts_verified 必须为 true",
"backup_schedule_installed 必须为 true",
"offsite_encrypted_copy_verified 必须为 true",
"alert_receiver 不能为空",
"backup_schedule 不能为空",
"offsite_storage 不能为空"
],
"evidence": {
"status": "not_run",
"verified_at": "",
"reviewer": "",
"artifact_refs": [],
"alert_receiver": "",
"backup_schedule": "",
"offsite_storage": "",
"alerts_verified": false,
"backup_schedule_installed": false,
"offsite_encrypted_copy_verified": false
}
},
{
"code": "stage6_recovery",
"title": "阶段 6:隔离一致性恢复",
"status": "passed",
"source": "recovery_evidence",
"reasons": [],
"evidence": {
"schema_version": 1,
"status": "passed",
"verified_at": "2026-07-27T09:24:21Z",
"compose_project": "ai-ticket-restore-drill-5124",
"backup_id": "20260727T092235Z",
"duration_seconds": 106.57,
"database_smoke": "ticket_and_attachment_restored",
"object_storage_smoke": "marker_restored",
"django_check": "passed",
"artifact_refs": [
"docs/operations/recovery-drill-2026-07-27.md"
]
}
}
]
}

View File

@@ -0,0 +1,64 @@
# 产品蓝图统一验收
## 目的
`report_blueprint_readiness` 将产品蓝图阶段 2~6 的最终退出条件收敛为一个机器可读报告。
报告不会因为工程测试通过而替代真实案例或真实环境证据,也不会把合成案例计入阶段退出。
当前共检查 9 个门槛:
1. 阶段 2 脱敏真实案例智能建单指标。
2. 阶段 3 脱敏真实案例支持闭环指标。
3. 阶段 3 PostgreSQL、Embedding 与重排基准。
4. 阶段 4 真实模型知识蒸馏、独立审核、发布与重新检索。
5. 阶段 4 MinIO、ClamAV、PostgreSQL、Embedding 和六类文档导入。
6. 阶段 6 企业渠道签名、收发、回执与幂等。
7. 阶段 6 OIDC、组织声明、故障降级与 LDAP 目录同步。
8. 阶段 6 真实告警、备份调度与异地加密副本。
9. 阶段 6 数据库与对象存储隔离一致性恢复。
## 准备证据
阶段 2、3 的业务指标从平台评审记录实时计算。先按对应说明导入案例并逐案评审:
- `stage2-evaluation.md`
- `stage3-evaluation.md`
其余真实环境验收从以下模板开始:
```powershell
Copy-Item `
docs/product/acceptance/blueprint-external-evidence.template.json `
docs/product/acceptance/blueprint-external-evidence.json
```
只能填写验收结果、环境代号、指标和证据文件引用。清单会递归拒绝字段名包含
`password`、`secret`、`token` 或 `credential` 的内容,不得在其中保存任何真实凭据。
每个通过项必须包含带时区的 `verified_at`、`reviewer` 和至少一个 `artifact_refs`。
## 运行
目标数据库必须先应用当前迁移:
```powershell
cd backend
python manage.py migrate
python manage.py report_blueprint_readiness `
--evidence ../docs/product/acceptance/blueprint-external-evidence.json `
--output ../docs/product/acceptance/blueprint-readiness.current.json
```
CI 或正式退出评审使用非零退出码阻断未满足项:
```powershell
python manage.py report_blueprint_readiness `
--evidence ../docs/product/acceptance/blueprint-external-evidence.json `
--format json `
--fail-on-not-ready
```
若数据库未迁移、证据文件缺失、契约字段不完整、恢复记录无效或任一业务指标未达标,
命令都会输出 `not_ready`。只有 9 个门槛全部通过时,顶层 `exit_ready` 才会为 `true`。
仓库中的 `blueprint-readiness.current.json` 是当前环境快照,不是永久通过证明;每次正式
验收都应重新生成,并保留它引用的原始指标、运行日志、截图或审批记录。

View File

@@ -0,0 +1,63 @@
# 阶段 2 智能受理评估说明
该目录提供可重复执行的评估框架。`stage2-sample-cases.json` 仅包含合成脱敏样例,
用于验证导入、比对和指标计算,不得作为“脱敏真实案例集已验收”的证据。
`stage2-real-cases.template.json` 是禁用状态的真实案例结构模板,也不能直接作为证据。
## 真实案例要求
技术支持提供的案例应设置 `source_kind` 为 `anonymized_real`,并在导入前确认:
- 原始聊天、截图、日志和文档已经移除客户名称、账号、手机号、IP、业务编号等标识;
- `expected_fields` 由技术支持人工标注,而不是复制模型输出;
- `valid_input`、`expected_auto_created` 和 `expected_similar_ticket` 有明确审核结论;
- 对聊天顺序和业务时间有要求时提供 `expected_timeline`;时间原文、解析值与时区分开标注;
- 同一个案例可以对应多次受理运行,但指标会保留每次运行结果以便审计。
真实案例文件还需要覆盖以下输入组合,否则阶段退出报告会保持 `not_ready`:
- 至少一个图片案例;
- 至少一个文本加图片混合案例;
- 至少一个文档或日志案例;
- 至少一个无效输入案例,用于验证追问与人工接管路径。
## 执行流程
```powershell
cd backend
python manage.py import_intake_evaluation_cases ..\docs\product\acceptance\stage2-cases.json
python manage.py record_intake_evaluation --case <case-key> --draft <draft-public-id>
python manage.py report_stage2_acceptance --output ..\reports\stage2-acceptance.json
```
指标接口:`GET /api/tickets/intake-quality-metrics`。默认只统计
`anonymized_real` 案例;显式传入 `include_synthetic=true` 才会包含合成样例。
CI 或正式验收应增加严格退出检查:
```powershell
python manage.py report_stage2_acceptance `
--output ..\reports\stage2-acceptance.json `
--fail-on-not-ready
```
该命令仅在真实案例评审覆盖完整、输入模态覆盖完整、自动建单率和字段准确率达标,
且非空评估字段全部有证据时返回成功。使用 `--include-synthetic` 时报告状态固定为
`diagnostic`,永远不会把合成案例判定为阶段退出证据。
指标口径:
- 运行态自动建单率:所有 `problem_valid=true` 的非拒绝、非过期受理中,
`decision=auto_created` 且关联正式工单的比例。
- 案例集自动建单率:有效案例结果中实际自动建单的比例。
- 字段准确率:所有已评估字段中,与人工基准归一化后完全一致的字段比例;
按字段数量加权,不对空案例伪造 100%。
- 字段证据覆盖率:非空预期字段中,存在材料引用、原文摘录、定位、原始值或生成规则
的字段比例;该指标用于审计证据链,不替代字段准确率。
- 消息时间线准确率:按预期顺序逐项比对人工标注的角色、内容、时间原文、解析时间和
时区;案例可只声明需要核对的键。
- 同一案例存在多次评审运行时,当前质量指标只使用最新一次结果;历史结果仍保留用于
审计,避免旧模型运行与当前版本混算。
- 自动建单率和字段准确率只有在所有启用案例都完成评审后才返回达标/未达标结论;
覆盖不完整时达标状态保持 `null`。
- 真实案例未导入或未执行时,相关比率返回 `null`,达标状态也返回 `null`。

View File

@@ -0,0 +1,145 @@
{
"schema_version": 1,
"description": "阶段 2 脱敏真实案例模板。复制为 stage2-cases.json、替换全部 REPLACE_* 内容并完成脱敏复核后再导入;本模板全部 disabled,不能直接作为验收证据。",
"cases": [
{
"key": "real-mixed-images-REPLACE_001",
"name": "文本加多图混合输入",
"source_kind": "anonymized_real",
"valid_input": true,
"input_manifest": {
"source_text": "REPLACE_脱敏后的补充说明",
"materials": [
{
"file_name": "REPLACE_chat-01.png",
"type": "png"
},
{
"file_name": "REPLACE_chat-02.png",
"type": "png"
}
],
"anonymization_review": {
"reviewer": "REPLACE_复核人",
"reviewed_at": "REPLACE_YYYY-MM-DD",
"removed_identifiers": [
"客户名称",
"账号",
"手机号",
"IP",
"业务编号"
]
}
},
"expected_fields": {
"description": "REPLACE_人工标注的问题描述",
"category_code": "REPLACE_business_issue|technical_issue|data_issue|operation_issue",
"environment": "REPLACE_明确环境或空字符串",
"problem_started_at": "REPLACE_带时区 ISO 8601 或空字符串"
},
"expected_timeline": [
{
"role": "customer",
"content": "REPLACE_人工标注的脱敏消息",
"occurred_at": "REPLACE_带时区 ISO 8601 或空字符串",
"occurred_at_raw": "REPLACE_原始时间文本或空字符串",
"timezone": "REPLACE_原文时区或空字符串"
}
],
"expected_auto_created": true,
"expected_similar_ticket": false,
"notes": "REPLACE_审核结论与边界说明",
"enabled": false
},
{
"key": "real-image-only-REPLACE_002",
"name": "仅图片输入",
"source_kind": "anonymized_real",
"valid_input": true,
"input_manifest": {
"source_text": "",
"materials": [
{
"file_name": "REPLACE_chat.png",
"type": "png"
}
],
"anonymization_review": {
"reviewer": "REPLACE_复核人",
"reviewed_at": "REPLACE_YYYY-MM-DD",
"removed_identifiers": []
}
},
"expected_fields": {
"description": "REPLACE_人工标注的问题描述",
"category_code": "REPLACE_business_issue|technical_issue|data_issue|operation_issue"
},
"expected_timeline": [
{
"role": "customer",
"content": "REPLACE_人工标注的脱敏消息"
}
],
"expected_auto_created": true,
"expected_similar_ticket": false,
"notes": "REPLACE_审核结论与边界说明",
"enabled": false
},
{
"key": "real-document-REPLACE_003",
"name": "文档或日志输入",
"source_kind": "anonymized_real",
"valid_input": true,
"input_manifest": {
"source_text": "REPLACE_可选补充说明",
"materials": [
{
"file_name": "REPLACE_service.log",
"type": "log"
}
],
"anonymization_review": {
"reviewer": "REPLACE_复核人",
"reviewed_at": "REPLACE_YYYY-MM-DD",
"removed_identifiers": []
}
},
"expected_fields": {
"description": "REPLACE_人工标注的问题描述",
"error_information": "REPLACE_错误信息",
"attempted_actions": "REPLACE_已尝试动作或空字符串"
},
"expected_timeline": [
{
"role": "customer",
"content": "REPLACE_人工标注的脱敏消息"
}
],
"expected_auto_created": true,
"expected_similar_ticket": false,
"notes": "REPLACE_审核结论与边界说明",
"enabled": false
},
{
"key": "real-invalid-REPLACE_004",
"name": "无有效问题描述",
"source_kind": "anonymized_real",
"valid_input": false,
"input_manifest": {
"source_text": "REPLACE_脱敏后的无效输入",
"materials": [],
"anonymization_review": {
"reviewer": "REPLACE_复核人",
"reviewed_at": "REPLACE_YYYY-MM-DD",
"removed_identifiers": []
}
},
"expected_fields": {},
"expected_timeline": [],
"expected_auto_created": false,
"expected_similar_ticket": false,
"notes": "应进入追问或人工补充,不得自动创建正式工单。",
"enabled": false
}
]
}

View File

@@ -0,0 +1,137 @@
{
"schema_version": 1,
"description": "阶段 2 评估框架示例。全部为合成脱敏数据,不计入真实业务验收。",
"cases": [
{
"key": "synthetic-text-login-001",
"name": "生产环境登录失败文本",
"source_kind": "synthetic",
"valid_input": true,
"input_manifest": {
"source_text": "客户机构 A 反馈生产环境统一登录从 10:00 起提示服务异常。",
"materials": []
},
"expected_fields": {
"title": "生产环境统一登录服务异常",
"description": "客户机构 A 反馈生产环境统一登录从 10:00 起提示服务异常。",
"category_code": "technical_issue",
"environment": "生产环境"
},
"expected_auto_created": true,
"expected_similar_ticket": false,
"notes": "验证纯文本有效问题自动建单。"
},
{
"key": "synthetic-log-timeout-002",
"name": "日志附件接口超时",
"source_kind": "synthetic",
"valid_input": true,
"input_manifest": {
"source_text": "请排查回调任务持续超时。",
"materials": [
{"file_name": "callback-sanitized.log", "type": "log"}
]
},
"expected_fields": {
"description": "回调任务持续超时",
"category_code": "technical_issue"
},
"expected_auto_created": true,
"expected_similar_ticket": false,
"notes": "验证文档材料可读时仍按有效输入统计。"
},
{
"key": "synthetic-invalid-greeting-003",
"name": "无具体问题的问候",
"source_kind": "synthetic",
"valid_input": false,
"input_manifest": {
"source_text": "你好,在吗?",
"materials": []
},
"expected_fields": {},
"expected_auto_created": false,
"expected_similar_ticket": false,
"notes": "验证无有效问题时进入追问而不是建单。"
},
{
"key": "synthetic-duplicate-sync-004",
"name": "重复同步异常材料再次建单",
"source_kind": "synthetic",
"valid_input": true,
"input_manifest": {
"source_text": "生产环境数据同步任务停止更新,错误码 SYNC-504。",
"materials": [
{"file_name": "sync-504-sanitized.txt", "type": "text"}
]
},
"expected_fields": {
"description": "生产环境数据同步任务停止更新,错误码 SYNC-504。",
"category_code": "data_issue",
"environment": "生产环境"
},
"expected_auto_created": true,
"expected_similar_ticket": true,
"notes": "重复输入仍应创建独立工单,同时出现非阻断相似候选。"
},
{
"key": "synthetic-context-timeline-005",
"name": "结构化上下文与带时区消息时间线",
"source_kind": "synthetic",
"valid_input": true,
"input_manifest": {
"source_text": "2026-07-27 10:00(UTC+8),客户机构 A 反馈生产环境订单中心退款模块报错 REFUND-502;已重试三次,当前仍失败,希望尽快恢复。",
"materials": []
},
"expected_fields": {
"description": "生产环境订单中心退款模块报错 REFUND-502",
"environment": "生产环境",
"product_name": "订单中心",
"module_name": "退款模块",
"attempted_actions": "已重试三次",
"error_information": "REFUND-502",
"customer_request": "尽快恢复",
"current_result": "当前仍失败",
"problem_started_at": "2026-07-27T10:00:00+08:00"
},
"expected_timeline": [
{
"role": "customer",
"content": "生产环境订单中心退款模块报错 REFUND-502",
"occurred_at": "2026-07-27T10:00:00+08:00",
"occurred_at_raw": "2026-07-27 10:00(UTC+8)",
"timezone": "UTC+8"
}
],
"expected_auto_created": true,
"expected_similar_ticket": false,
"notes": "验证业务上下文、显式时区、字段证据和消息时间线。"
},
{
"key": "synthetic-ambiguous-time-006",
"name": "无时区时间不得猜测",
"source_kind": "synthetic",
"valid_input": true,
"input_manifest": {
"source_text": "客户说今天 10:00 起生产报表一直无法生成,但没有说明所在时区。",
"materials": []
},
"expected_fields": {
"description": "生产报表一直无法生成",
"environment": "生产环境",
"problem_started_at": ""
},
"expected_timeline": [
{
"role": "customer",
"occurred_at": "",
"occurred_at_raw": "今天 10:00",
"timezone": ""
}
],
"expected_auto_created": true,
"expected_similar_ticket": false,
"notes": "验证问题描述有效时仍可建单,但无时区的业务时间保持缺失并等待人工补全。"
}
]
}

View File

@@ -0,0 +1,108 @@
# 阶段 3 支持分析验收
本目录只提供评估框架、案例格式和执行口径。仓库中的合成数据只能验证工具链,不能作为
“脱敏真实案例已验收”或阶段 3 已退出的证据。
## 1. 案例文件
案例文件使用 UTF-8 JSON,`schema_version` 固定为 `1`:
可从 `stage3-real-cases.template.json` 复制真实案例模板;`stage3-sample-cases.json`
只用于本地验证导入和报告工具。
```json
{
"schema_version": 1,
"cases": [
{
"key": "order-status-auto-resolve",
"name": "订单状态回写延迟",
"source_kind": "anonymized_real",
"input_manifest": {
"ticket_no": "脱敏工单编号",
"ticket_summary": "生产环境订单状态未更新",
"expected_reason": "已发布方案匹配且风险策略允许"
},
"expected_solution_ids": [12],
"expected_auto_resolve": true,
"expected_manual_fallback": false,
"notes": "方案 ID 必须来自当前验收环境中的已发布方案",
"enabled": true
}
]
}
```
要求:
- `source_kind` 只能是 `anonymized_real` 或 `synthetic`;默认报告只统计前者。
- `expected_solution_ids` 使用验收环境中的正式方案 ID。没有正确方案时使用空数组。
- `expected_auto_resolve` 与 `expected_manual_fallback` 必须且只能有一个为 `true`。
- 自动解决案例必须提供至少一个期望方案 ID。
- 真实案例必须提供非空 `input_manifest`,但不得写入客户、人员、组织、账号、密钥或原始
附件内容。
导入:
```powershell
python manage.py import_support_evaluation_cases docs/product/acceptance/stage3-cases.local.json
```
## 2. 记录评审
先在真实 PostgreSQL、Embedding/重排和文本模型环境完成支持分析,再把案例与分析记录
绑定:
```powershell
python manage.py record_support_evaluation --case order-status-auto-resolve --analysis 123
```
也可调用:
```text
POST /api/tickets/support-evaluations
{
"case_key": "order-status-auto-resolve",
"analysis_id": 123
}
```
只有 Agent 运行成功且支持分析已完成后处理的记录可以进入指标。记录时会冻结并核对:
- Agent 候选方案是否命中期望方案。
- 引用序号是否全部存在于本次冻结引用列表。
- 符合条件的案例是否实际自动解决。
- 应人工处理的案例是否进入 `manual_recommendation`。
- 自动采纳的方案是否落在期望方案集合中。
同一案例可以评审多次,报告只使用该案例最新一条结果;历史结果保留用于审计。
## 3. 指标与退出报告
指标接口:
```text
GET /api/tickets/support-quality-metrics
```
生成可归档的 JSON 报告:
```powershell
python manage.py report_stage3_acceptance `
--format json `
--output artifacts/stage3-acceptance.json `
--fail-on-not-ready
```
默认退出要求:
- 所有启用的脱敏真实案例都有评审结果。
- 案例集同时覆盖允许自动解决、人工降级和无正确方案场景。
- 已发布方案自动匹配率不低于 50%。
- 符合自动处理条件的工单自动解决率不低于 30%。
- 错误自动复用率不高于 5%。
- 人工降级场景全部正确阻断自动解决。
- 所有评审结果的引用序号均可追溯到冻结引用。
`--include-synthetic` 只用于验证评估框架,报告状态固定为 `diagnostic`,永远不会把
`exit_ready` 设为 `true`。

View File

@@ -0,0 +1,20 @@
{
"schema_version": 1,
"cases": [
{
"key": "replace-with-anonymized-case-key",
"name": "替换为脱敏真实案例名称",
"source_kind": "anonymized_real",
"input_manifest": {
"ticket_no": "替换为脱敏工单编号",
"ticket_summary": "替换为不含客户身份和敏感信息的问题摘要",
"expected_reason": "说明允许自动解决或必须人工降级的业务依据"
},
"expected_solution_ids": [123],
"expected_auto_resolve": true,
"expected_manual_fallback": false,
"notes": "123 必须替换为验收环境中的已发布方案 ID",
"enabled": true
}
]
}

View File

@@ -0,0 +1,47 @@
{
"schema_version": 1,
"cases": [
{
"key": "synthetic-auto-resolve",
"name": "合成:高分低风险方案自动解决",
"source_kind": "synthetic",
"input_manifest": {
"ticket_summary": "生产环境订单状态长时间未更新",
"expected_reason": "已发布方案高分匹配、范围一致且风险策略允许"
},
"expected_solution_ids": [900001],
"expected_auto_resolve": true,
"expected_manual_fallback": false,
"notes": "仅验证评估框架,900001 需在测试环境替换为实际方案 ID",
"enabled": true
},
{
"key": "synthetic-risk-fallback",
"name": "合成:生产变更方案人工降级",
"source_kind": "synthetic",
"input_manifest": {
"ticket_summary": "需要修改生产配置才能恢复",
"expected_reason": "方案涉及生产变更,必须人工处理"
},
"expected_solution_ids": [900002],
"expected_auto_resolve": false,
"expected_manual_fallback": true,
"notes": "仅验证评估框架",
"enabled": true
},
{
"key": "synthetic-no-match",
"name": "合成:无正确方案",
"source_kind": "synthetic",
"input_manifest": {
"ticket_summary": "新问题,没有适用的已发布方案",
"expected_reason": "不得错误复用,应进入人工推荐"
},
"expected_solution_ids": [],
"expected_auto_resolve": false,
"expected_manual_fallback": true,
"notes": "仅验证评估框架",
"enabled": true
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,48 +1,67 @@
# AI 工单平台能力状态
更新日期:2026-07-16
更新日期:2026-07-27
状态定义:
| 状态 | 含义 |
|---|---|
| 真实 | 已接真实数据库或服务,具备自动化测试 |
| 演示 | 使用 Mock、确定性桩或独立概念页面 |
| 缺失 | 尚无可用实现 |
| 债务 | 已有实现与目标架构存在明确差距 |
| 工程完成 | 代码、迁移、自动化测试和本地可重复验证已经完成 |
| 真实验收通过 | 已在目标服务或脱敏真实案例上取得可追溯证据 |
| 待真实验收 | 工程完成,但仍缺企业外部服务或真实案例证据 |
| 未实现 | 蓝图要求尚无可用工程实现 |
## 当前能力
| 领域 | 能力 | 状态 | 说明 |
|---|---|---|---|
| 企业治理 | 登录、用户、用户组、角色、菜单权限 | 真实 | Django 权限与菜单 API 已实现 |
| 企业治理 | 操作审计 | 真实 | 已覆盖治理、工单以及 AI 渠道、版本和运行操作;敏感运行正文不进入普通审计 |
| 工单 | 创建、查询、编辑、分类状态流转、评论、导出 | 真实 | 后端与前端均使用真实 API |
| 工单 | AI 建单草稿 | 真实 | 自然语言起草、批量补齐、最多 5 轮逐问、人工修改、修订冲突、明确确认、幂等建单和整单决定已实现;真实文本闭环验收通过 |
| 工单 | 草稿图片与工单附件 | 真实 | JPEG/PNG/WebP 经签名解码、去 EXIF 后由 Django 代理写入 MinIO,确认时转为真实附件;未确认图片随草稿过期清理 |
| 工单 | 真实视觉模型建单 | 缺失 | 多模态协议、视觉模型能力和图片出境授权校验已实现并由模拟适配器覆盖;尚未完成真实视觉渠道验收 |
| 工单 | AI 建议 | 债务 | `Ticket.ai_solution` 位于业务主表,后续停止新增依赖 |
| 解决方案 | 维护、关联、采纳并关闭工单 | 真实 | 已有 API、事件和使用次数统计 |
| 知识 | 知识库、条目、文档文本、切片和检索 | 真实 | 基础 CRUD 与检索 API 可运行 |
| 知识 | 向量检索 | 演示 | 使用 JSON 哈希向量和应用内排序,不是 pgvector/真实 Embedding |
| AI 平台 | 模型渠道和真实模型测试 | 真实 | OpenAI-compatible 适配器、凭证加密/脱敏、文本/视觉能力标识、图片出境授权、异步测试和一次瞬时重试已实现;本地真实文本渠道验收通过 |
| AI 平台 | Skill 草稿、发布、Schema 和回滚 | 真实 | 受限模板、JSON Schema、不可变发布版本、克隆草稿和按版本回滚已实现 |
| AI 平台 | Agent 版本、有序执行和运行轨迹 | 真实 | 草稿沙箱、发布校验、Celery 有序执行、失败终止、结构修复、取消、快照和运行详情已实现 |
| AI 平台 | MCP | 缺失 | 不在本次演示范围 |
| 前端 | 研发管理工作台、两级导航、页面标签、个人中心 | 真实 | 使用真实治理与业务 API;桌面端人工验收已通过 |
| 前端 | 全局 Agent 助手面板 | 演示 | 仅做本地交互演示,页面持续显示演示标识,不写业务数据 |
| 部署 | PostgreSQL、Redis、MinIO 本地基础设施 | 真实 | `infra/docker-compose.local.yml` |
| 部署 | Celery worker 与 Beat | 真实 | 模型测试、Agent 运行与每日留存清理使用 Celery;本地完整编排包含 Redis worker 和 Beat |
| 企业治理 | 用户、用户组、角色、菜单和细粒度权限 | 工程完成 | API、前端与权限拒绝测试已覆盖 |
| 企业治理 | OIDC、目录同步和企业组映射 | 待真实验收 | 本地契约和治理界面完成,待企业 IdP/LDAP |
| 审计 | 工单、Agent、模型、知识、Tool、渠道和身份审计 | 工程完成 | 普通审计不保存凭据和敏感运行正文 |
| 工单 | 创建、编辑、状态机、评论、协作、归档和导出 | 工程完成 | 所有写入通过统一领域服务 |
| 工单 | 人工字段保护和字段证据 | 工程完成 | Agent 值保留证据,人工修改阻止静默覆盖 |
| 智能受理 | 文本、图片和六类文档自动建单 | 待真实验收 | 工程闭环完成,待脱敏真实案例指标 |
| 智能受理 | 材料校验、ClamAV、MinIO 和失败恢复 | 待真实验收 | 测试覆盖完成,待真实服务与不同文件类型 |
| 支持分析 | 混合检索、引用冻结和结构化建议 | 待真实验收 | 待真实 PostgreSQL、Embedding、重排和案例 |
| 自动化 | 方案复用、受控自动解决、客户回复和 SLA | 待真实验收 | 默认关闭自动解决,待真实错误复用率验证 |
| 知识 | 知识、排查方案和解决方案统一治理 | 工程完成 | 独立审核、发布、下线、回滚和不可变版本 |
| 知识 | 已解决工单知识蒸馏 | 待真实验收 | 待真实文本模型、独立审核和发布回检 |
| 知识 | 文档安全导入和向量索引 | 待真实验收 | 待真实 MinIO、ClamAV、PostgreSQL 和 Embedding |
| AI 平台 | 模型渠道、部署、凭据和调用记录 | 工程完成 | OpenAI-compatible,支持文本、视觉、向量和重排 |
| AI 平台 | Skill 与 Agent 版本和运行轨迹 | 工程完成 | 冻结配置、有序步骤、修复、取消和 SSE 事件 |
| Tool/MCP | HTTP MCP、统一目录、授权交集和风险确认 | 工程完成 | 内部只读 MCP 已通过真实 HTTP 端到端调用 |
| 渠道 | 签名入站、出站、回执和幂等 | 待真实验收 | 待企业服务群机器人联调 |
| 运维 | 健康、指标、告警、生产 Compose | 工程完成 | 待配置真实告警接收方 |
| 运维 | 一致性备份、校验和恢复 | 真实验收通过 | 隔离恢复已验证数据库、附件和 MinIO 一致性 |
| 运维 | 定时与异地加密备份 | 待真实验收 | 待目标生产主机和异地存储 |
## 当前质量基线
## 质量基线
- 后端测试:88 项通过;Ruff、迁移检查、Django system check 和数据库迁移通过。
- 前端测试:40 项通过;ESLint、TypeScript 类型检查和生产构建通过。
- 前端已按路由懒加载拆包,生产主入口约 479.90 KB,无 Vite 体积告警。
- `/concept` 设计实验室及其 Mock 数据已按产品决策删除;正式路由测试禁止重新引入概念页面。
- 本地桌面端界面人工验收已通过。
- 真实模型三步端到端脚本已通过:草稿沙箱与发布版本均成功,版本快照、结构修复、权限拒绝和审计脱敏符合约定。
- AI 平台配置 Demo Milestone 已完成;Phase 1 可信建单真实文本闭环已实现并验收。
- 真实视觉渠道验收仍待完成,因此不能宣称视觉建单正式可用。
- 后端:217 项测试通过。
- 前端:73 项测试通过。
- Ruff、Django system check 和迁移漂移检查通过。
- TypeScript、ESLint 和 Vite 生产构建通过。
- 生产 Compose 基础及 monitoring profile 配置通过。
- Linux 脚本语法和 `git diff --check` 通过。
- 隔离恢复演练验证工单、附件记录和 MinIO 对象一致恢复。
能力状态只依据已验证代码更新。页面存在、类型定义存在或 Mock 可交互,不视为真实能力。
## 蓝图退出状态
统一蓝图报告当前为 **1/9 个门槛通过**。已通过:
- 阶段 6 隔离一致性恢复。
仍待:
1. 阶段 2 脱敏真实受理案例。
2. 阶段 3 脱敏真实支持案例。
3. 真实 PostgreSQL、Embedding 和重排检索。
4. 真实模型知识蒸馏、审核、发布和回检。
5. 六类文档真实服务闭环。
6. 企业服务群机器人。
7. 企业 OIDC、LDAP 或目录服务。
8. 生产告警、定时备份和异地加密存储。
权威结果见[统一蓝图验收](acceptance/blueprint-readiness.md)和
[当前机器报告](acceptance/blueprint-readiness.current.json)。页面存在、类型定义存在、
Mock 可交互或合成案例通过,均不能替代真实环境验收。

View File

@@ -0,0 +1,106 @@
# 企业身份接入与验收
## 工程边界
当前仓库已经提供企业身份工程基线:
- OpenID Connect 授权码登录,服务端保存授权状态并校验 `state`、`nonce` 和 ID Token。
- 身份提供方配置、客户端密钥加密保存、启停和安全审计。
- 以 `(provider, subject)` 唯一绑定本地用户,不以可变邮箱作为默认身份主键。
- 首次登录可创建无本地密码账号;停用账号不能通过企业登录恢复访问。
- 企业组织声明只同步管理员显式登记的业务用户组映射,不覆盖其他手工用户组。
- 标准化目录记录可幂等批量同步,并保存完成、部分成功或失败的运行结果。
- LDAP 提供连接配置和标准化目录适配边界,尚未在应用进程内实现 LDAP 搜索或轮询。
工程完成不等于企业环境验收完成。真实 IdP、LDAP 目录、网络出口、证书和组织声明仍需按本文
最后的清单联调。
## 部署配置
1. 配置稳定的 `AI_CREDENTIAL_ENCRYPTION_KEY`。身份提供方密钥与模型、渠道凭据共用这套
Fernet 加密能力;密钥丢失后已有密文不可恢复。
2. 将 `FRONTEND_APP_URL` 设置为用户访问的前端 HTTPS 根地址。
3. 将 `OIDC_CALLBACK_BASE_URL` 设置为企业 IdP 可访问的后端 HTTPS 根地址。留空时,服务端
会从当前请求推导根地址。
4. 执行迁移和治理初始化:
```bash
python manage.py migrate
python manage.py bootstrap_governance
```
5. 在“系统治理 → 企业身份”新增 OIDC 提供方,并在 IdP 登记精确回调地址:
```text
https://<后端域名>/api/identity/auth/oidc/<provider-slug>/callback
```
生产 OIDC 地址必须使用 HTTPS;仅在 Django 调试模式下允许本机 `localhost` 或
`127.0.0.1` 使用 HTTP。
## OIDC 声明
默认声明映射如下,可在治理页按企业 IdP 的实际声明修改:
| 平台字段 | 默认声明 | 说明 |
|---|---|---|
| 稳定身份 | `sub` | 必填,同一提供方内不可变化 |
| 登录账号 | `preferred_username` | 首次创建本地账号时使用,冲突会生成唯一后缀 |
| 邮箱 | `email` | 用于资料同步,不默认用于绑定已有账号 |
| 显示名称 | `name` | 同步到本地显示名称 |
| 企业组织 | `groups` | 只匹配已登记的组织映射 |
默认禁止按邮箱自动链接已有账号,以避免邮箱声明错误导致账号接管。确需迁移存量账号时,应由
管理员评估 IdP 的邮箱验证策略后,在提供方 `configuration` 中显式启用
`allow_email_linking`,并先用脱敏账号演练。
## 目录适配器契约
治理页和 `POST /api/identity/providers/{id}/directory-sync` 接收标准化成员数组:
```json
{
"records": [
{
"subject": "employee-1001",
"username": "zhangsan",
"email": "zhangsan@example.com",
"display_name": "张三",
"active": true,
"groups": ["IT-Support"]
}
]
}
```
- `subject` 是必填稳定标识。
- 同一提供方和 `subject` 重复提交只会更新原身份。
- 单次最多 1000 条,单条冲突会记录在同步运行中,不会伪造整批成功。
- `active=false` 会停用对应本地账号。
- 连接 LDAP、HR 或 IAM 的可信适配器负责读取企业目录并转换为上述结构;浏览器和审计日志
不保存 Bind password。
## 接口与权限
| 接口 | 权限/用途 |
|---|---|
| `GET /api/identity/auth/providers` | 匿名读取已启用 OIDC 登录入口 |
| `GET /api/identity/auth/oidc/{slug}/start` | 启动授权码登录 |
| `GET /api/identity/auth/oidc/{slug}/callback` | IdP 回调、身份同步并建立 Django 会话 |
| `GET/POST/PATCH /api/identity/providers` | `system.setting.manage` 管理提供方 |
| `GET/POST/DELETE .../group-mappings` | `system.setting.manage` 管理受控组织映射 |
| `POST .../directory-sync` | `system.setting.manage` 执行标准化目录同步 |
密钥不会通过管理接口返回;操作审计只记录修改字段、提供方、计数和错误类型,不记录令牌、
Client secret 或 Bind password。
## 真实企业环境验收
- [ ] IdP 发现文档、JWKS 和令牌端点均通过受信任 HTTPS 证书访问。
- [ ] 正常授权码登录成功,篡改 `state`、错误 `nonce`、过期或错误签名 ID Token 均被拒绝。
- [ ] 同一 `sub` 重复登录只关联一个本地账号,账号名冲突不会串号。
- [ ] 停用提供方、停用本地账号和无效组织声明都按预期阻断或忽略。
- [ ] 企业组织新增、移除后只改变已登记映射对应的业务用户组。
- [ ] IdP 不可用时,本地受控管理员账号仍可完成应急登录。
- [ ] 登录成功、失败、提供方修改、映射变更和目录同步均可在审计日志追溯。
- [ ] LDAP/目录适配器在真实目录完成分页、超时、证书、增量和停用成员演练。

414
docs/product/stage-plan.md Normal file
View File

@@ -0,0 +1,414 @@
# AI 工单平台阶段计划
更新日期:2026-07-27
依据:[产品蓝图](./blueprint.md)
执行原则:按可验收业务闭环推进;每个里程碑通过回归后再进入下一项。
## 阶段总览
| 阶段 | 状态 | 目标 | 退出条件 |
|---|---|---|---|
| 阶段 1:领域基线 | 已完成 | 统一工单数据、权限、状态机和字段保护 | 工单写入具有唯一领域入口,人工字段受到保护 |
| 阶段 2:多模态智能建单 | 进行中 | 材料上传后自动解析,有效问题直接建单 | 文本、图片和文档可建单,证据可追溯,失败可人工接管 |
| 阶段 3:智能支持闭环 | 进行中 | Agent 检索、排查、复用方案并生成回复 | 建议有引用,自动解决受权限、策略和审计约束 |
| 阶段 4:知识审核闭环 | 进行中 | 已解决工单生成并发布知识 | 知识发布后重新进入检索,达到首个业务版本 |
| 阶段 5:Agent/MCP 扩展 | 已完成 | 统一 Tool、MCP、授权和风险控制 | 内部只读 HTTP MCP 已完成真实 HTTP Agent 调用 |
| 阶段 6:渠道与生产化 | 进行中 | 接入服务群并补齐生产运维 | 渠道幂等收发、监控、备份和恢复演练通过 |
## 跨阶段领域基线收口
状态:**已完成(2026-07-27)**
- [x] 工单详情展示完整评论历史、作者、时间和可见范围;新增评论校验内容、类型与
可见性,客户可见记录明确不等同于渠道送达。
- [x] 工单详情支持查看、添加和移除协作人/关注人;候选目录只返回启用账号,管理受
`ticket.assign` 权限约束,只读账号不会加载成员目录。
- [x] 重复添加同一协作关系保持幂等,不重复写入工单事件。
## 阶段 2 里程碑
### 2.1 自动建单纵向闭环
状态:**已完成(2026-07-25)**
- [x] 保留 `/api/ticket-drafts` 兼容接口,将草稿扩展为统一受理记录。
- [x] Agent 输出增加问题有效性、字段证据和消息时间线。
- [x] 有效问题描述形成后通过工单领域服务幂等自动建单。
- [x] 缺少业务字段时创建 `pending_info` 工单;完整时创建 `pending` 工单。
- [x] 原始图片转为正式附件,字段值记录来源、证据、置信度和 Agent 运行。
- [x] 结构化结果覆盖产品、模块、标签、已尝试动作、错误信息、客户诉求、当前结果和
四类业务时间;无显式时区时保留原文但不猜测解析时间。
- [x] 无效问题保留材料和追问;失败时支持重试或人工建单。
- [x] 创建页切换为智能受理语义,工单详情展示待补全信息与受理轨迹,并提供原位人工
补全抽屉;业务必填字段补齐后自动从 `pending_info` 进入 `pending`。
- [x] 后端及前端全量回归通过。
验收标准:
- 文本、图片及文本加图片均可启动受理。
- 有效描述不要求人工确认即可创建且只创建一张工单。
- 缺失分类、机构、环境等信息不会阻塞建单,也不会被模型伪造。
- 模型、对象存储或自动建单失败时原始材料仍可恢复。
验证结果:后端 106 项测试、前端 43 项测试全部通过;Django check、Ruff、
TypeScript、ESLint 与 Vite 生产构建通过。
### 2.2 通用附件与解析
状态:**已完成(2026-07-25)**
- [x] 将图片受理模型原位迁移为统一 `TicketDraftMaterial`,兼容旧 `/images` 接口和
`images` 响应字段。
- [x] 支持 JPEG、PNG、WebP、PDF、TXT、LOG、DOCX、XLSX 和 PPTX,统一保存 MinIO
对象、摘要、检测类型、扫描状态和解析状态。
- [x] 服务端依次执行扩展名、MIME、文件签名、单文件大小、文件数量和总量校验。
- [x] 接入 ClamAV INSTREAM 扫描;扫描未通过的材料不会进入解析或模型输入。
- [x] 支持 PDF、文本、日志和 Office 文档文本提取,并以材料 ID 作为 Agent 证据引用。
- [x] 扫描、解析或单份材料处理失败时只标记对应材料,原始对象继续保留。
- [x] 自动/人工建单转存全部材料,并同步扫描、解析、摘要和提取文本元数据。
- [x] 创建页支持通用材料选择和处理状态;详情页展示材料扫描与解析结果。
验收标准:
- 单文件最大 20 MB、单次最多 10 个、总量最大 100 MB,限制由后端配置返回。
- 文件伪装、MIME 不匹配和无效签名在进入对象存储前被拒绝。
- 恶意、扫描失败和解析失败材料不进入 Agent,且原件可追溯。
- 仅提交成功解析的文档或日志也能启动智能受理。
验证结果:后端 120 项测试、前端 44 项测试全部通过;Django check、迁移检查、Ruff、
TypeScript、ESLint 与 Vite 生产构建通过。
### 2.3 消息时间线、任务中心与 SSE
状态:**已完成(2026-07-27)**
- [x] 将受理结果中的消息时间线迁移为规范化实体,并关联受理记录、正式工单和来源材料。
- [x] 建立通用 `WorkItem` 任务模型,为 `pending_info` 工单创建唯一活动的
`ticket_missing_info` 任务,字段补齐或状态流转后自动完成。
- [x] 失败或取消的受理创建唯一 `ticket_intake_failed` 人工接管任务;重试、人工建单
或放弃受理后自动完成/取消,可从工作台恢复原受理记录。
- [x] 建立有序 `AgentRunEvent`,覆盖排队、材料解析、字段提取、正式建单、完成、
需补充和失败等运行事件。
- [x] 提供 `GET /api/agent-runs/{id}/events` SSE,支持 `Last-Event-ID` 和 `after`
游标续传,并校验运行所有者或运行查看权限。
- [x] 创建页使用 SSE 实时展示有序运行事件,断线时自动重连并以低频查询兜底。
- [x] 创建页支持取消排队中或运行中的受理;取消请求撤销 Celery 任务并保持 Agent
运行状态为 `cancelled`,不再错误改写为模型失败。
- [x] 工作台增加任务中心,工单详情展示活动待补全任务与规范化消息时间线。
验收标准:
- 同一工单最多存在一条活动待补全任务,Agent 或 Celery 重试不会制造重复任务。
- 补齐业务必填字段或将工单流转出 `pending_info` 后,待补全任务自动完成。
- SSE 事件序号单调递增;断线后只补发游标之后的事件,越权订阅返回 403。
- 页面恢复正在分析的受理时继续订阅原运行,完成、需补充或失败后刷新最终状态。
- 取消运行不会创建工单或丢失材料,随后仍可使用同一受理记录重试或转人工。
验证结果:后端 141 项测试、前端 49 项测试全部通过;Django check、迁移检查、Ruff、
TypeScript、ESLint 与 Vite 生产构建通过。
### 2.4 相似工单与阶段验收
状态:**工程能力已完成,真实案例验收待执行(2026-07-27)**
- [x] 使用 PostgreSQL 全文检索、标题三元组相似度和加权分数生成候选;SQLite
回退算法用于本地测试,不替代生产检索。
- [x] 自动建单和关键字段更新后刷新相似工单快照;查询失败不会回滚或阻塞正式工单。
- [x] 提供只读相似工单 API,详情页只展示候选、分数与跳转入口,不合并、不拦截重复建单。
- [x] 建立受理评审案例、评审结果、案例导入命令、人工记录命令和质量指标 API。
- [x] 将自动建单率与字段准确率分开统计;默认只计入脱敏真实案例,不把合成样例冒充业务验收。
- [x] 提供明确标记为 `synthetic` 的样例集与真实案例采集、导入、评审说明。
- [x] 评估结果同时核对问题有效性、字段证据和消息时间线;质量指标展示证据覆盖率与
时间线准确率,案例集未达到 100% 评审覆盖时不提前给出达标结论。
- [x] 增加阶段 2 验收报告命令:同一案例只使用最新评审结果,检查图片、文本加图片、
文档/日志和无效输入覆盖;合成案例报告永不具备阶段退出资格。
- [x] 提供默认禁用的真实案例模板和 CI 严格退出命令,不在仓库中伪造真实业务证据。
- [ ] 由技术支持提供并导入脱敏真实案例,逐案评审后确认自动建单率不低于 70%、
字段准确率不低于 90%。
验收标准:
- 相似候选排除当前工单,允许用户继续创建和处理独立工单。
- 相似度快照、算法版本和候选摘要可追溯,读取候选不产生业务写入。
- 没有真实评审结果时指标返回“无证据”,不得按 100% 或已达标展示。
- 真实案例包含输入材料清单、预期字段、预期建单结果和人工评审记录。
验证结果:后端 141 项测试、前端 49 项测试全部通过;Django check、迁移检查、Ruff、
TypeScript、ESLint 与 Vite 生产构建通过。当前未获得脱敏真实案例,因此阶段 2 保持
“进行中”,不宣称已达到 70%/90% 业务指标。
## 阶段 3 里程碑
### 3.1 真实工单支持分析纵向闭环
状态:**已完成(2026-07-27)**
- [x] 提供版本化 `support-analysis` Agent 和 Skill 发布命令,最终输出固定为分析摘要、
排查步骤、候选方案、客户回复草稿、引用和自动解决建议。
- [x] 从真实工单详情启动已发布 Agent;同一工单已有排队中或运行中的分析时复用原运行,
防止重复提交。
- [x] 检索范围只包含已发布知识、已发布解决方案和已解决/已关闭历史工单,草稿和未发布
内容不进入 Agent 输入。
- [x] 按分类、关联系统和环境过滤适用范围,冻结来源类型、ID、版本、标题、片段、分数、
适用范围和自动解决风险策略。
- [x] Agent 输出只能引用冻结列表内的排名和方案 ID;引用越界或自动解决建议不满足
0.85、范围及风险条件时,将运行标记为失败并保留人工处理入口。
- [x] 解决方案增加“允许自动解决、需要人工操作、需要外部确认、涉及生产变更”策略字段。
- [x] 工单详情展示运行状态、结构化建议、回复草稿和按排名排列的检索依据,并可跳转
Agent 运行轨迹。
- [x] 启动行为记录工单事件和操作审计;需要工单、知识、方案和 Agent 四类权限。
验收标准:
- 支持分析运行必须关联真实工单和已发布 Agent 版本,不能使用后台演示输入替代。
- 草稿知识、草稿方案和未解决历史工单不能出现在冻结引用中。
- 模型不能引用检索范围外的来源或方案;不可信结果不得显示为成功运行。
- 启动失败、模型失败和引用校验失败均不改变工单状态,可继续人工排查或重新运行。
验证结果:后端全量 217 项、前端全量 73 项测试通过;Django check、迁移漂移检查、
Ruff、TypeScript、ESLint 与 Vite 生产构建全部通过。阶段 3.1 定向权限与运行回归
14 项通过。
### 3.2 正式混合检索与重排
状态:**进行中**
- [x] 为知识分块增加 1536 维 pgvector 字段、vector 扩展迁移和 HNSW cosine 索引;
旧 JSON 向量暂保留用于平滑重建。
- [x] 接入模型中心 `embedding` 能力和 OpenAI-compatible Embeddings API;生产默认禁止
哈希回退,测试环境保留明确的 portable 回退。
- [x] PostgreSQL 使用全文与 pgvector 余弦双路召回;按可配置的文本、向量和范围权重
合并重排,SQLite 只承担测试兼容。
- [x] 冻结召回通道、文本/向量/范围分数、权重、查询模型和分块模型,并提供
`rebuild_knowledge_embeddings` 重建命令。
- [x] 将已解决或已关闭历史工单纳入持久化向量索引;状态回退、归档和字段更新会在事务
提交后同步索引,重建命令同时覆盖历史工单。
- [x] 知识条目增加分类、关联系统和环境结构化适用范围;检索先排除明确冲突范围,再参与
范围评分,未知或停用分类不能写入。
- [x] 模型中心增加可选 `rerank` 能力;重排结果与模型快照进入检索审计,模型缺失、超时
或输出无效时保持加权排序并明确标记降级。
- [ ] 在 PostgreSQL + 真实 Embedding 服务环境完成召回率、延迟和 HNSW 参数验收。
当前验证:后端全量 217 项、前端全量 73 项测试通过;Django check、迁移漂移检查、
Ruff、TypeScript、项目约定的 `eslint src` 和 Vite 生产构建通过。PostgreSQL + 真实
Embedding/重排服务的召回率、延迟和 HNSW 参数验收仍是本里程碑的退出条件。
### 3.3 方案复用、自动解决与客户回复任务
状态:**已完成(2026-07-27)**
- [x] 实现 0.85 阈值、分类/范围一致、发布状态、风险条件、用户权限、Agent 权限和
全局策略的统一自动解决判定。
- [x] 满足条件时通过工单领域服务复用方案并标记已解决;冲突、低置信度或任一策略关闭时
降级为人工推荐。
- [x] Agent 版本显式声明 `allowed_actions`,管理界面可授权 `ticket.resolve`;运行快照冻结
Agent 权限,不能因后续配置变化扩大既有运行权限。
- [x] 建立正式客户回复任务、草稿、最终话术、版本化编辑记录、审批冻结和发送确认;
渠道出站只能引用冻结的任务版本,只有送达回执才自动确认回复事实;`replied_to_customer`
仅保留为兼容镜像,不再作为回复事实来源。
- [x] 自动解决判定、方案采纳、回复编辑和发送确认均写入工单事件与操作审计;前端展示
自动执行结果或逐项人工降级原因。
验证结果:后端阶段 3.3 定向 7 项、前端工单详情 7 项测试通过;阶段 3.3 完成时后端
全量 217 项、前端全量 73 项通过,Django check、迁移漂移检查、Ruff、TypeScript、
ESLint 与 Vite 生产构建全部通过。
### 3.4 任务中心、SLA 与阶段验收
状态:**进行中**
- [x] 将待回复、待关闭和支持分析失败接入统一任务中心;任务创建、去重、完成和取消
跟随领域状态自动收口。
- [x] 为任务冻结可配置截止时间,提供活动、即将超时、已超时、按时完成和超时完成统计;
工作台展示任务类型、截止时间和 SLA 状态,首期不自动升级。
- [x] 增加阶段 3 脱敏案例导入、支持分析结果评审、质量指标 API 和退出报告命令;同一
案例只取最新结果,合成案例固定为诊断状态。
- [x] 退出报告统一计算方案匹配率、符合条件自动解决率、错误自动复用率、人工降级
准确率和冻结引用有效率,并检查自动、人工和无正确方案三类案例覆盖。
- [ ] 使用脱敏真实案例验证方案匹配、错误复用、自动解决和人工降级指标。
- [x] 完成阶段 3 工程全量回归并提供可用于 CI 的退出报告;真实案例或真实环境证据
不足时报告必须返回 `not_ready`,不得提前宣称阶段通过。
当前验证:阶段 3 验收工具定向后端 3 项、任务/SLA 定向后端 3 项和前端工作台 1 项通过;
最终全量回归为后端 217 项、前端 73 项,Django check、迁移漂移检查、Ruff、TypeScript、
ESLint 与 Vite 生产构建全部通过。
阶段 3.2 的真实 PostgreSQL/Embedding/重排环境验收和本里程碑的脱敏真实案例指标
尚未满足,因此阶段 3 继续保持“进行中”。
## 阶段 4 里程碑
### 4.1 统一知识资产治理
状态:**已完成(2026-07-27)**
- [x] 为知识条目、排查方案和解决方案建立统一 `GovernedAsset` 与不可变版本记录。
- [x] 新建资产一律保存为草稿,不再接受客户端绕过审核直接发布。
- [x] 实现草稿编辑、提交审核、独立审核、驳回、发布、下线、版本比较和回滚。
- [x] 阻止提交人审核自己的版本;新版本发布后自动下线旧版本,回滚只创建可追溯新草稿。
- [x] 兼容迁移已有知识、排查方案和解决方案,并保留其发布/下线状态。
- [x] 发布或下线在事务提交后异步重建/清理知识分块与检索索引。
- [x] 提供工单引用、方案采纳、支持分析运行和 Agent 运行影响范围 API。
- [x] 资产提交审核时创建唯一 `asset_review` 任务,通过或驳回后自动完成。
### 4.2 已解决工单知识蒸馏
状态:**工程能力已完成,真实环境闭环待验收(2026-07-27)**
- [x] 提供版本化 `knowledge-distillation` Agent 和 Skill 发布命令,固定知识价值评分、
冻结引用、知识草稿、排查方案草稿和可选解决方案草稿输出契约。
- [x] 工单进入 `resolved` 后在事务提交回调中异步启动知识价值评估;重复投递复用已有
活动或成功运行,不重复生成知识资产。
- [x] Agent 输入冻结已发布知识、已发布方案和已解决历史工单;输出引用不能越出冻结范围。
- [x] Prompt 明确隔离不可信指令并要求去除客户、人员、组织、账号、密钥等身份或敏感信息。
- [x] 可信结果在同一事务内生成知识、排查方案和可选解决方案草稿,并统一进入版本治理;
生成方案默认禁止自动解决且要求人工操作。
- [x] 模型、检索、任务入队或后处理失败时创建唯一
`knowledge_distillation_failed` 人工接管任务,不影响已解决工单事实。
- [x] 工单详情展示蒸馏运行、四类评分、生成草稿和运行轨迹;知识治理中心提供编辑、提交、
审核、驳回、版本比较、影响范围和回滚界面。
- [x] 知识条目和解决方案创建页移除直接发布选项,明确双人审核路径。
- [ ] 在真实 PostgreSQL、Embedding/重排和文本模型环境发布 Agent,使用脱敏真实已解决
工单完成“评估 → 草稿 → 独立审核 → 发布 → 重新检索”端到端验收。
当前验证:后端全量 217 项、前端全量 73 项测试通过;Django check、迁移漂移检查、
Ruff、TypeScript、ESLint 与 Vite 生产构建全部通过。真实模型环境、真实案例去标识化质量
和发布后召回效果尚未验收,因此阶段 4 继续保持“进行中”,不提前宣称达到首个业务版本
交付条件。
### 4.3 知识文档安全导入闭环
状态:**工程能力已完成,真实环境闭环待验收(2026-07-27)**
- [x] 知识文档支持 PDF、TXT、LOG、DOCX、XLSX 和 PPTX 原件上传,沿用统一的扩展名、
MIME、文件签名和 20 MB 大小校验。
- [x] 原件先保存到对象存储,再异步执行恶意文件扫描、文本解析、分块和向量索引;记录
SHA-256、扫描结果、处理次数、任务 ID 和索引完成时间。
- [x] 扫描、解析、索引或任务入队失败时保留原件和失败原因;非恶意失败可重新入队,
恶意文件保持隔离且禁止通过下载接口取回。
- [x] 重复任务只允许一个 Worker 领取待处理文档;已成功或正在处理的文档不会重复增加
处理次数或并发重建索引。
- [x] 提供文档列表、上传、失败重试和原件下载 API,并继续保留旧文本录入接口作为兼容
路径;API 分别受知识查看和管理权限约束。
- [x] 知识库页面增加“原件 → 安全扫描 → 文本解析 → 向量索引”导入队列,展示知识库、
文件元数据、扫描/处理状态、失败原因、处理次数,并自动刷新活动任务。
- [ ] 在真实 MinIO、ClamAV、PostgreSQL 和 Embedding 服务环境,以不同 Office/PDF/TXT
样本执行上传、扫描、解析、索引、下载和失败恢复验收。
当前验证:知识文档定向后端 11 项、前端 2 项通过;最终全量回归为后端 217 项、前端
73 项,Django check、迁移漂移检查、Ruff、TypeScript、ESLint 与 Vite 生产构建全部通过。
真实对象存储、扫描器和正式向量服务仍待环境验收,因此阶段 4 状态不变。
## 阶段 5 里程碑
### 5.1 统一 Tool/MCP 安全底座
状态:**已完成(2026-07-27)**
- [x] 建立统一工具服务、工具目录、用户/用户组/Agent 授权、调用和高风险确认实体。
- [x] 支持远程 HTTP MCP `tools/list` 同步和 `tools/call` JSON-RPC 调用,访问令牌加密保存,
API 只返回是否已配置,不回传明文。
- [x] 工具输入按同步的 JSON Schema 校验;同一工具和幂等键只形成一条调用记录。
- [x] 有效权限同时检查用户全局调用权限、用户/用户组工具授权;关联 Agent 运行时继续
检查运行快照 `allowed_actions` 和 Agent 工具授权。
- [x] 工具风险分为只读、低风险写和高风险;高风险调用只创建待确认记录和任务,
非申请人通过后才执行,拒绝后不调用外部服务。
- [x] 冻结授权与风险快照,记录同步和调用结果审计,不在审计摘要中保存工具完整输出。
- [x] 完成 Tool/MCP 管理页面:支持服务接入与同步、风险分层、用户/用户组/Agent
授权规则、受控试运行、调用轨迹和高风险独立确认。
- [x] 补齐服务更新、授权列表和调用列表接口;调用审计展示申请人、确认原因、输入输出、
授权和风险快照,普通调用者只可查看自己的记录。
- [x] 提供受独立 Bearer Token 保护的 `/internal-mcp`,以 `search_tickets` 查询真实、
未归档工单数据;令牌未配置时网关关闭,不复用用户会话认证。
- [x] 使用真实 HTTP 测试服务器完成 `tools/list → 目录同步 → Agent 版本动作快照 →
Agent 工具授权 → tools/call → 结构化结果与审计快照` 端到端验收。
当前验证:阶段 5.1 后端定向 6 项(其中 1 项为真实 HTTP Agent 调用)、前端治理页面
定向 1 项通过;后端全量 217 项、前端全量 73 项通过,Django check、迁移漂移检查、
Ruff、TypeScript、ESLint 和 Vite 生产构建全部通过。部署时必须配置
`INTERNAL_MCP_TOKEN`,并在工具治理页使用相同令牌接入当前服务的 `/internal-mcp`。
### 5.2 步骤级模型绑定与运行快照
状态:**已完成(2026-07-27)**
- [x] `AgentStepBinding` 支持可选模型部署;未指定时继承 Agent 版本默认部署,既有 Agent
和管理命令无需迁移配置即可继续运行。
- [x] 草稿更新 API、版本序列化和草稿克隆完整保留步骤模型覆盖;只允许
`text_chat`、`vision_chat` 作为 Agent 步骤能力,发布时拒绝停用渠道或部署。
- [x] `AgentRunStep` 冻结实际使用的部署,运行配置快照逐步骤记录部署、渠道、模型、
能力和是否继承,历史运行不受后续配置修改影响。
- [x] 运行时按步骤选择部署;图片只发送给 `vision_chat` 步骤,且每个视觉步骤的渠道
都必须完成图片出境授权,文本步骤不会接收图片内容。
- [x] 智能建单的图片可用性和执行前检查改为按有效步骤模型计算,支持“默认文本模型 +
步骤视觉模型”,并阻断未授权或停用的视觉部署。
- [x] Agent 管理页可为每个步骤选择继承默认模型或独立部署,版本记录展示独立绑定数量;
运行轨迹展示每一步实际使用的模型和能力。
当前验证:步骤绑定、草稿克隆、非法能力、运行部署选择、视觉材料路由、出境拦截、
配置快照和建单可用性定向后端 33 项通过;AI 平台页面定向前端 5 项通过。最终全量
回归为后端 217 项、前端 73 项,Django check、迁移漂移检查、Ruff、TypeScript、ESLint、
Vite 生产构建和 `git diff --check` 全部通过。
## 阶段 6 里程碑
### 6.1 通用渠道适配与生产运维基线
状态:**工程基线与隔离恢复已验收,真实渠道和生产配置待验收(2026-07-27)**
- [x] 建立 `ChannelEndpoint`、会话、消息和回执实体,凭证加密保存,管理 API 不回传明文。
- [x] 提供 HMAC-SHA256 签名入站 Webhook;同一渠道和外部消息 ID 只保存一次,并记录操作审计。
- [x] 出站消息只接受已确认的 `CustomerReplyTask` 当前版本,并冻结回复内容、工单和版本;
同一任务版本只能进入一个渠道会话,调用方幂等键去重,事务提交后进入 Celery 投递。
- [x] 保存外部消息 ID、发送/送达时间和失败原因;失败消息沿用原记录幂等重试,只有
`delivered` 回执才把回复任务标记为已发送并完成对应待回复任务。
- [x] 回执按消息、类型和外部回执 ID 去重;送达、已读和失败结果更新同一出站消息。
- [x] 完成渠道治理页面,展示适配器、脱敏凭证状态、Webhook 地址、收发时间线和
失败重试;正式发送从工单回复任务发起,不提供任意文本直发入口。
- [x] 增加存活、就绪探针和 Prometheus 文本指标;就绪探针检查数据库与缓存,指标接口
支持专用令牌和 Bearer 令牌。
- [x] 增加可选 Prometheus/Alertmanager 生产编排、失败与积压告警规则、持久化存储、
本机端口绑定和基于 Docker secret 的告警接收方配置。
- [x] 增加独立生产 Compose、Gunicorn、静态 Nginx、服务健康检查和重启策略。
- [x] 增加 PostgreSQL 与 MinIO 备份、SHA-256 校验、恢复脚本、受保护的备份裁剪脚本、
cron 调度示例和生产运行手册。
- [x] 增加 Windows PowerShell 备份、校验、恢复和自动隔离演练入口;对象归档使用固定
辅助容器挂载 MinIO 数据卷,不依赖 MinIO 镜像内置 `tar`;生产备份默认冻结业务写入
服务并在退出时恢复原运行集合。
- [x] 增加 OIDC 授权码登录工程基线:提供方密钥加密、`state`/`nonce`/ID Token 校验、
`(provider, subject)` 外部身份绑定、无密码账号创建、失败审计和本地登录降级。
- [x] 增加企业身份治理页、受控组织映射和标准化目录同步运行;LDAP 保留加密连接配置与
可信适配器契约,不在浏览器或审计日志保存 Bind password。
- [ ] 与至少一个真实企业服务群机器人完成签名入站、出站和回执联调。
- [ ] 与至少一个真实企业 IdP 完成 OIDC 登录、组织声明和故障降级联调,并完成 LDAP/目录
适配器的真实目录验收。
- [x] 在独立 Compose 项目完成数据库与对象存储一致性恢复演练;备份
`20260727T092235Z` 在 106.57 秒内恢复,工单、附件、对象读取和 Django check 冒烟通过。
- [ ] 配置真实生产告警接收方、安装备份 cron,并将校验后的备份复制到异地加密存储。
当前验证:企业身份定向后端 6 项、前端 4 项通过;后端全量 217 项、前端全量 73 项测试
通过;Django check、迁移漂移检查、
Ruff、TypeScript、ESLint、Vite 生产构建和 `git diff --check` 全部通过。生产 Compose
(含 monitoring profile)配置校验及备份、恢复、裁剪脚本语法检查通过;独立 Docker
恢复演练也已通过。真实企业渠道、真实 IdP/LDAP 目录、真实告警接收方和异地加密备份
尚未执行,因此阶段 6 保持“进行中”。
### 跨阶段最终退出报告
- [x] 增加 `report_blueprint_readiness`,统一聚合阶段 2/3 真实案例指标、阶段 3/4/6
外部验收证据和机器可读恢复记录。
- [x] 外部证据契约要求验收人、带时区时间和原始证据引用,并递归拒绝凭据类字段。
- [x] 数据库未迁移、证据缺失或专项字段不完整时稳定返回 `not_ready`;CI 可使用
`--fail-on-not-ready` 阻断错误宣称完成。
当前环境报告为 **1/9 个门槛通过**:隔离一致性恢复已通过;阶段 2 尚无脱敏真实案例,
本地数据库尚未应用阶段 3 评估表迁移,其余 6 项外部证据尚未执行。报告见
`docs/product/acceptance/blueprint-readiness.current.json`。
## 质量门槛
- 后端:`pytest`、Ruff 全部通过。
- 前端:Vitest、TypeScript、ESLint 和生产构建全部通过。
- 必测场景:有效/无效文本、单图/多图、字段缺失、显式/缺失时区、字段证据、重复任务、
失败接管、取消与重试、权限不足、对象存储失败、人工字段保护、人工降级、冻结引用越界
和运行轨迹越权,以及知识自审拦截、发布版本不可变、回滚新版本和蒸馏重复投递。