---
phase: 02-rbac-ai
plan: 02
type: execute
wave: 2
depends_on:
  - "02-01"
files_modified:
  - docs/修改记录.md
autonomous: true
requirements:
  - CRED-FE-02
  - CRED-FE-03
must_haves:
  truths:
    - "docs/修改记录.md 顶部含一条 [2026-05-08] Phase 2 条目（最新在最前，紧跟「修改历史」标记之后、Phase 1 [2026-05-08] 条目之前）"
    - "Phase 2 条目含完整 5 字段：日期、文件路径、修改类型、修改内容、修改原因，外加跨项目联动 + 服务端联动两个项目惯用扩展字段"
    - "Phase 2 条目「文件路径」字段列出本期实际改动的 2 个文件：lib/permissions.ts、app/ai-model/page.tsx"
    - "「跨项目联动」字段写「无 — Phase 2 是纯前端 RBAC + UI 入口落地，不引入新跨项目契约；后端 commit 46d72b8 已建立的互引仍有效；Phase 3 引入实质 PUT 调用时若涉及新契约再评估」（CONTEXT.md D-XX 锁定文案）"
    - "Phase 2 条目覆盖前端需求：CRED-FE-02 + CRED-FE-03（在条目元信息行明确列出）"
    - "整体类型检查 npx tsc --noEmit 整体退出码可能为 2（存量错误），但 grep 过滤后 0 条指向本 phase 改动的 lib/permissions.ts 与 app/ai-model/page.tsx（Phase 1 已建立的判定模式）"
    - "package.json / yarn.lock / package-lock.json / pnpm-lock.yaml 4 个 manifest/lockfile 均未改动（不引入新依赖）"
  artifacts:
    - path: "docs/修改记录.md"
      provides: "顶部 Phase 2 修改记录条目"
      contains: "[2026-05-08] Phase 2"
      min_lines: 100
  key_links:
    - from: "docs/修改记录.md Phase 2 条目"
      to: "Plan 02-01 改动的 lib/permissions.ts + app/ai-model/page.tsx"
      via: "「文件路径」字段精确列出"
      pattern: "lib/permissions\\.ts|app/ai-model/page\\.tsx"
    - from: "docs/修改记录.md Phase 2 条目「服务端联动」字段"
      to: "qy_lty/.planning/phases/02-admin-rest commit 46d72b8"
      via: "文本引用 commit hash"
      pattern: "46d72b8"
---

<objective>
完成 Phase 2 收尾：在 `docs/修改记录.md` 顶部追加 Phase 2 条目（CLAUDE.md 强制要求），并执行 plan 级整体验证（双重类型检查 + grep 11 条 specifics 全命中 + 不引入新依赖）。

Purpose：满足 CLAUDE.md 项目宪法「修改记录强制」规则；按 Phase 1 已建立的双重验证模式（tsc + grep）封盘 Phase 2，让 STATE.md 可推进到 Phase 3 待启动状态。
Output：`docs/修改记录.md`（修改，仅顶部追加；不动其他历史条目）。
</objective>

<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/02-rbac-ai/02-CONTEXT.md
@.planning/phases/02-rbac-ai/02-RESEARCH.md
@.planning/phases/02-rbac-ai/02-01-PLAN.md
@CLAUDE.md
@docs/修改记录.md
@lib/permissions.ts
@app/ai-model/page.tsx
</context>

<interfaces>
<!-- 修改记录头部「修改格式说明」（VERIFIED docs/修改记录.md line 9-20） -->

```
### [日期] 修改简述

- **文件路径**: 相对于项目根目录的文件路径
- **修改类型**: 新增 / 修改 / 删除 / 重构 / 修复Bug
- **修改内容**: 具体修改了什么
- **修改原因**: 为什么要做这个修改
```

<!-- Phase 1 条目（VERIFIED docs/修改记录.md line 28-48）作为本期模板，关键扩展字段 -->

Phase 1 条目结构（**直接抄此 7 字段结构**）：
1. **元信息行**（标题下方紧跟）：「配套服务端 Phase: ...」+「覆盖前端需求: CRED-FE-XX」
2. **文件路径**：列出实际改动的所有文件相对路径
3. **修改类型**：新增 / 修改 / 删除 / 重构 / 修复Bug
4. **修改内容**：分点 bullet 描述每个文件做了什么
5. **修改原因**：解释为什么做、对后续 phase 的支撑作用
6. **跨项目联动**（项目惯用扩展字段，CONTEXT.md 已锁定本期文案）
7. **服务端联动**（项目惯用扩展字段，可与「跨项目联动」复用文案或简短交叉引用）

<!-- 顶部插入位置 -->

`docs/修改记录.md` line 26 是注释 `<!-- 新的修改记录添加在此处下方，最新的在最前面 -->`，line 28 是当前最顶 Phase 1 条目 `### [2026-05-08] Phase 1（前端）凭据槽位 API 客户端`。**新条目必须插入到 line 26 的注释**之后**、line 28 的 Phase 1 条目**之前**。
</interfaces>

<tasks>

<task type="auto" tdd="false">
  <name>任务 1：docs/修改记录.md 顶部追加 Phase 2 条目</name>
  <files>docs/修改记录.md</files>

  <read_first>
    1. **必读**：`docs/修改记录.md` 完整 line 1-50（确认头部「修改格式说明」+ line 26 锚点注释 + line 28-48 Phase 1 条目作为模板）
    2. **必读**：`.planning/phases/02-rbac-ai/02-CONTEXT.md` 「修改记录」段（CONTEXT D-XX 锁定的「跨项目联动」字段精确文案）
    3. **必读**：`.planning/phases/02-rbac-ai/02-01-PLAN.md`（确认 Phase 2 实际改动文件 = `lib/permissions.ts` + `app/ai-model/page.tsx`）
    4. **必读**：`CLAUDE.md` 「项目修改记录规则（重要 — 自动执行）」段 + 「`qy-lty-admin` 与 `qy_lty` 是独立项目，各自维护」段
  </read_first>

  <action>
    用 Edit 工具对 `docs/修改记录.md` 做**1 处**精确插入：在 line 26 的锚点注释 `<!-- 新的修改记录添加在此处下方，最新的在最前面 -->` 之后、line 28 的 `### [2026-05-08] Phase 1（前端）凭据槽位 API 客户端` 之前，插入完整 Phase 2 条目。

    **old_string**（精确匹配 line 26-28，含中间空行）：
    ```
    <!-- 新的修改记录添加在此处下方，最新的在最前面 -->

    ### [2026-05-08] Phase 1（前端）凭据槽位 API 客户端
    ```

    **new_string**（在锚点与 Phase 1 之间插入完整 Phase 2 条目；Phase 2 条目结尾 → 1 个空行 → Phase 1 条目原行）：
    ```
    <!-- 新的修改记录添加在此处下方，最新的在最前面 -->

    ### [2026-05-08] Phase 2（前端）RBAC 收敛 + AI 模型页凭据槽位入口

    配套服务端 Phase：本 phase **不**触达服务端；与服务端 v1.0 Phase 2「管理端读写接口」commit `46d72b8` 既有契约保持兼容（不引入新契约）
    覆盖前端需求：CRED-FE-02、CRED-FE-03

    - **文件路径**：
      - `lib/permissions.ts`（修改）
      - `app/ai-model/page.tsx`（修改）
    - **修改类型**: 修改（前端 RBAC 矩阵扩展 + 页面入口控件 + 占位 Dialog；纯前端，无新依赖、不动 lockfile）
    - **修改内容**:
      - `lib/permissions.ts`：
        - `PermissionModule` union 末尾追加 `"credential-slot"`，扩为 14 项
        - `PERMISSION_MATRIX["超级管理员"]` 数组末尾追加 `"credential-slot"`
        - `PERMISSION_MATRIX["AI模型管理员"]` 数组末尾追加 `"credential-slot"`
        - 其他 4 个角色（内容管理员 / 卡牌管理员 / 查看者 / 管理员）数组**逐字不变**
        - `getModuleFromPath` 函数体完全不动（凭据槽位是 `/ai-model` 子能力，不占独立路由）
        - 顶部「权限矩阵对照表」注释新增一行「凭据槽位」与代码同步
      - `app/ai-model/page.tsx`：
        - 文件 line 1 顶部新增 `"use client"` 指令，从 Server Component 转为 Client Component
        - 新增 import：`useState` / `useEffect`（react）+ `Dialog` / `DialogContent` / `DialogDescription` / `DialogHeader` / `DialogTitle`（@/components/ui/dialog）+ `KeyRound`（lucide-react）+ `hasPermission`（@/lib/permissions）
        - 函数体顶部新增 `mounted` + `isCredentialDialogOpen` 两个 `useState` + 1 个 `useEffect` 设 `mounted` 为 true（复用 `components/sidebar.tsx` mounted 守卫模式避免 SSR 水合不匹配）
        - `DashboardHeader` 内部用 `<div className="flex items-center gap-2">` 包两个 Button：保留原有「添加新模型」+ 新增 `{mounted && hasPermission("credential-slot") && <Button variant="outline" onClick={() => setIsCredentialDialogOpen(true)}><KeyRound /> 凭据槽位</Button>}`
        - `</Tabs>` 之后、`</DashboardShell>` 之前新增 controlled mode `<Dialog open={isCredentialDialogOpen} onOpenChange={setIsCredentialDialogOpen}>`，内含 `DialogTitle`「通用凭据槽位」+ `DialogDescription`「对话框真实内容由 Phase 3 落地」（占位，无表单）
        - Tabs / TabsContent / Card / 卡片内的现有按钮等所有内容（line 18-441）逐字不变
    - **修改原因**:
      - 推进 Milestone v1.0「通用凭据槽位前端集成」第二步：让授权运营立即看到入口（已就位的 UX 收敛），未授权角色彻底看不到（DOM 中完全不存在的安全前置）
      - 沿用 RBAC 单一来源原则（`lib/permissions.ts:hasPermission`）+ shadcn Dialog primitive，不重复造轮子
      - 为 Phase 3 真实表单（CRED-FE-04 + CRED-FE-05）预留 Dialog 挂载点；Dialog 用 controlled mode 让 Phase 3 可在打开瞬间触发 `getCredentialSlot()`
      - 注意：前端 RBAC 仅是 UI 礼貌，最终安全闭环依赖后端 `/v1/admin/credential-slot/` 的 admin 鉴权（PERM-06 / `qy_lty` 后端）；本 phase 不消化该闭环
    - **跨项目联动**: 无 — Phase 2 是纯前端 RBAC + UI 入口落地，不引入新跨项目契约；后端 commit 46d72b8 已建立的互引仍有效；Phase 3 引入实质 PUT 调用时若涉及新契约再评估
    - **服务端联动**: 同上「跨项目联动」字段；后端 commit `46d72b8` 已建立互引闭环，本 phase 无需再次互引

    ### [2026-05-08] Phase 1（前端）凭据槽位 API 客户端
    ```

    **明确不要做的事**：
    - 不要动 line 1-26 的头部说明 / 修改格式说明 / 修改历史标记
    - 不要动 line 28 之后任何已有条目（Phase 1 / 2026-05-07 的两个条目 / 2026-04-30 初始化条目）
    - 不要把「跨项目联动」字段文案缩短或重写（CONTEXT.md 已逐字锁定）
    - 不要漏掉 Phase 2 条目的「覆盖前端需求」元信息行（必须含 CRED-FE-02 + CRED-FE-03）
    - 不要在「文件路径」中列入 docs/修改记录.md 自身（CLAUDE.md 适用范围说「单纯的 typo 修复 / 注释微调可省略」，但本条目作为 phase 收尾骨干条目，遵循 Phase 1 模板的写法 = 仅列被修改的代码文件）
  </action>

  <acceptance_criteria>
    - `grep -n "\\[2026-05-08\\] Phase 2" docs/修改记录.md` 命中 1 行（标题行）
    - `grep -n "\\[2026-05-08\\] Phase 1" docs/修改记录.md` 仍命中 1 行（Phase 1 条目未被破坏）
    - `head -n 30 docs/修改记录.md` 输出含「修改格式说明」+「修改历史」+ `<!-- 新的修改记录添加在此处下方，最新的在最前面 -->` 锚点（line 1-26 完全不变）
    - `awk '/### \\[2026-05-08\\]/{count++} count==1 && /Phase 2/{print "PASS"; exit} count==1 && /Phase 1/{print "FAIL: Phase 1 在最前面"; exit}' docs/修改记录.md` 输出 `PASS`（确保 Phase 2 在 Phase 1 之上）
    - `grep -nE "CRED-FE-(02|03)" docs/修改记录.md | head -n 5` 命中至少 1 行包含 `CRED-FE-02` 或 `CRED-FE-03` 的元信息行（在 Phase 2 条目之内）
    - `grep -n "credential-slot" docs/修改记录.md` 命中 ≥1 行（Phase 2 条目里描述 PermissionModule 字面量）
    - `grep -n "46d72b8" docs/修改记录.md` 命中 ≥2 行（Phase 1 条目已有的 + Phase 2 条目新增的，证明跨项目联动文案已嵌入）
    - `grep -n "凭据槽位" docs/修改记录.md` 命中 ≥1 行（Phase 2 条目内容描述）
    - `grep -n "通用凭据槽位" docs/修改记录.md` 命中 ≥1 行（Phase 2 条目 DialogTitle 描述）
    - `git diff --stat docs/修改记录.md` 显示仅 +N 行（无 -行；纯追加）
  </acceptance_criteria>

  <verify>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && grep -c "\[2026-05-08\] Phase 2" docs/修改记录.md
    # 预期：1
    </automated>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && grep -c "\[2026-05-08\] Phase 1" docs/修改记录.md
    # 预期：1（Phase 1 条目仍存在）
    </automated>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && awk '/### \[2026-05-08\] Phase 2/{p2=NR} /### \[2026-05-08\] Phase 1/{p1=NR} END{ if(p2>0 && p1>0 && p2<p1) print "PASS"; else print "FAIL p2="p2" p1="p1 }' docs/修改记录.md
    # 预期：PASS
    </automated>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && grep -c "CRED-FE-02" docs/修改记录.md
    # 预期：≥1
    </automated>
  </verify>

  <done>
    - `docs/修改记录.md` 顶部新增 Phase 2 条目（最新在最前）
    - 条目含 5 个标准字段（文件路径 / 修改类型 / 修改内容 / 修改原因）+ 2 个项目惯用扩展字段（跨项目联动 / 服务端联动）+ 元信息行（覆盖前端需求 + 配套服务端 Phase）
    - 「跨项目联动」字段文案逐字与 CONTEXT.md 锁定一致
    - Phase 1 条目以及更早的所有历史条目逐字不变
  </done>
</task>

<task type="auto" tdd="false">
  <name>任务 2：plan 级整体双重验证（tsc + grep + 不引入新依赖）</name>
  <files></files>

  <read_first>
    1. **必读**：`.planning/phases/02-rbac-ai/02-01-PLAN.md` 的 `<verification>` 段（4 条整体校验列表）
    2. **必读**：`.planning/phases/02-rbac-ai/02-CONTEXT.md` 「specifics」表（11 条验证点）
    3. **必读**：`.planning/STATE.md` Phase 1 收尾段（line 80-81）确认 Phase 1 已建立的 tsc 双重验证模式（整体退出码 2 但过滤后零指向新文件）
    4. **必读**：本 plan 任务 1 落地后的 `docs/修改记录.md` 顶部（确认 Phase 2 条目结构正确）
  </read_first>

  <action>
    本任务**不修改任何代码或配置文件**，仅执行验证命令并把结果汇总写入 `02-02-SUMMARY.md`（在 Plan 02-02 收尾时由 execute-plan 流程统一写）。

    按以下顺序执行**4 大类**验证命令，逐条记录退出码与命中数：

    ### 验证 A：TypeScript 编译（双重判定，与 Phase 1 一致）

    ```bash
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin
    npx tsc --noEmit > /tmp/tsc-phase2.log 2>&1
    echo "tsc exit code: $?"

    # 整体错误数（预期与 Phase 1 的 67 条相近 ± 微小波动；不应大幅增加）
    grep -cE "error TS" /tmp/tsc-phase2.log

    # 反向断言：本 phase 改动文件零类型错误
    grep -E "(lib/permissions\.ts|app/ai-model/page\.tsx)" /tmp/tsc-phase2.log
    # 预期：0 行输出（grep 退出码 1 也算 PASS）
    ```

    **判定**：
    - tsc 整体退出码可能为 2（存量错误），允许
    - 反向 grep 必须 0 行输出（无任何错误指向 `lib/permissions.ts` 或 `app/ai-model/page.tsx`）
    - 整体错误数与 Phase 1 收尾时（67 条）相比浮动 ≤ 3 条，否则人工核查是否有新引入

    ### 验证 B：specifics 11 条 grep 全命中（CONTEXT.md 锁定）

    ```bash
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin

    # specifics 1：PermissionModule union 含 credential-slot
    grep -cE "['\"]credential-slot['\"]" lib/permissions.ts   # 期望 ≥3

    # specifics 2-3：超管 + AI模型管理员含；其他 4 角色不含
    awk '/超级管理员: \[/,/\],/' lib/permissions.ts | grep -c "credential-slot"   # 期望 1
    awk '/AI模型管理员: \[/,/\],/' lib/permissions.ts | grep -c "credential-slot"  # 期望 1
    awk '/内容管理员: \[/,/\],/' lib/permissions.ts | grep -c "credential-slot"    # 期望 0
    awk '/卡牌管理员: \[/,/\],/' lib/permissions.ts | grep -c "credential-slot"    # 期望 0
    awk '/查看者: \[/,/\],/' lib/permissions.ts | grep -c "credential-slot"        # 期望 0
    # 「管理员」（最末位）匹配，避免被「AI模型管理员」前缀干扰：用末尾段
    awk '/^  管理员: \[/,/\],/' lib/permissions.ts | grep -c "credential-slot"    # 期望 0

    # specifics 4：getModuleFromPath 行为不变
    grep -c '"ai-model": "ai-model"' lib/permissions.ts   # 期望 1

    # specifics 5：app/ai-model/page.tsx 第 1 行是 "use client"
    head -n 1 app/ai-model/page.tsx | grep -c '"use client"'   # 期望 1

    # specifics 6：含「凭据槽位」文案
    grep -c "凭据槽位" app/ai-model/page.tsx   # 期望 ≥2（Button + DialogTitle）

    # specifics 7：含 KeyRound
    grep -c "KeyRound" app/ai-model/page.tsx   # 期望 ≥2

    # specifics 8：含 hasPermission("credential-slot")
    grep -cE "hasPermission\\([\"']credential-slot[\"']\\)" app/ai-model/page.tsx   # 期望 ≥1

    # specifics 9：含 useState + onClick + Dialog 三连
    grep -c "useState" app/ai-model/page.tsx                      # 期望 ≥3（import + 2 调用）
    grep -c "setIsCredentialDialogOpen" app/ai-model/page.tsx    # 期望 ≥3

    # specifics 10：占位 Dialog 含「通用凭据槽位」DialogTitle
    grep -c "通用凭据槽位" app/ai-model/page.tsx   # 期望 1

    # specifics 11：修改记录顶部含 Phase 2 条目
    grep -c "\[2026-05-08\] Phase 2" docs/修改记录.md   # 期望 1
    ```

    **判定**：以上 14 条 grep 全部满足预期值 → 11 条 specifics 全命中。

    ### 验证 C：不引入新依赖

    ```bash
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin
    git diff --name-only -- package.json yarn.lock package-lock.json pnpm-lock.yaml 2>/dev/null
    # 期望：0 行输出（4 个文件均未改动）

    git diff --name-only HEAD~1 -- package.json yarn.lock package-lock.json pnpm-lock.yaml 2>/dev/null
    # 期望：0 行输出（与上一 commit 比较仍无 manifest 改动）
    ```

    **判定**：4 个文件均未出现在 diff → 不引入新依赖。

    ### 验证 D：（跳过）next lint

    `npm run lint`（即 `next lint`）在 Phase 1 已确认会进入「ESLint 未 bootstrap → 交互式 prompt」状态（无 `.eslintrc*` / `eslint-config-next`），按 STATE.md line 81「ESLint 基础设施补齐留给 PERM-06 候选 #3」的判定 → **本 phase 跳过 lint**，与 Phase 1 一致。

    在 SUMMARY 中显式记录：「next lint 因项目未 bootstrap ESLint 跳过；判定与 Phase 1 一致；不指向本 phase 改动文件」。

    ### 失败处理

    任一条验证失败 → **不要继续**，立即返回 STATE 报告问题，不可静默继续 SUMMARY 写入；按以下优先级处理：
    1. tsc 出现指向 `lib/permissions.ts` 或 `app/ai-model/page.tsx` 的新错误 → 回到 Plan 02-01 任务 1 或 2 修补
    2. 反向 grep 在「内容管理员 / 卡牌管理员 / 查看者 / 管理员」数组中命中 `credential-slot` → 回到 Plan 02-01 任务 1 重新核对
    3. specifics grep 数量不足 → 回到 Plan 02-01 任务 2 检查 import / JSX
    4. package.json / lockfile 出现 diff → 回滚 lockfile（`git checkout HEAD -- package.json yarn.lock package-lock.json pnpm-lock.yaml`）
  </action>

  <acceptance_criteria>
    - 验证 A：tsc 整体退出码 2 容许；过滤后 0 行指向 `lib/permissions.ts` / `app/ai-model/page.tsx`
    - 验证 B：14 条 grep 全部满足预期值（specifics 11 条 + 反向断言 3 条）
    - 验证 C：`git diff` 对 4 个 manifest/lockfile 文件输出 0 行
    - 验证 D：在 SUMMARY 中显式记录「next lint 跳过原因」
  </acceptance_criteria>

  <verify>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && npx tsc --noEmit 2>&1 | grep -cE "(lib/permissions\.ts|app/ai-model/page\.tsx)"
    # 预期：0
    </automated>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && (awk '/超级管理员: \[/,/\],/' lib/permissions.ts | grep -c "credential-slot") && (awk '/AI模型管理员: \[/,/\],/' lib/permissions.ts | grep -c "credential-slot")
    # 预期：两条命令各输出 1
    </automated>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && for ROLE in 内容管理员 卡牌管理员 查看者; do echo "$ROLE: $(awk -v role="$ROLE" '$0 ~ role"\\: \\[" {flag=1} flag {print} /\],/ {flag=0}' lib/permissions.ts | grep -c "credential-slot")"; done
    # 预期：3 行各为 X: 0
    </automated>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && git diff --name-only -- package.json yarn.lock package-lock.json pnpm-lock.yaml | wc -l
    # 预期：0
    </automated>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && head -n 1 app/ai-model/page.tsx
    # 预期：含 "use client"
    </automated>
    <automated>
    cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin && grep -c "\[2026-05-08\] Phase 2" docs/修改记录.md
    # 预期：1
    </automated>
  </verify>

  <done>
    - 4 大类验证全部通过（A / B / C / D）
    - 11 条 specifics 全命中，反向断言（其他 4 角色数组不含 `credential-slot`）通过
    - tsc 不引入指向本 phase 改动文件的新错误
    - 不引入新依赖（4 个 manifest/lockfile 均未改动）
    - SUMMARY 中明确记录 next lint 跳过原因（与 Phase 1 一致）
  </done>
</task>

</tasks>

<verification>
## Plan 级整体验证（覆盖整个 Phase 2）

执行完两个任务后，确认以下**3 条**整体校验通过：

### 1. 修改记录顶部条目格式
```bash
cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin
sed -n '/<!-- 新的修改记录添加在此处下方/,/### \[2026-05-08\] Phase 1/p' docs/修改记录.md | head -n 60
```
**判定**：输出含完整 Phase 2 条目结构（标题 / 元信息行 / 文件路径 / 修改类型 / 修改内容 / 修改原因 / 跨项目联动 / 服务端联动）+ 紧跟 Phase 1 标题行作为下一条。

### 2. RBAC 矩阵 5+1 角色逐一确认
```bash
cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin
echo "应含 credential-slot 的 2 角色："
awk '/超级管理员: \[/,/\],/' lib/permissions.ts | grep "credential-slot"
awk '/AI模型管理员: \[/,/\],/' lib/permissions.ts | grep "credential-slot"
echo "应不含 credential-slot 的 4 角色："
for ROLE in 内容管理员 卡牌管理员 查看者; do
  HIT=$(awk -v role="$ROLE" '$0 ~ role"\\: \\[" {flag=1} flag {print} /\],/ {flag=0}' lib/permissions.ts | grep -c "credential-slot")
  echo "$ROLE: $HIT 次（期望 0）"
done
# 「管理员」单独取末尾段（避免「AI模型管理员」前缀污染）
awk '/^  管理员: \[/,/\],/' lib/permissions.ts | grep -c "credential-slot"
```
**判定**：超管 + AI模型管理员各命中 1 次；其他 4 角色各 0 次。

### 3. Phase 2 入口控件 + 占位 Dialog 端到端就位
```bash
cd C:\Users\admin\Desktop\Lila-Server\qy-lty-admin
# 整段验证：1) "use client" 顶置；2) 入口 Button 受 mounted + hasPermission 守卫；3) Dialog 在 DashboardShell 末尾
echo "=== line 1 ==="
head -n 1 app/ai-model/page.tsx
echo "=== mounted 守卫 + hasPermission(credential-slot) ==="
grep -nE "mounted &&" app/ai-model/page.tsx
grep -nE "hasPermission\\([\"']credential-slot" app/ai-model/page.tsx
echo "=== Dialog 占位 ==="
grep -nE "<DialogTitle>通用凭据槽位</DialogTitle>" app/ai-model/page.tsx
grep -nE "对话框真实内容由 Phase 3 落地" app/ai-model/page.tsx
```
**判定**：所有 5 段输出非空且行号合理（"use client" 在 line 1；mounted + hasPermission 守卫在 DashboardHeader 区域；Dialog 在文件末尾区域）。

**整体判定**：3 条全部通过 → Phase 2 全部交付，可推进 STATE.md → Phase 3 待启动。
</verification>

<success_criteria>
**ROADMAP.md Phase 2 Success Criteria 4 条最终确认（前 3 条由 Plan 02-01 主体落地、本 Plan 02-02 验证；第 4 条由 Plan 02-01 落地、本 Plan 02-02 验证；CLAUDE.md 修改记录强制由本 Plan 02-02 落地）：**

1. ✅ 验证：`hasPermission('credential-slot')` 对超管 + AI模型管理员返回 true、其他角色返回 false（通过本 plan 验证 B 段反向断言确认）
2. ✅ 验证：`getModuleFromPath('/ai-model')` 行为不变（通过 grep `'ai-model': 'ai-model'` 仍命中 1 行确认）
3. ✅ 验证：`/ai-model` 页面 DashboardHeader 含「凭据槽位」入口控件，未授权角色 DOM 中不存在（通过 mounted + hasPermission 守卫的 grep 命中确认）
4. ✅ 验证：可见性走 `hasPermission('credential-slot')`、点击触发占位 Dialog 打开（通过 grep `setIsCredentialDialogOpen(true)` + `<Dialog open=` 命中确认）
5. ✅ CLAUDE.md 修改记录强制：`docs/修改记录.md` 顶部含 Phase 2 条目，跨项目联动字段写「无」（CONTEXT.md 锁定文案）
</success_criteria>

<output>
完成后由 execute-plan 自动创建：
- `.planning/phases/02-rbac-ai/02-01-SUMMARY.md`（Plan 02-01 收尾摘要：RBAC 矩阵 + 入口控件 + Dialog 落地）
- `.planning/phases/02-rbac-ai/02-02-SUMMARY.md`（Plan 02-02 收尾摘要：修改记录追加 + 双重验证结果，含 next lint 跳过说明）

并由后续 `/gsd-verify-phase 2`（如启用）或人工触发把 STATE.md 推进到 Phase 3 待启动状态。
</output>
