fischer-agentkit/docs/plans/2026-07-02-001-refactor-rem...

30 KiB
Raw Permalink Blame History

title date type status approved_at progress origin
refactor: Remove all emoji from agentkit 2026-07-02 refactor in-progress 2026-07-02
u1 u2 u3 u4 u5
done mostly-done mostly-done done not-started
user-direct (ce-plan invocation, 2026-07-02)

refactor: Remove all emoji from agentkit

Summary

@board 私董会数据恢复的修复已就位。但项目长期混用 emoji专家头像、CLI 状态、私董会横幅、bitable 默认图标等),与既有的 Ant Design Vue Outlined 图标家族视觉风格不一致,且跨字体/OS 渲染不稳定。本次重构一次性把全部 emoji 收敛到三套等价替代:

  • 头像/单字符位 → 统一走 expertIdentity.ts 风格的「CJK/ASCII 首字符大写」YAML/DB 中仍是字符串字段,前端渲染照常。
  • 横幅/卡片图标 → 改用 Ant Design Vue 组件(BankOutlined/AuditOutlined/TeamOutlined 等)。
  • CLI 状态标记 → Rich 文本标签(OK/FAIL/WARN + Rich 颜色样式。

执行顺序按 5 个批次分阶段落地,每批可独立提交/回滚。

Problem Frame

现状

全仓 22 个文件含 emoji 字符,覆盖 7 个语义类别专家头像、bitable 默认、私董会横幅、辩论横幅、CLI 状态、终端提示、DB 默认值)。其中:

  • configs/experts/*.yaml 15 个文件使用 emoji 作为 avatar
  • bitable/db.py📋icon 字段的 DB defaultmodels.py:80 已有 "table" 默认不一致)
  • chat.py🏛️ 私董会开始:… 写入 SqliteConversationStore,作为无障碍/纯文本回退
  • BoardBannerCard.vueDebateBannerCard.vueDebateConclusionCard.vueUserBubble.vue 直接渲染 emoji
  • 4 个 CLI 文件用 作状态标记
  • 3 个测试文件把 emoji 作为 fixture

触发原因

  • 跨平台渲染不稳定Linux 服务器无 Noto Color Emoji 时私董会横幅显示豆腐方块
  • 视觉风格不一致:与项目其余 Ant Design Vue Outlined 图标家族1.5px stroke不协调
  • DB schema 漂移:bitable/models.py:80 已迁到稳定 key "table",但 bitable/db.py:68,216 ORM/SQL 仍用 📋

期望效果

  • 全部 emoji 字符从仓库代码中清除(注释、文档除外)
  • 视觉风格统一为 Ant Design Vue Outlined + 字符首字母
  • 旧 Bitable 行的 emoji 值通过前端 resolveBitableIcon 惰性回退到 TableOutlined,无需迁移
  • CLI 输出在所有终端(包括无 emoji 字体)下稳定显示

Key Technical Decisions

KTD1专家头像改为「首字符大写」策略expertIdentity.ts 行为对齐

决策YAML 中 avatar 字段从 emoji 改为对应专家名的首字符大写(中文取首个 CJK 字,英文取首字母大写)。保留 IBoardExpert.avatar 字段(不删),值由后端 ExpertConfig 解析或前端 pickExpertIdentity 兜底。

理由

  • frontend/src/components/chat/helpers/expertIdentity.ts:55pickExpertIdentity 默认就是首字符策略
  • 删除字段会破坏既有 WebSocket payloadboard_started.experts[].avatar)契约
  • 字符位渲染跨字体稳定

取舍:放弃了 emoji 头像的「人格化表达」换取视觉一致性与跨平台稳定。Lead/主持人仍可通过 color token + tag 区分。

KTD2横幅/卡片图标改用 Ant Design Vue 组件shell.avatar 改为 Component 类型

决策BoardBannerCard / DebateBannerCard / DebateConclusionCard / UserBubble / useMessageRenderer.ts 引入 Ant Design Vue 组件(如 <BankOutlined>/<AuditOutlined>/<TeamOutlined>/<CheckOutlined>),把 shell.avatar 字段从 string 改为 Component 类型。

理由

  • 项目图标家族已统一为 OutlinedSidebarTabsTool call cards
  • useMessageRenderer.ts 现有 shell.avatar 字段在 MessageShell.vue 渲染,与后端 expert_avatar 字段不冲突(那是单个专家的 avatar

影响MessageShell.vue 接收 shell 的 avatar 字段如果是 Component 类型则用 <component :is="..." />;如果是 string(首字母)则原样渲染。

KTD3CLI 状态标记用 Rich 文本标签 + 颜色,弃用

决策OK / FAIL / WARN 作为文本标签,配合 Rich [green] / [red] / [yellow] 颜色。横幅标题用 [OK 验收结果] / [WARN 风险标记] 形式保留 emoji 缺失的视觉强度。

理由

  • 终端字体差异Windows Terminal / 容器 tty / 旧版 macOS Terminal 对 Unicode 符号渲染不一致
  • 颜色已能传达同样信息量
  • 与 Python rich 库的最佳实践一致(标签 + 颜色)

KTD4Bitable DB 默认值从 📋 改为 table,旧数据惰性收敛

决策

  • bitable/db.py:68 ORM default="📋"default="table"
  • bitable/db.py:216 SQL DEFAULT '📋'DEFAULT 'table'
  • 不写迁移脚本 — 前端 resolveBitableIcon 已对未知值回退到 TableOutlined,下次访问旧行时自动收敛
  • 新建行直接用 table;旧行 render 时也是 TableOutlined,零差异

理由

  • bitable/models.py:80Pydantic已经是 "table"ORM 端对齐消除双默认值
  • 避免引入 Alembic 迁移;旧数据下次访问收敛
  • bitable.ts:73bitableIcons.ts:86 已说明「legacy emoji 字符串自动回退」

已知限制:旧行在 DB 中仍是 📋 字符串。若未来要做 DB 备份快照或导出/导入,可能需要清理脚本。本次不处理。

KTD5App.vue 字体回退去掉 emoji 字体声明

决策App.vue:109-110 中的 'Apple Color Emoji''Segoe UI Emoji''Segoe UI Symbol''Noto Sans Emoji' 字体回退删除。

理由:既然不再渲染任何 emoji 字符,浏览器/系统不会下载这些字体;删去减少 30KB+ 的潜在字体下载请求。保留 sans-serif 作为最终回退。

KTD6测试 fixture 同步更新,保持断言真实

决策3 个测试文件中的 emoji fixture🤖 🎯 🐱 💡 🦊 🐼 🏛️改为对应的首字母大写A/T/C/I/F/P 等),断言中的 expect(avatars[0].textContent).toBe('🤖') 同步改为 'A'

理由restoreBoardStateFromMessages 的 7 个新单元测试已锁定「缺 avatar/缺 color 走 fallback」行为fixture 改字母不会绕过 fallback 链(仍由 pickExpertIdentity(name) 决定)。

Scope Boundaries

包含

  • 22 个源码文件中的 emoji 字符移除(不含文档注释)
  • 5 批次的实施顺序与每批对应的文件清单
  • DB 默认值从 emoji 改为稳定 key无 schema migration
  • App.vue 字体回退清理
  • 3 个测试文件 fixture 同步
  • 验证typecheck / pytest / vitest / 视觉冒烟

不包含Deferred to Follow-Up Work

  • emoji 自动检测CI 守卫 / pre-commit 钩子)— 防止新增 emoji 复发,作为后续独立计划
  • Bitable 旧行清理脚本DB 备份/导出场景下需要时再做)
  • @ant-design/icons-vue 包增量依赖 — 该包已是项目依赖(bitableIcons.ts 现有 import无新增
  • CLI 国际化i18nOK/FAIL/WARN 目前硬编码中英混排;国际化是更大范围重构,本次不动
  • Tauri 桌面端 emoji 字体 — Tauri 客户端的 emoji 字体回退不在本计划范围
  • avatar 字段语义升级(如改成 avatar_url 支持真实头像图片)— 是产品级决策,超出本次范围

System-Wide Impact

受影响方 影响
终端用户Web GUI 私董会/辩论横幅、专家头像、Bitable 图标视觉变化;语义不变
终端用户CLI agentkit CLI 表格/状态标记从符号改为文本标签;颜色保留
终端用户Tauri 桌面) 间接通过 Web GUI 同步
开发者 写新代码时不能直接用 emoji 字符;后续建议加 lint 规则
运营/部署 无(不涉及端口、配置、依赖增减)
测试 3 个 vitest fixture 文件需同步更新断言;不影响测试覆盖度

High-Level Technical Design

视觉风格统一KTD1+KTD2的目标是把混用状态收敛成两条规则

┌─────────────────────────────────────────────────────┐
│  头像/单字符位                                       │
│  • YAML avatar 字段 → "S"/"B"/"P" 等首字符           │
│  • 前端 expertIdentity.ts 兜底(如缺 avatar        │
│  • ExpertMessage/StickyModeHeader/BoardBannerCard   │
│    都按 string 渲染字符                              │
└─────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│  横幅/卡片图标                                       │
│  • BoardBannerCard: <BankOutlined />                │
│  • DebateBannerCard: <AuditOutlined />              │
│  • DebateConclusionCard: 4 个决策图标 = 4 个组件    │
│  • UserBubble command card: <BankOutlined /> 私董会 │
│                                <TeamOutlined /> 团  │
│  • useMessageRenderer shell.avatar 改为 Component   │
│    MessageShell 用 <component :is=...> 渲染          │
└─────────────────────────────────────────────────────┘

CLI 状态机收敛KTD3

旧:                          新:
"✓" "✗" "⚠"                  "OK" "FAIL" "WARN"
[green]✓ X[/green]            [bold green]OK X[/bold green]
[red]✗ X[/red]                [bold red]FAIL X[/bold red]
[yellow]⚠ X[/yellow]          [bold yellow]WARN X[/bold yellow]

DB schema 收敛KTD4

bitable/db.py:68      icon = Column(String, default="table")
bitable/db.py:216     icon VARCHAR DEFAULT 'table'
                                                  ↓
旧 DB 行: '📋'        → 前端 resolveBitableIcon 命中 DEFAULT_BITABLE_ICON='table'  → 渲染 TableOutlined
新 DB 行: 'table'     → 渲染 TableOutlined                                  (与旧行一致)

Implementation Units

U1. 数据/契约层 — avatar 字段、持久化文本、DB 默认值

Goal:把数据层/契约层的 emoji 全部收敛到字符串默认值或首字符。

Files

  • configs/experts/*.yaml15 个文件apple/private_board/team/tech_lead 等)— avatar 字段从 emoji 改首字符大写
  • src/agentkit/bitable/db.py:68 — ORM default 📋table
  • src/agentkit/bitable/db.py:216 — SQL DEFAULT '📋'DEFAULT 'table'
  • src/agentkit/server/routes/chat.py:304,306🏛️ 私董会开始:…私董会开始:…
  • src/agentkit/server/frontend/src/stores/chatStream.ts:1149🏛️ 私董会开始:…私董会开始:…
  • src/agentkit/core/plan_schema.py:107,122📋/⚠️[Plan ...]/WARN
  • src/agentkit/experts/registry.py:85 — 注释 📊 改为纯文字

Approach

  • YAML avatar 字段值:英文名取首字母大写(steve_jobsS),中文名取首 CJK 字(张三
  • 后端 chat.py 与前端 chatStream.tsboard_started 持久化文本保持语义一致(去 emoji 字符本身不影响 message_type/board_started metadata
  • plan_schema.py:to_readable() 是给人工看的报告,文本用纯文字更稳

Test scenarios

  • Happy pathconfigs/experts/steve_jobs.yaml 加载后 expert.avatar == "S"
  • Happy pathFileModel 新实例 icon == "table"
  • Happy path_apply_v1_schema 生成的表 icon 列默认值为 'table'
  • Edge case:现有 emoji DB 行(如 icon='📋')通过 resolveBitableIcon 仍渲染为 TableOutlined

Verification

  • pytest tests/unit/experts -k "config or registry" 通过
  • pytest tests/unit/bitable -k "schema or model" 通过
  • 启动 backend 调用 @board,确认 DB 中 board_started 消息 content 为 私董会开始:...(无 emoji

U2. 前端 UI 组件 — 横幅、卡片、命令 chip

Goal:把 emoji 图标改用 Ant Design Vue 组件。

Files

  • src/agentkit/server/frontend/src/components/chat/messages/BoardBannerCard.vue🏛️<BankOutlined />
  • src/agentkit/server/frontend/src/components/chat/messages/DebateBannerCard.vue<AuditOutlined />
  • src/agentkit/server/frontend/src/components/chat/messages/DebateConclusionCard.vuedecisionIcons map 改为 Ant Design Vue 组件(CheckOutlined/SwapOutlined/MinusOutlined/QuestionOutlined
  • src/agentkit/server/frontend/src/components/chat/messages/UserBubble.vue:143'🏛️'/'👥' 字符串 → <BankOutlined />/<TeamOutlined />
  • src/agentkit/server/frontend/src/components/chat/helpers/useMessageRenderer.ts:203,262已完成avatar: AuditOutlined
  • src/agentkit/server/frontend/src/components/chat/helpers/useMessageRenderer.ts:286avatar: '◆' → Ant Design 组件(如 ApartmentOutlined 用于协作图)
  • src/agentkit/server/frontend/src/components/chat/helpers/useMessageRenderer.ts:307avatar: review.passed ? '\u2713' : '\u2717'review.passed ? CheckOutlined : CloseOutlined
  • src/agentkit/server/frontend/src/components/chat/helpers/useMessageRenderer.ts:328avatar: '!'WarningOutlined(与 ReviewResultCard 的 risk_flagged 语义一致)
  • src/agentkit/server/frontend/src/components/chat/messages/ReviewResultCard.vue:42-44'\u2713'/'\u2717'/'\u21bb'CheckOutlined/CloseOutlined/ReloadOutlined
  • src/agentkit/server/frontend/src/components/chat/messages/MessageShell.vue — 检查 avatar 字段类型Component 走 <component :is="..." />string 走原样(已实现 Component vs string 分支)
  • src/agentkit/server/frontend/src/App.vue:109-110 — 字体回退删 emoji 字体声明

Approach

  • 引入 BankOutlined / AuditOutlined / TeamOutlined / CheckOutlined / SwapOutlined / MinusOutlined / QuestionOutlined(均已在 @ant-design/icons-vue 中,无需新装)
  • DebateBannerCard<span class="...__icon">X</span> 改为 <component :is="X" class="...__icon" />BoardBannerCard 已为纯文本,不适用)
  • UserBubble 的 command card 改造:icon prop 改为 Component 类型
  • useMessageRenderershell.avatar 类型由 string 改为 Component(行 203/262 已完成286/307 待改),其余 shell 仍用 string首字母
  • MessageShell.vuev-if="typeof shell.avatar === 'string'" 分支处理

Test scenarios

  • Happy pathBoardBannerCard 渲染时包含 BankOutlined SVG path
  • Happy pathDebateBannerCard 渲染时包含 AuditOutlined SVG path
  • Happy pathDebateConclusionCard decision="adopt" 渲染 CheckOutlined
  • Happy pathUserBubble 解析 @board:alice, bob 时 command icon 为 BankOutlined
  • Edge caseshell.avatar 是 stringexpert_initial)时仍原样渲染,不被当作 component

Verification

  • npm run typecheck 通过
  • npx vitest run tests/unit/components/ 通过
  • 浏览器打开 /agent/chat 触发 @board,确认横幅为纯文本(无 emoji
  • 触发辩论确认 DebateBannerCard 显示 <AuditOutlined />

U3. CLI 控制台输出 + Shell/CI 脚本 — admin / chat / skill / benchmark / scripts

Goal:把 Rich 输出中的 改为 OK/FAIL/WARN 文本标签 + Rich 颜色;同时清理 shell/CI 脚本中的 emoji 状态标记。

Files

  • src/agentkit/cli/admin.py:215,601 — 表格 is_active 列的 /OK/--
  • src/agentkit/cli/chat.py:589,603,692,694,727,730 — 验收/阶段/风险标记全部收敛
  • src/agentkit/cli/skill.py:296⚠ 以下为自动生成…WARN 以下为自动生成…
  • src/agentkit/cli/benchmark.py:895,989,2032,2733,2767,2784,2790 — 所有 // 收敛
  • scripts/dev-start.sh:88,91,123-132//[ OK ]/[FAIL]/[ .. ](与 KTD3 文本标签策略一致)
  • scripts/deploy.sh:16,21,36/[FAIL]/[OK]
  • .gitea/workflows/deploy.yml:69[OK]

Approach

  • 字符串替换策略:所有 [green]✓ X[/green][bold green]OK X[/bold green][red]✗ X[/red][bold red]FAIL X[/red][yellow]⚠ X[/yellow][bold yellow]WARN X[/yellow]
  • 表格列中的 /OK/--(失败用 -- 而非 FAIL 因为列宽有限)
  • 横幅标题的 ⚠ 风险标记WARN 风险标记(保留全部大写作为视觉强度替代)

Test scenarios

  • Happy pathagentkit admin list-users 输出包含 OK 而非
  • Happy pathagentkit chat 触发的 phase completion 打印 [OK] 阶段名summary
  • Error pathphase 失败时打印 [FAIL] 阶段名error
  • Integrationagentkit benchmark 在失败用例上打印 [FAIL](无 emoji

Verification

  • pytest tests/unit/cli -k "admin or chat or skill or benchmark" 通过
  • 手动跑 agentkit admin list-users / agentkit chat "test" / agentkit benchmark list 确认输出无 emoji

U4. 终端前端 + 测试 fixture + 字体回退

Goal:清理剩余的终端提示、测试 fixture、字体回退。

Files

  • src/agentkit/server/frontend/src/stores/terminal.ts:251,262,266,270,275 WARN PENDING OK REJECTED/TIMEOUT
  • src/agentkit/server/frontend/src/components/terminal/CommandHistory.vue:20/OK/FAIL
  • src/agentkit/server/frontend/tests/unit/stores/chatStream.test.ts:731avatar: '🦊'avatar: 'F'
  • src/agentkit/server/frontend/tests/unit/stores/chatStore.test.ts:22content: '🏛️ 私董会开始:…'content: '私董会开始:…'
  • src/agentkit/server/frontend/tests/unit/stores/chatStore.test.ts:33,40avatar: '🦊'/'🐼'avatar: 'F'/'P'
  • src/agentkit/server/frontend/tests/unit/components/StickyModeHeader.test.ts — 所有 emoji fixture 改首字母
  • src/agentkit/server/frontend/src/components/chat/messages/TeamPlanCard.vue:67,82,127 — 注释更新(已说明弃用,保留为历史说明即可,无运行影响)

Approach

  • 终端消息用 [WARN] / [PENDING] / [OK] / [REJECTED] / [TIMEOUT] 文本格式(与 CLI KTD3 保持一致)
  • 测试 fixture 改为对应名称首字母(StickyModeHeader.test.tsavatar: '🤖'avatar: 'A'expect(avatars[0].textContent).toBe('A')
  • chatStore.test.tsboard_started content 改 私董会开始AI 未来(与 U1 后端持久化文本一致)

Test scenarios

  • Happy pathCommandHistory 渲染 exit_code=0 时显示 OK、非 0 时显示 FAIL
  • Happy pathStickyModeHeader.test.tsexpect(avatars[0].textContent).toBe('A') 通过
  • Happy pathchatStore.test.ts restoreBoardStateFromMessages 测试对新的非-emoji content 仍正确解析
  • Edge case:终端 store 中 appendOutput 的 ANSI 颜色(\x1b[33m)保留,仅替换前缀文本

Verification

  • npm run typecheck 通过
  • npx vitest run tests/unit/ 全通过
  • 终端面板审批流程人工冒烟

U5. 端到端验证 + 防止复发pre-commit grep 守卫 + 文档)

Goal:确认全仓无残留 emoji并加入轻量防复发守卫。

Files

  • scripts/check-no-emoji.sh(新增)— 用 rg 扫描字面 emoji + 转义序列,覆盖 src/configs/tests/scripts
  • .pre-commit-config.yaml(若不存在则创建)— 添加 agentkit-no-emoji 钩子(调用上述 shell 脚本)
  • docs/solutions/style/no-emoji-style-guide.md(新增)— 记录三套替代策略KTD1-3与 Unicode 范围参考

Approach

  • 轻量方案(替代原 ESLint + ruff 自定义规则,因项目无 ESLint 基础设施且 ruff 不支持自定义规则):
    • shell 脚本用 rg 扫描两类模式:(a) 字面 emoji 字符 [\x{1F000}-\x{1FFFF}\x{2600}-\x{27BF}\x{2300}-\x{23FF}\x{2500}-\x{25FF}\x{2190}-\x{21FF}\x{2B00}-\x{2BFF}](b) 转义序列 \\u(271[0-9a-fA-F]|26[0-9a-fA-F]{2}|2[0-5][0-9a-fA-F]{2}|21[0-9a-fA-F]{2})
    • pre-commit 钩子在 commit 阶段跑该脚本,拦截含 emoji 的暂存文件
    • 白名单:docs/(文档允许 emoji*.mdmarkdown 注释允许)
  • 风格指南文档说明三套替代策略KTD1-3+ 何时用 Ant Design 组件 vs 文本标签 vs 首字母

Test scenarios

  • Happy pathbash scripts/check-no-emoji.sh 退出码 0无 emoji 残留)
  • Error path:故意在某 .ts 文件中加 \u2713 转义序列,脚本检出并报错
  • Integration:本地 commit 含 emoji 的文件被 pre-commit 阻止

Verification

  • bash scripts/check-no-emoji.sh 全通过
  • pre-commit run --all-files 全通过(若 pre-commit 已安装)
  • 手动在临时文件加 emoji 字符和 \u2713 转义,确认脚本检出

Deferred to Follow-UpCI 工作流(.gitea/workflows/)添加 emoji 检查步骤 — 等 pre-commit 钩子稳定后再加。


Risks & Dependencies

风险 缓解
Ant Design Vue 图标视觉与原 emoji 风格差异大,用户不适应 U2 完成后做视觉冒烟;如不接受可回退到 string 字符首字母策略KTD1
useMessageRenderer.tsshell.avatarComponent 类型影响 MessageShell.vue 之外的消费者 全仓 grep shell.avatar / message.shell.avatar 确认仅 MessageShell.vue 消费
CLI 输出改为 OK/FAIL 文本会改变宽度,可能破坏现有对齐 表格用 -- 而非 FAIL(列宽更短)
Bitable 旧行不清理,未来 DB 导出/快照会有 📋 字符串 文档记录 KTD4 限制;后续可加迁移脚本
pre-commit / 自定义 ESLint 规则本身可能误报CJK 字符、注释中的 emoji 规则用明确的 Unicode range白名单机制支持 // allow-emoji 行级豁免
测试 fixture 改首字母可能与某个测试断言的「fallback 行为」冲突 U4 前先跑一遍 vitest 全量测试,建立基线;逐个 fixture 改并立即跑对应测试

依赖关系

  • U1 独立(数据/契约层)
  • U2 独立(前端 UI
  • U3 独立CLI
  • U4 依赖 U1chatStore.test.ts content 需与 U1 后端持久化文本一致)
  • U5 依赖 U1-U4 全部完成

实施顺序U1 → U2 → U3 → U4 → U5。每批独立可提交/可回滚。

Acceptance Examples

AE1. 私董会横幅显示矢量图标 — 触发 @board 测试主题,确认 BoardBannerCard 渲染 <BankOutlined /> 矢量图标SVG不再显示 🏛️ 字符。

AE2. Bitable 默认图标稳定 — 创建新 Bitable 文件,icon 字段在 DB 中为 'table'UI 渲染 TableOutlined。已存在的 emoji 行通过前端 resolveBitableIcon 自动收敛。

AE3. CLI 状态无 emoji — 运行 agentkit admin list-users,表格中 is_active=true 显示 OKis_active=false 显示 --,无 / 字符。

AE4. 专家头像首字符@board steve_jobs, charlie_munger 私董会,BoardBannerCard 中 Steve Jobs 头像显示 S、Charlie Munger 头像显示 C(不再显示 🍎/🧠)。

AE5. 测试 fixture 与生产代码一致npm run typecheck + npx vitest run + pytest tests/unit/ 三套全通过,无 emoji 残留。

AE6. CI 守卫 — 故意在某 .vue 模板加 🏛️ 字符,npm run lint 报错并阻止。

Open Questions

  1. useMessageRenderer.tsshell.avatar 类型升级是否需要更平滑(保留 string 但用约定 __ICON__BankOutlined)?— 当前方案改为 Component 是更类型安全的,但若 MessageShell.vue 之外有第三方消费方可能破坏。默认决定U2 实施前先全仓 grep 确认无外部消费者。

  2. Bitable 📋 旧行是否要做一次性清理脚本?— KTD4 决定惰性收敛,文档记录为 follow-up。如用户要求显式清理U5 后可加一个 agentkit bitable migrate-icons 命令。

  3. @ant-design/icons-vue 包体积(目前约 300KB+)— 项目已在用,仅新增 7 个组件bundle size 影响可忽略。如未来有更激进的优化诉求可走按需 import + Vite tree-shaking已默认开启

ce-doc-review 2026-07-03 发现P1-P2

以下发现由 ce-doc-review 5 个 persona reviewer 在 2026-07-03 重新核查时识别,需在 U5 实施前决策。

P1 发现8 个):

  1. scripts/ 和 .gitea/ 中的 emoji 未纳入计划scripts/dev-start.sh)、scripts/deploy.sh)、.gitea/workflows/deploy.yml`)含与 CLI 同语义的状态标记,但不在 U1-U4 任何文件清单中。决策:将其加入 U3 或 U4 范围,沿用 KTD3 替换策略。

  2. "22 个文件"计数矛盾 — Problem Frame 声称 22 个文件,类别求和为 28U1-U4 文件清单求和为 37。决策:重新统计并订正。

  3. pre-commit 钩子范围矛盾 — "不包含"段将 pre-commit 列为后续独立计划,但 U5 明确包含 .pre-commit-config.yaml决策:从"不包含"删除 pre-commit 提及,明确 U5 包含 pre-commit仅 CI 工作流延期。

  4. ESLint 未安装 — 仓库无 ESLint 配置、无 eslint 依赖、package.jsonlint 脚本。U5 隐含 4 个未声明子任务(安装 ESLint、创建配置、编写规则、添加脚本决策U5 拆分为 U5aESLint 基础设施)+ U5bno-emoji 规则),或改用轻量 shell 脚本 + pre-commit grep 方案。

  5. ruff "自定义规则 RUF900" 不可行 — ruff 不支持用户通过 pyproject.toml 注册自定义规则,RUF 前缀是 ruff 保留命名空间。决策:删除 ruff 自定义规则选项Python 侧统一走 pre-commit hook + rg 扫描。

  6. "全部 emoji 字符从仓库代码中清除"与范围不匹配 — 绝对承诺但 scripts/CI 文件遗漏、useMessageRenderer.ts 转义形式遗漏。决策:修改为"U1-U4 列出文件中的 emoji 清除"或扩展范围。

  7. useMessageRenderer.ts 3 处字符串 glyph 破坏 KTD2 一致性 — 行 286、307\u2713/\u2717、328!)未转换,与 KTD2"图标家族统一为 Outlined"目标矛盾。286/307 已在 P0 修复中加入 U2328 的 ! 需决策是否也改组件。)决策:将 ! 也改为 WarningOutlined 或保留为 ASCII 文本标签。

  8. U5 过度工程 — 自定义 ESLint + ruff + pre-commit + 风格文档四件套,与剩余清理任务不相称。项目当前无 ESLint 基础设施emoji 复发概率低。决策U5 瘦身为"风格文档 + pre-commit grep 守卫",删除自定义 ESLint/ruff 规则。

P2 发现6 个):

  1. 无障碍决策未声明 — 图标替换全程未声明 aria-label/aria-hidden 决策。装饰性图标应 aria-hidden="true",承载语义的图标(如 review pass/failaria-label决策:在 KTD2 加无障碍子决策。

  2. 计划状态字段未反映进度 — 仍标记 status: approved,但 U1-U4 已基本完成。决策:更新为 status: in-progress,加 progress 字段。

  3. BoardBannerCard 实现偏离计划但未记录 — 从"Ant Design 组件"变成"纯文本"。P0 修复已更新 AE1/U2/KTD2 描述,但 KTD2 取舍段落仍提及"放弃了 emoji 头像换取视觉一致性",需补充"无图标"理由。)决策:在 KTD2 取舍段补理由。

  4. "无图标"第三选项从未被计划考虑 — KTD2 选项空间只有"emoji vs Ant Design 组件",实际实现了"无图标"。决策:在 KTD2 补"无图标"为显式选项并给取舍。

  5. KTD4 旧行 📋 无主动清理路径 — 被动等待"如用户要求显式清理"。决策:加主动触发条件(如"下次 schema migration 时顺带 UPDATE")。

  6. U5 "阻止 build" 验收与现有 build 流程脱节npm run buildvue-tsc --noEmit && vite build,不跑 ESLint。决策明确接入点pre-commit 拦截 vs build 前置检查)。

Sources & Research

  • 本地参考
    • frontend/src/components/chat/helpers/expertIdentity.ts — 字符首字母策略的权威实现
    • frontend/src/components/bitable/bitableIcons.ts:89resolveBitableIcon 的回退路径
    • docs/plans/2026-06-19-001-feat-chat-area-vi-redesign-plan.md:192 — BoardBannerCard 的设计说明(含 🏛️
    • docs/plans/2026-07-01-001-feat-ui-ue-enhancement-plan.md:154-155 — StickyModeHeader 的 emoji 头像渲染说明
  • 项目记忆
    • 「UI components must use consistent color tokens; avoid hardcoded blue fallback colors」— 沿用到图标风格统一
    • 「CSS token fallback values can cause unintended color changes when tokens load late」— Ant Design Vue 组件是设计良好的回退机制
  • 无外部研究触发emoji 替换是纯内部风格收敛,无外部 API/技术依赖。

Plan Metadata

  • Depth: Standard5 个 implementation units跨前后端+CLI+DB+测试+lint 守卫)
  • Expected commits: 5每个 U 一个 commitU5 包含 lint 规则可能拆 2 个)
  • Risk profile: 中(无安全/支付/外部 API 风险,主要是视觉/UX 风险)
  • Origin: 用户直接在 ce-plan 中提出(无 upstream brainstorm doc
  • Confidence: 中高KTD1-4 都有项目内既有模式可遵循KTD5/6 引入新机制U5 留验证空间)