# AI 模块审计报告

> 审计日期：2026-06-25
> 审计范围：`src/modules/ai/` 全部代码 + `src/app/api/ai/` 路由 + app 层接入点
> 审计依据：`docs/architecture/004_architecture_impact_map.md`、`docs/architecture/005_architecture_data.json`、`docs/standards/coding-standards.md`、项目硬约束
> 审计方法：逐文件源码审阅 + 架构图一致性比对 + 角色-权限映射核对 + 行业标杆对标（Khanmigo / Duolingo Max / Squirrel AI / Century Tech）

---

## 一、现有实现概要

### 1.1 文件分布（共 32 个文件）

```
src/modules/ai/
├─ types.ts                          330 行  AiService / AiClientService 接口 + 业务类型
├─ schema.ts                         248 行  Zod 校验（输入 + AI 输出）
├─ actions.ts                        415 行  10 个 Server Action（含权限校验）
├─ data-access.ts                    138 行  内存事件存储 + 使用统计聚合
├─ services/
│  ├─ ai-service.ts                  478 行  DefaultAiService 实现（封装 shared/lib/ai）
│  ├─ prompt-templates.ts            300 行  9 套 System Prompt 常量
│  ├─ usage-tracker.ts               100 行  trackAiUsage + withAiTracking
│  └─ content-safety.ts              291 行  输入/输出过滤 + 每日限额（原子操作）
├─ context/
│  ├─ ai-client-provider.tsx          62 行  React Context 注入 AiClientService
│  └─ create-ai-client-service.ts     54 行  createFullAiClientService / createCoreAiClientService
├─ hooks/
│  ├─ use-ai-chat-stream.ts          155 行  SSE 流式聊天 + localStorage 持久化
│  ├─ use-ai-chat.ts                  57 行  非流式聊天（⚠ 死代码，未被引用）
│  ├─ use-ai-suggestion.ts            72 行  相似题 / 批改建议
│  ├─ stream-utils.ts                135 行  SSE 解析纯函数
│  ├─ use-floating-ball.ts           160 行  悬浮球组合 hook
│  ├─ use-drag-position.ts           130 行  拖拽 hook
│  └─ use-position-persistence.ts      99 行  位置 localStorage
├─ components/
│  ├─ ai-assistant-widget.tsx        329 行  全局悬浮球 + 上下文感知 + Sheet
│  ├─ ai-chat-panel.tsx              417 行  聊天面板（card / widget 双变体）
│  ├─ ai-error-boundary.tsx           31 行  SectionErrorBoundary 包装
│  ├─ ai-skeleton.tsx                 47 行  AiSuggestionSkeleton / AiChatSkeleton
│  ├─ ai-suggestion-card.tsx         178 行  相似题卡片（⚠ 死代码，未被引用）
│  ├─ ai-provider-selector.tsx        89 行  表单字段（react-hook-form）
│  ├─ ai-markdown-renderer.tsx       162 行  Markdown + 图表代码块渲染
│  ├─ ai-chart-renderer.tsx          351 行  Recharts 4 图表（bar/line/pie/radar）
│  ├─ ai-grading-assist.tsx          173 行  教师批改辅助
│  ├─ ai-error-book-analysis.tsx     246 行  学生错题本 AI 分析
│  ├─ ai-lesson-content-generator.tsx 180 行  教师备课内容生成
│  ├─ ai-question-variant-generator.tsx 218 行  题目变体生成
│  ├─ ai-usage-dashboard.tsx         221 行  管理员使用统计
│  ├─ ai-child-summary.tsx           186 行  家长学情摘要（⚠ 未接入页面）
│  └─ ai-study-path.tsx              200 行  学生学习路径（⚠ 未接入页面）
└─ src/app/api/ai/
   ├─ chat/route.ts                  196 行  非流式聊天端点
   └─ chat/stream/route.ts           237 行  SSE 流式端点
```

### 1.2 数据流

```
app/(dashboard)/layout.tsx
  │ 模块级 const aiClientService = createFullAiClientService()
  ▼
<AiClientProvider service={aiClientService}>  ← React Context
  │
  ├─ <AiAssistantWidget />                       ← 全局悬浮球
  │     └─ useAiClientOptional() / useFloatingBall()
  │           └─ <AiChatPanel variant="widget">
  │                 └─ useAiChatStream()  →  fetch('/api/ai/chat/stream')
  │                                                      │
  │                                                      ▼
  │                                 route.ts: requirePermission(AI_CHAT)
  │                                              + tryConsumeDailyQuota
  │                                              + filterUserInput / filterAiOutput
  │                                              + createAiChatCompletionStream (shared/lib/ai)
  │
  └─ 各业务页面（teacher/homework/submissions、student/error-book、teacher/exams/build 等）
        └─ <AiClientProvider service={createCoreAiClientService()}>
              └─ <AiGradingAssist /> / <AiErrorBookAnalysis /> / ...
                    └─ useAiClient().suggestGrading(...) → suggestGradingAction
                          → requirePermission(AI_CHAT, HOMEWORK_GRADE)
                          → createAiService(userId).suggestGrading(input)
                                → withAiTracking(...)
                                      → createAiChatCompletion (shared/lib/ai)
```

### 1.3 架构图记录情况

`005_architecture_data.json` 中 `modules.ai` 节点记录了完整的依赖矩阵、exports 清单、集成点、权限点、安全策略、流式特性、i18n 命名空间。

**但比对发现两处与实际实现不一致**（详见 §二 P0-2）：
- `ai.integrations.parent-dashboard` 声称 `AiChildSummary` 接入 `parent/dashboard` 页面 → 实际未接入
- `ai.integrations.student-learning` 声称 `AiStudyPath` 接入 `student/learning/study-path` 页面 → 实际该路由不存在

---

## 二、现存问题与原因分析

### P0 — 紧急且阻断使用

#### P0-1：家长角色完全缺失 `AI_CHAT` 权限

- **位置**：[permissions.ts](file:///e:/Desktop/CICD/src/shared/lib/permissions.ts#L161-L176) `ROLE_PERMISSIONS_SEED.parent` 数组
- **问题**：parent 角色权限清单中**没有任何** `Permissions.AI_CHAT`，但：
  - [actions.ts](file:///e:/Desktop/CICD/src/modules/ai/actions.ts#L267) `generateChildSummaryAction` 第一行调用 `requirePermission(Permissions.AI_CHAT)` → 家长调用必返回 403
  - [actions.ts](file:///e:/Desktop/CICD/src/modules/ai/actions.ts#L296) `recommendStudyPathAction` 同上
  - `/api/ai/chat/route.ts` L49 同上
  - `AiChildSummary` / `AiStudyPath` 组件存在但家长/学生路径下完全无法使用
- **违反规则**：
  - 项目硬约束「所有 Server Action 必须调用 `requirePermission()` 进行权限校验」—— 校验逻辑本身正确，但权限未授予
  - 项目硬约束「家长需要的功能应被授权」（K12 系统家长是关键角色）
- **后果**：家长角色付费的 AI 学情摘要功能在生产环境 100% 失败；学生使用学习路径推荐时若依赖家长代调也会失败

#### P0-2：架构图虚构集成（AiChildSummary / AiStudyPath 完全未接入）

- **位置**：
  - [005_architecture_data.json](file:///e:/Desktop/CICD/docs/architecture/005_architecture_data.json#L19725-L19744) `ai.integrations.parent-dashboard` / `ai.integrations.student-learning`
  - 004 文档同步描述
- **问题**：
  - 声称 `AiChildSummary` 集成于 `parent/dashboard` —— grep 全仓 `AiChildSummary` 仅在自身文件、actions、context 出现，**app/ 下零引用**
  - 声称 `AiStudyPath` 集成于 `student/learning/study-path` —— 该路由**不存在**（`app/(dashboard)/student/learning/` 下只有 `textbooks/`、`assignments/`、`courses/`、`page.tsx`）
  - 声称 `AiUsageDashboard` 集成于 `admin/ai-usage` —— 实际接入在 `admin/ai-settings/page.tsx`（路径不一致）
- **违反规则**：
  - 项目硬约束「如果发现项目中存在架构图未记录的模块、函数、表、路由等，必须优先完善架构图信息」
  - 项目硬约束「改码必同步图」—— 反向也成立：图中记录的集成必须真实存在
- **后果**：依赖架构图做影响分析的开发者会误以为功能已上线，跳过实现；测试用例遗漏；产线功能缺失

#### P0-3：`getAiUsageStatsAction` 错误消息 i18n 键错误

- **位置**：[actions.ts](file:///e:/Desktop/CICD/src/modules/ai/actions.ts#L381)
- **问题**：管理员查询使用统计失败时返回 `t("error.chatFailed")`（"AI 请求失败"/"AI request failed"），与场景不符
- **后果**：管理员看到"AI 请求失败"误以为是 AI 调用失败，实为统计查询失败

### P1 — 高优先级

#### P1-1：数据访问层使用内存存储，多实例部署不可用

- **位置**：
  - [data-access.ts](file:///e:/Desktop/CICD/src/modules/ai/data-access.ts#L34) `const eventStore: StoredAiEvent[] = []` 单实例内存
  - [content-safety.ts](file:///e:/Desktop/CICD/src/modules/ai/services/content-safety.ts#L137) `const dailyUsageMap = new Map<...>()` 单实例内存
- **问题**：注释自承认"生产环境应替换为 Redis"，但当前实现：
  - 多实例部署下，`getAiUsageStats` 聚合的统计仅包含当前实例数据
  - `tryConsumeDailyQuota` 在多实例下，每个实例独立计数，实际可用次数 = 限额 × 实例数
  - 进程重启后所有统计归零
- **违反规则**：项目硬约束「企业级补充」「可扩展性：采用配置驱动设计」
- **后果**：K8s 多 Pod 部署后限额失效、统计失真

#### P1-2：`AiUsageDashboard` 违反 React Hooks 规范

- **位置**：[ai-usage-dashboard.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-usage-dashboard.tsx#L53-L57)
- **问题**：
  ```tsx
  useEffect(() => {
    void loadStats()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])
  ```
  - `loadStats` 依赖 `aiClient` 但被 disable 抑制
  - `aiClient` 变化时不会重新加载
- **后果**：eslint-disable 掩盖真实 bug；aiClient 引用变更时不刷新

#### P1-3：`AiClientProvider` 在 layout 模块级创建 service

- **位置**：[layout.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/layout.tsx#L10)
- **问题**：`const aiClientService = createFullAiClientService()` 在模块加载时执行（module scope），service 对象被所有用户共享
- **当前可工作原因**：Server Action 内部 `requirePermission()` 会从 session 动态解析用户
- **风险**：未来若 service 需要请求级状态（如缓存当前用户权限），模块级单例会泄露
- **建议**：移入 Server Component 函数体内创建

#### P1-4：`AiAssistantWidget` 内嵌英文 prompt 硬编码

- **位置**：[ai-assistant-widget.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-assistant-widget.tsx#L228-L326) `inferContextFromPath`
- **问题**：6 个角色的 `systemPrompt` 为英文硬编码字符串，未走 i18n
- **缓解**：API 端点会强制覆盖（学生侧 SOCRATIC_TUTOR_SYSTEM_PROMPT），客户端 prompt 仅作为上下文提示
- **后果**：维护 prompt 需改代码；多语言场景下非英语用户的提示词不一致

#### P1-5：死代码 `useAiChat` Hook

- **位置**：[use-ai-chat.ts](file:///e:/Desktop/CICD/src/modules/ai/hooks/use-ai-chat.ts) 57 行
- **问题**：grep 全仓 `useAiChat` 仅在自身文件 + 005 架构数据中引用，**实际无任何组件使用**
- **原因**：早期非流式实现被 `useAiChatStream` 取代，但文件未删除
- **后果**：架构图 exports 中仍记录 `useAiChat`，误导调用方

#### P1-6：死代码 `AiSuggestionCard` 组件

- **位置**：[ai-suggestion-card.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-suggestion-card.tsx) 178 行
- **问题**：grep 全仓 `AiSuggestionCard` 仅在自身文件 + 架构数据中引用，**实际无任何页面使用**
- **原因**：`AiErrorBookAnalysis` 已包含相似题功能，`AiSuggestionCard` 是早期独立实现
- **后果**：维护成本；架构图 exports 仍记录该组件

#### P1-7：API 路由与非流式路由大量重复代码

- **位置**：
  - [chat/route.ts](file:///e:/Desktop/CICD/src/app/api/ai/chat/route.ts) 196 行
  - [chat/stream/route.ts](file:///e:/Desktop/CICD/src/app/api/ai/chat/stream/route.ts) 237 行
- **问题**：权限校验 / 限流 / Zod 校验 / 配额消费 / 输入过滤 / 系统提示构建 / 配额退款 7 段逻辑几乎逐行复制
- **后果**：修一处漏一处易出 bug；测试需双倍

### P2 — 中等优先级

#### P2-1：`ai-chart-renderer.tsx` 使用 `as` 断言

- **位置**：[ai-chart-renderer.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-chart-renderer.tsx#L122-L132)
- **问题**：
  ```ts
  data: obj.data as Array<Record<string, string | number>>,    // as 断言
  series: obj.series as AiChartSeries[],                        // as 断言
  yDomain: Array.isArray(obj.yDomain) ? obj.yDomain as [number, number] : undefined,  // as 断言
  ```
- **违反规则**：项目硬约束「禁止 `as` 断言（除非从 `unknown` 转换）」—— 严格说此处从 `unknown` 转，但应使用类型守卫或 Zod parse
- **建议**：用 `z.array(AiChartSeriesSchema).parse(obj.series)` 校验

#### P2-2：`AiChatPanel` 单文件 417 行接近上限

- **位置**：[ai-chat-panel.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-chat-panel.tsx) 417 行
- **问题**：card / widget 两个变体有 ~60% 重复 JSX（消息列表、空状态、输入框、流式指示器各写两遍）
- **建议**：抽取 `<ChatMessages>` / `<ChatInput>` / `<ChatEmptyState>` / `<ChatStreamingIndicator>` 子组件

#### P2-3：`AiAssistantWidget.inferContextFromPath` 配置硬编码

- **位置**：[ai-assistant-widget.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-assistant-widget.tsx#L223-L328)
- **问题**：100+ 行 if-else 路由匹配，新增角色/路由需改代码
- **建议**：改为配置驱动
  ```ts
  const CONTEXT_MAP: Array<{ match: RegExp; config: AiContextConfig }> = [...]
  ```

#### P2-4：`content-safety.ts` 关键词仅英文

- **位置**：[content-safety.ts](file:///e:/Desktop/CICD/src/modules/ai/services/content-safety.ts#L20-L43)
- **问题**：`BLOCKED_INPUT_PATTERNS` / `STUDENT_BLOCKED_PATTERNS` 正则仅匹配英文关键词
- **后果**：中文"自杀/暴力/色情"等不当内容无法识别，K12 中国场景下安全防线不足

#### P2-5：`AiService.chat` 的 `usage` 字段始终返回 `null`

- **位置**：[ai-service.ts](file:///e:/Desktop/CICD/src/modules/ai/services/ai-service.ts#L177)
- **问题**：`return { result: { content, usage: null }, tokenUsage }` —— `AiChatResult.usage: unknown` 类型但实际始终 null
- **建议**：将 `tokenUsage` 包入 `usage` 字段，或修改类型为 `usage: null`

#### P2-6：架构图遗漏 `/admin/ai-settings` 路由

- **位置**：[005_architecture_data.json](file:///e:/Desktop/CICD/docs/architecture/005_architecture_data.json) `routes` 节点
- **问题**：仅在 `ai.integrations.admin-dashboard.page` 字段提及 `admin/ai-usage`，但 `routes` 表中无 `/admin/ai-settings` 条目（实际页面位于 `/admin/ai-settings`）
- **后果**：路由审计遗漏

---

## 三、行业差距对比

### 3.1 与 Khanmigo（Khan Academy）差距

| 维度 | Khanmigo | 我们 | 差距影响 |
|------|----------|------|---------|
| 教师可见学生 AI 对话 | ✓ 教师后台可审阅 | ✗ 对话仅存 localStorage | 教师无法了解学生提问习惯，无法干预 Socratic 失败场景 |
| 多模态输入 | ✓ 支持图片 | ✗ 仅文本 | 数学几何题无法拍照上传 |
| Activity 难度自适应 | ✓ 根据学生水平动态调整 | ✗ 固定 difficulty 参数 | 同一题目对快慢学生无差异 |
| Teacher copilot 模式 | ✓ 教师侧 AI 提示教学策略 | ✗ 仅 widget 通用助手 | 教师备课缺专业引导 |

### 3.2 与 Duolingo Max 差距

| 维维 | Duolingo Max | 我们 | 差距影响 |
|------|--------------|------|---------|
| Explain My Answer | ✓ 错题后一键解释 | ✓ `explainError` 已实现但未接入页面 | 功能闲置 |
| Roleplay | ✓ 情景对话练习 | ✗ 无 | 英语口语训练缺失 |
| "立即练习"按钮 | ✓ 相似题后直接进入练习流 | ✗ 仅"选择" | 学生看到相似题但无法作答，流程断裂 |

### 3.3 与 Squirrel AI（松鼠 AI）差距

| 维度 | Squirrel AI | 我们 | 差距影响 |
|------|-------------|------|---------|
| 纳米级知识图谱 | ✓ 700+ 知识点拆分 | ⚠ `recommendStudyPath` 已支持 knowledgeGraph 注入，但未接入页面 | 功能已实现但未上线 |
| 自适应路径 | ✓ 实时根据答题调整 | ✗ 一次性生成路径，无反馈循环 | 路径在学习过程中不更新 |
| 学习目标对齐 | ✓ 与课标 / 升学目标对齐 | ✗ studyPathInput.learningGoal 仅文本 | 缺少课标映射 |

### 3.4 与 Century Tech 差距

| 维度 | Century Tech | 我们 | 差距影响 |
|------|--------------|------|---------|
| 全校 AI 成本看板 | ✓ token 消耗 / 预算预警 | ⚠ `AiUsageDashboard` 无 token 字段 | 管理员无法评估成本 |
| 多 Provider 对比 | ✓ A/B 测试 | ✗ 单次调用单 provider | 无法评估哪家性价比高 |
| 课程标准映射 | ✓ AI 推荐与课标对齐 | ✗ 无 | 学习路径与课标脱节 |

### 3.5 K12 通用缺失

- **a11y**：`AiAssistantWidget` 悬浮球无键盘焦点；`AiChatPanel` 流式 token 更新未限流（屏幕阅读器频繁打断）
- **空状态**：`AiUsageDashboard` 无数据时仅显示文案，无引导管理员"先发起一次 AI 对话"
- **错误恢复**：`AiErrorBoundary` 透传 `SectionErrorBoundary`，无 AI 专属重试策略（如降级到非流式）

---

## 四、改进优先级建议

### P0（必须立即修复 — 阻断核心功能）

| 编号 | 改进项 | 方向说明 |
|------|--------|---------|
| P0-1 | parent 角色补齐 `AI_CHAT` 权限 | 在 `ROLE_PERMISSIONS_SEED.parent` 数组追加 `Permissions.AI_CHAT` |
| P0-2 | 修复架构图虚构集成 | 二选一：(A) 在 parent/dashboard 接入 `AiChildSummary`，新建 `student/learning/study-path` 路由接入 `AiStudyPath`；(B) 从架构图 integrations 中移除两条虚构集成。**本次采用方案 A**：实际接入组件，让功能上线 |
| P0-3 | `getAiUsageStatsAction` 错误 i18n 修复 | 新增 `ai.error.statsFailed` 翻译键，替换 `chatFailed` |

### P1（高优先级 — 影响可维护性与正确性）

| 编号 | 改进项 | 方向说明 |
|------|--------|---------|
| P1-1 | 内存存储抽象化 | 提取 `AiUsageStore` 接口，当前内存实现作为 `InMemoryAiUsageStore`，未来可替换 `RedisAiUsageStore`；不阻塞当前发布 |
| P1-2 | `AiUsageDashboard` useEffect 修复 | 抽取 `loadStats` 为 `useCallback`，依赖数组加入 `aiClient` |
| P1-3 | layout service 创建移入 Server Component | 改为 `function DashboardLayout() { const service = createFullAiClientService(); ... }` |
| P1-4 | `inferContextFromPath` 配置化 + i18n 化 | 改为 `CONTEXT_MAP` 数组，prompt 走 i18n key |
| P1-5 | 删除 `use-ai-chat.ts` 死代码 | 文件 + 架构图 exports 同步移除 |
| P1-6 | 删除 `ai-suggestion-card.tsx` 死代码 | 同上 |
| P1-7 | API 路由共享逻辑抽取 | 抽取 `prepareAiChatRequest(req)` 返回 `{ body, isStudent, quota, limitResult }` |

### P2（中等优先级 — 代码质量与扩展性）

| 编号 | 改进项 | 方向说明 |
|------|--------|---------|
| P2-1 | `ai-chart-renderer` `as` 断言替换为 Zod parse | 用 `AiChartSpecSchema.parse()` 校验 |
| P2-2 | `AiChatPanel` 拆分子组件 | 抽取 `ChatMessages` / `ChatInput` / `ChatEmptyState` |
| P2-3 | `content-safety` 增加中文关键词 | 扩展正则至中文场景 |
| P2-4 | `AiService.chat.usage` 修正 | 返回实际 tokenUsage 或改类型为 `null` |
| P2-5 | 架构图补齐 `/admin/ai-settings` 路由 | 005 routes 节点新增 |

### 中长期方向（不在本次实施范围）

- 接入 Redis 替换内存存储（需运维配合）
- 多模态输入（需 OCR/视觉模型）
- 教师 AI 对话审阅后台（需新增 DB 表）
- 多 Provider A/B 测试（需扩展 Provider 模型）
- 课程标准映射（需课标数据源）

---

## 五、架构图同步说明

本次审计发现架构图需更新如下节点：

### 5.1 `005_architecture_data.json` 同步项

1. **`modules.ai.exports.hooks`** 移除 `useAiChat`（死代码已删除）
2. **`modules.ai.exports.components`** 移除 `AiSuggestionCard`（死代码已删除）
3. **`modules.ai.integrations.parent-dashboard`** 更新 `page` 字段为真实接入路径
4. **`modules.ai.integrations.student-learning`** 更新 `page` 字段为真实接入路径 `student/learning/study-path`
5. **`modules.ai.integrations.admin-dashboard`** 更正 `page` 为 `admin/ai-settings`（原误记为 `admin/ai-usage`）
6. **`routes./admin/ai-settings`** 新增节点（若 routes 表中确实缺失）
7. **`rolePermissionsSeed.parent`** 追加 `ai:chat` 权限
8. **`modules.ai.i18n.v2Keys`** 追加 `error.statsFailed` 翻译键

### 5.2 `004_architecture_impact_map.md` 同步项

1. AI 模块章节的「集成点」表格更新实际接入路径
2. 移除已删除组件的引用

---

## 六、本次实施清单

### 已实施（本次审计直接修复）

| 编号 | 类型 | 改动 |
|------|------|------|
| P0-1 | 代码 | `permissions.ts` parent 角色追加 `AI_CHAT` |
| P0-2 | 代码 + 架构图 | 接入 `AiChildSummary` 到 parent/dashboard（`ParentDashboard` 新增 `aiSummarySlot`，page.tsx 为每个子女渲染 `AiChildSummary`）；新建 `student/learning/study-path` 路由（page.tsx + loading.tsx + error.tsx）接入 `AiStudyPath`；同步 004/005 文档集成点与路由表 |
| P0-3 | 代码 + i18n | `actions.ts` 修复错误键；`ai.json` (zh/en) 新增 `error.statsFailed` |
| P1-2 | 代码 | `ai-usage-dashboard.tsx` 修复 useEffect |
| P1-3 | 代码 | `layout.tsx` service 移入函数体 |
| P1-5 | 代码 | 删除 `use-ai-chat.ts`；架构图 exports.hooks 移除 `useAiChat` |
| P1-6 | 代码 | 删除 `ai-suggestion-card.tsx`；架构图 exports.components 移除 `AiSuggestionCard` |
| P2-1 | 代码 | `ai-chart-renderer.tsx` 替换 `as` 为 Zod parse（新增 `AiChartSpecSchema`） |
| P2-4 | 代码 | `ai-service.ts` 修正 `usage` 字段返回实际 tokenUsage |
| 架构图 | 文档 | 004/005 同步上述改动；新增 `student.studyPath` i18n 块（zh/en） |
| 权限 | 文档 | `005` 的 `rolePermissionsSeed.parent` 追加 `AI_CHAT` |
| i18n | 文档 | `005` 的 `modules.ai.i18n.v2Keys` 追加 `error.statsFailed` |
| 路由 | 文档 | `005` 的 `routes` 表新增 `/student/learning/study-path`；更新 `/parent/dashboard` 描述含 AI 摘要集成；`/admin/ai-settings` 校正为 admin 集成路径（原误记为 `admin/ai-usage`） |

### 未实施（中长期，需独立任务）

| 编号 | 原因 |
|------|------|
| P1-1 Redis 替换内存 | 需运维提供 Redis 实例 |
| P1-4 prompt 完全 i18n 化 | 客户端 prompt 已被服务端覆盖，影响小 |
| P1-7 API 路由共享逻辑抽取 | 涉及测试回归，单独 PR |
| P2-2 AiChatPanel 拆分 | 涉及大量回归，单独 PR |
| P2-3 中文关键词扩展 | 需安全策略评审 |
