<!-- 文档分类: MGMT-RPT-006 | 阶段: 项目管理 | 原路径: docs/报告/AB-交付质量对齐-2026-06-03.md -->
# KHY vs Claude Code: AB 全面对齐报告

**Date:** 2026-06-03
**Scope:** KHY vs Claude Code, UI 互动感 + 任务交付质量全链路对照
**Method:** 代码审计 + 单元测试 (147 tests, 3 test suites)
**Result:** 147 tests 全通过, 5 项已修复, 4 项结构性差距待修复 (P0-P3)

---

## 1. 测试总览

本次 AB 对齐分为 **两大阶段**:

| 阶段 | 关注层面 | 测试套件 | 测试数 |
|------|---------|----------|--------|
| 第一阶段: UI 互动感 | 终端输出时间线 + 20 项 CC 功能覆盖 | v1 + v2 | 113 |
| 第二阶段: 交付质量 | 三类小任务端到端交付管线 | v3 | 34 |
| **合计** | | | **147** |

---

# 第一阶段: UI 互动感对齐

## 2. Claude Code 输出时间线参考

KHY 需要完整复现 Claude Code 的终端输出序列:

```
╔══════════════════════════════════════════════════════════════╗
║  Claude Code output timeline (reference)                    ║
║                                                             ║
║  1. User message (dark bg)                                  ║
║  2. Spinner "Thinking..." (elapsed + tokens + stall color)  ║
║  3. [thinking indicator if extended thinking]               ║
║  4. Tool call start: ⏺ Read(file.js)                       ║
║     - intent line above: "Reading file contents"            ║
║  5. Tool call result: ● Read(file.js) 0.1s                 ║
║     ⎿ 245 lines                                            ║
║  6. [repeat 4-5 for each tool]                              ║
║  7. Streamed markdown response                              ║
║  8. Cost/model line: ╰─ claude-3.5 · 2.3s · ↑12k ↓1.5k    ║
║  9. Dim separator ─                                         ║
║ 10. Prompt >                                                ║
║                                                             ║
║  Multi-tool: [2/5] prefix from 2nd call onward              ║
║  Agent: ToolUseTracker tree → collapse to "Done" summary    ║
║  Bash: command preview box (bg color block)                 ║
║  Edit: diff preview (+/- lines)                             ║
║  Interrupt: dim "⏸ Interrupted"                             ║
║  Compaction: "✻ Conversation compacted"                     ║
║  Exit: session recap (tokens, cost, time, top tools)        ║
╚══════════════════════════════════════════════════════════════╝
```

## 3. 20 项功能矩阵 (F1-F20)

CC 的 20 项核心交互功能, KHY 逐项对照:

| ID | 功能 | CC 实现 | KHY 实现 | 对齐 |
|----|------|---------|----------|------|
| F1 | Spinner + elapsed + tokens + stall | Ink spinner | `DynamicSpinner` (弹跳 + 3s 黄/8s 红停滞检测) | ✅ |
| F2 | Tool call start (icon+name+params+intent) | `⏺ Read(file.js)` + intent | `printToolCallStart` (6 族图标 + intent 描述) | ✅ |
| F3 | Tool call result (overwrite+dot+elapsed) | 原地覆写 start 行 | `printToolCallResult` (绿/红点 + 耗时) | ✅ |
| F4 | Bash 命令预览框 | bg color block | `printToolCallStart('Bash')` 背景色 `$ cmd` 框 | ✅ |
| F5 | 文件操作统计 (+N -M lines) | Added/removed stats | `printFileOperation` (Added N line, removed M line) | ✅ |
| F6 | Step 计数器 [N/M] | 第 2 个工具起显示 | `setStepTotal` + `_stepCounter` (第 2 个起显示) | ✅ |
| F7 | 任务计划跟踪 + 折叠 | checklist | `TaskPlanTracker` (>3 完成折叠为摘要行) | ✅ |
| F8 | 完成面板 (files+cmds+summary) | 框线面板 | `printCompletionPanel` (改动/新建/命令/摘要/统计) | ✅ |
| F9 | 执行简报面板 | 框线面板 | `printExecutionBrief` (需求/分析/计划/文件) | ✅ |
| F10 | 费用/Token 透明度 | `╰─ model · time · ↑in ↓out · $cost` | `printTurnCost` (模型/耗时/token/费用/适配器) | ✅ |
| F11 | 级联透明度 | 多适配器日志 | `printCascadeSteps` (16 适配器级联可视化) | ✅ |
| F12 | 思考指示器 + 动词轮换 | Thinking... | 8+ 动词轮换 (中/英: 思考中/分析中/Thinking/Analyzing...) | ✅ |
| F13 | Markdown 渲染 (code+tables+headers) | Ink markdown | `renderMarkdownLite` (10 语言高亮 + box-drawing 表格) | ✅ |
| F14 | 用户消息深色背景 | dark bg block | `renderUserMessage` (ANSI 背景色块) | ✅ |
| F15 | Agent/Subagent 树 (ToolUseTracker) | tree display + collapse | `ToolUseTracker` (header → tool 列表 → Done 摘要) | ✅ |
| F16 | 可展开输出 (ctrl+o) | expandable | `ExpandableSection` + `printCollapseCounter` (ctrl+o 提示) | ✅ |
| F17 | 权限对话框 | permission dialog | `permissionDialog` 模块 | ✅ |
| F18 | 上下文压缩通知 | "✻ Conversation compacted" | `printCompactionResult` + `printCompactingNotice` | ✅ |
| F19 | 会话回顾 (退出时) | session recap | `printSessionRecap` (token/cost/time/top tools) | ✅ |
| F20 | 工具去重 (重复调用折叠) | 15s dedup window | `printToolCallStart` 内置 15s dedup + 合并提示 | ✅ |

**结果: 20/20 全部覆盖。**

## 4. v1 三轮时间线对照 (51 tests)

### R1 — 小任务: "修复 README.md 的错别字"

CC 时间线: Read → Edit → Done (3 tool calls, <10s)

| 测试 | 检查项 | 状态 |
|------|--------|------|
| F2 | tool start 显示 icon + name + file path | ✅ |
| F3 | tool result 显示结果 + 耗时 | ✅ |
| F2b | intent 描述 (读取意图) | ✅ |
| F5 | 文件操作 +1/-1 统计 | ✅ |
| F6 | 首次调用不显示 step counter | ✅ |
| F10 | printTurnCost 函数存在 | ✅ |
| F11 | printCascadeSteps 函数存在 | ✅ |
| F14 | 用户消息渲染 | ✅ |

### R2 — 中任务: "为登录表单添加输入验证"

CC 时间线: Read×3 → Grep → Edit×2 → Bash(test) → Done (7 tools)

| 测试 | 检查项 | 状态 |
|------|--------|------|
| F6 | [2/7] step counter 从第 2 个显示 | ✅ |
| F4 | Bash 命令预览框 `$ npm test` | ✅ |
| F7 | TaskPlanTracker 4 任务 checklist | ✅ |
| F7b | 任务 start → complete 状态更新 | ✅ |
| F9 | 执行简报面板 (需求/分析/文件) | ✅ |
| F2c | Grep 显示 pattern 参数 | ✅ |
| F20 | 重复调用去重/合并 | ✅ |
| F13 | Markdown 代码块渲染 | ✅ |
| F18 | 上下文压缩通知函数存在 | ✅ |

### R3 — 大任务: "重构 auth 模块 + 测试 + 文档"

CC 时间线: 15+ tool calls, subagent, multi-file, >60s

| 测试 | 检查项 | 状态 |
|------|--------|------|
| F15 | ToolUseTracker 树形显示 | ✅ |
| F15b | ToolUseTracker 完成 → Done 摘要 | ✅ |
| F7c | >3 完成任务折叠为摘要行 | ✅ |
| F8 | 完成面板: 文件改动/命令/摘要/统计 | ✅ |
| F8b | 完成面板: string summary 兼容 (回归) | ✅ |
| F15c | renderAgentProgress 多 Agent 树 | ✅ |
| F16 | ExpandableSection 存储 + toggle | ✅ |
| F19 | printSessionRecap 函数存在 | ✅ |
| F1 | DynamicSpinner 全部方法 (start/stop/setPhase/setTokens/setEffort/resetTimer) | ✅ |
| F12 | 8+ 思考动词轮换 | ✅ |
| F17 | permissionDialog 模块加载 | ✅ |
| F16b | printCollapseCounter + ctrl+o 提示 | ✅ |
| F15d | renderAgentDone 摘要行 (24 tool uses · 60.9k tokens · 2m 15s) | ✅ |
| F5b | printInlineDiff 彩色 +/- 行 | ✅ |

## 5. v2 精确时间线对照 (62 tests)

### CC-1 ~ CC-34: 逐帧验证

v2 套件对每一帧输出做精确检查:

**小任务 (CC-1 ~ CC-10):**

| ID | 检查项 | 状态 |
|----|--------|------|
| CC-1 | 用户消息暗色背景 + 文字内容 | ✅ |
| CC-2 | Spinner elapsed + tokens + stall (3s 黄/8s 红) | ✅ |
| CC-3 | intent 行 (工具调用前) | ✅ |
| CC-4 | tool start icon + display name + params | ✅ |
| CC-5 | tool result detail + elapsed (0.1s) | ✅ |
| CC-6 | Edit 工具显示 file path + diff info | ✅ |
| CC-7 | 文件操作 Added 1 line, removed 1 line | ✅ |
| CC-8 | printTurnCost + printCascadeSteps 存在 | ✅ |
| CC-9 | 8+ 思考动词 | ✅ |
| CC-10 | 首次调用不显示 [1] | ✅ |

**中任务 (CC-11 ~ CC-21):**

| ID | 检查项 | 状态 |
|----|--------|------|
| CC-11 | [2/5] step counter (with setStepTotal) | ✅ |
| CC-12 | [2] auto-increment (without total) | ✅ |
| CC-13 | Bash 预览框 `$ npm test` + `$` 前缀 | ✅ |
| CC-14 | Write 工具显示 file + line count | ✅ |
| CC-15 | TaskPlanTracker 5 任务 + 待处理状态 | ✅ |
| CC-16 | 任务 start → complete 生命周期 | ✅ |
| CC-17 | 执行简报: 需求/分析/步骤/文件 | ✅ |
| CC-18 | Markdown 代码块 (含函数高亮) | ✅ |
| CC-19 | 工具去重 (15s window) | ✅ |
| CC-20 | 折叠计数器 + ctrl+o 提示 | ✅ |
| CC-21 | 压缩通知函数 | ✅ |

**大任务 (CC-22 ~ CC-34):**

| ID | 检查项 | 状态 |
|----|--------|------|
| CC-22 | ToolUseTracker header + tool 计数 | ✅ |
| CC-23 | ToolUseTracker finish → "Done" + 2 tool uses + 12.5k tokens + ctrl+o | ✅ |
| CC-24 | >3 完成折叠 + 进行中/待处理独立列出 | ✅ |
| CC-25 | 完成面板全部 section (改动/新建/命令/摘要/统计/耗时) | ✅ |
| CC-26 | string summary 兼容 (回归保护) | ✅ |
| CC-27 | Agent 进度树 (completed/running/pending + tokens + detail) | ✅ |
| CC-28 | Agent Done 摘要 (24 tool uses · 60.9k tokens · 2m 15s) | ✅ |
| CC-29 | inline diff 彩色渲染 (context/add/remove) | ✅ |
| CC-30 | ExpandableSection 存储 + toggle + 多段 | ✅ |
| CC-31 | printSessionRecap 存在 | ✅ |
| CC-32 | permissionDialog 模块 | ✅ |
| CC-33 | ProcessTracker 生命周期 (start/complete/fail) | ✅ |
| CC-34 | 压缩通知渲染 (compacted + token count) | ✅ |

### GAP-1 ~ GAP-8: 差距检测 (已全部修复)

| ID | 差距 | 修复内容 | 文件 |
|----|------|---------|------|
| GAP-1 | printTurnCost 在 QE 路径未调用 | `streamState._qeCost` 累积 + done 后调用 `printTurnCost` | `repl.js:7228,7249` |
| GAP-2 | 工具输出截断无告警 | `_formatToolResult` 末尾追加 `[已截断 N 字符]` | `repl.js:2893` |
| GAP-3 | Ctrl+C/Esc 中断信息冗长 | 改为简洁 `⏸ Interrupted` | `repl.js:2404,9264` |
| GAP-4 | 回复结束无分隔线 | finally 块添加 dim `─` 分隔符 | `repl.js:9175` |
| GAP-5 | 工具族图标需区分 | 6 族图标 (bash/read/write/edit/grep/agent) 各不相同 | `renderTheme.js` |
| GAP-6 | 工具显示名本地化 | `TOOL_DISPLAY_NAMES` 中文映射 | `renderTheme.js` |
| GAP-7 | 阶段标签缺工具级粒度 | `PHASE_LABELS` 新增 17 个 `tool:*` 标签 | `renderTheme.js` |
| GAP-8 | diff 渲染模块 | `diffRenderer.js` 存在且可加载 | 已有 |

---

# 第二阶段: 交付质量对齐

## 6. 测试概述

第二阶段检查 **实际任务交付能力**: 模型通过 KHY 工具链能否完成真实小任务, 交付物质量是否对齐 Claude Code。

### 三轮任务定义

| Round | 任务描述 | 覆盖管线 | CC 参照 |
|-------|---------|----------|---------|
| R1 | 用工具绘制一个表格 | markdownRenderer → formatters → ANSI output | CC Ink markdown renderer |
| R2 | 用网络搜索工具搜索新闻汇总 | WebSearchTool → webSearchService → 4 后端级联 | CC web_search (Anthropic native) |
| R3 | 做一个简单的网页 | FileWriteTool → fs → auto-mkdir → LSP | CC Write tool |

---

## 7. R1: 表格绘制

### 7.1 管线剖析

```
Model 输出 Markdown 表格
  → markdownRenderer.renderMarkdownLite()
    → _renderMarkdownTables()       # 识别 pipe-delimited 表格块
      → _parseTableData()           # 解析行列, CJK-aware 列宽
      → _formatTableFromData()      # box-drawing 渲染 + 比例缩放
      → _renderSideBySideTables()   # 宽终端并排 (>120 cols)
    → _highlightCodeLine()          # 代码高亮 (如果表格在代码块内)
  → ANSI 输出 → 终端
```

### 7.2 KHY vs CC 对照

| 能力 | Claude Code (Ink) | KHY | 对齐 |
|------|------------------|-----|------|
| Box-drawing 边框 | ╭╮╰╯│─ | ╭╮╰╯│─┬┴┼├┤ | ✅ KHY 更完整 (含交叉符) |
| 表头高亮 | Bold | Bold + Cyan (TTY) | ✅ |
| CJK 列宽 | string-width | string-width + manual fallback | ✅ KHY 双路径兜底 |
| 比例缩放 | Ink 自动 layout | proportional shrink (min 3 chars) | ✅ |
| 并排表格 | 无 | >120 cols 自动并排 + 统一列宽 | ✅ KHY 独有 |
| 单元格内 Markdown | 无 | bold/italic/code 解析 | ✅ KHY 独有 |
| 语法高亮 | 10 语言 | 10 语言 (JS/TS/Py/Bash/JSON/Go/Rust/SQL/CSS/HTML) | ✅ |

### 7.3 测试覆盖 (12 tests)

| ID | 检查项 | 状态 |
|----|--------|------|
| DQ-1.1 | 基本 box-drawing 渲染 (╭╰│┬┴┼) | ✅ |
| DQ-1.2 | 表头行分隔 (├┤ separator) | ✅ |
| DQ-1.3 | 单元格内 bold/code 格式保留 | ✅ |
| DQ-2.1 | displayWidth CJK = 2 | ✅ |
| DQ-2.2 | CJK 表格列对齐 (│ 数量一致) | ✅ |
| DQ-2.3 | truncateToWidth CJK 截断 + 省略号 | ✅ |
| DQ-3.1 | 窄终端比例缩放 (60 cols) | ✅ |
| DQ-3.2 | 最小列宽 3 chars (40 cols + 5 列) | ✅ |
| DQ-4.1 | 宽终端并排渲染 (140 cols) | ✅ |
| GAP-A.1 | displayWidth / truncateToWidth CJK 区间一致 | ✅ (修复后) |
| GAP-A.2 | emoji 宽度一致性 | ✅ |

---

## 8. R2: 网络搜索汇总

### 8.1 管线剖析

```
Model 调用 WebSearch(query)
  → WebSearchTool.execute()
    → webSearchService.search()
      → 级联后端:
        1. Baidu (无需 API key, cheerio 解析)
        2. Bing China (无需 key, cn.bing.com)
        3. Kiro MCP (若有 MCP server)
        4. DuckDuckGo (ddg lite, 无需 key)
      → _sanitizeProviderText()  # 防注入清洗
    → 格式化 Markdown 结果 (编号标题 + 摘要 + URL)
  → Model 收到搜索结果 → 生成汇总
```

### 8.2 KHY vs CC 对照

| 能力 | Claude Code | KHY | 对齐 |
|------|------------|-----|------|
| 搜索后端 | Anthropic web_search (单后端) | 4 后端级联 (Baidu→Bing→Kiro→DDG) | ✅ KHY 更强 |
| 需要 API key | 需要 (Anthropic API 内置) | 不需要 (Baidu/Bing/DDG 免费) | ✅ KHY 零配置 |
| 域名过滤 | allowed_domains / blocked_domains | allowed_domains / blocked_domains | ✅ |
| 防注入清洗 | 服务端处理 | _sanitizeProviderText (本地) | ✅ |
| CW 格式兼容 | web_search 被排除 (native tool) | WebSearch 大小写不同, 不被排除 | ✅ |
| 中国网络可用 | 需代理 | Baidu/Bing CN 直连 | ✅ KHY 独有 |
| 结果格式 | 嵌入模型上下文 | Markdown 编号列表 | ✅ |

### 8.3 CW 排除安全性分析

`_toolSchemaConverter.anthropicToCW()` 默认排除集: `new Set(['web_search', 'websearch'])`

- `Set.has()` 是 **大小写敏感** 的
- KHY 的工具名是 `WebSearch` (Pascal case)
- `Set.has('WebSearch')` → `false` → **不被排除**
- 因此 KHY 的 WebSearch 可以安全转换到 CW 格式 (Kiro adapter)

### 8.4 测试覆盖 (10 tests)

| ID | 检查项 | 状态 |
|----|--------|------|
| DQ-5.1 | WebSearchTool 模块加载 + alwaysLoad | ✅ |
| DQ-5.2 | schema.query required | ✅ |
| DQ-5.3 | schema 支持 allowed/blocked_domains | ✅ |
| DQ-6.1 | webSearchService 多后端方法 | ✅ |
| DQ-6.2 | search() 导出函数 | ✅ |
| DQ-7.1 | CW 默认排除 web_search | ✅ |
| DQ-7.2 | CW 可通过 excludeNames 包含 web_search | ✅ |
| DQ-7.3 | KHY WebSearch 经 CW 转换后保留 | ✅ |
| DQ-8.1 | _sanitizeProviderText 防注入 | ✅ |
| GAP-B.1 | CW 排除大小写安全 | ✅ |

---

## 9. R3: 创建简单网页

### 9.1 管线剖析

```
Model 调用 Write(file_path, content)
  → FileWriteTool.validateInput()
    → validateNotUNCPath()          # Windows UNC 拦截
    → validateNoPathTraversal()     # ../.. 拦截
  → FileWriteTool.execute()
    → 环境变量展开 ($VAR / %VAR%)
    → ~ 展开 (homedir)
    → path.resolve(cwd, rawPath)
    → Read-before-write 检查 (_readTracker)
    → 自动创建父目录 (mkdirSync recursive)
    → 文件历史快照 (fileHistoryService)
    → writeFileSync(path, content, 'utf-8')
    → LSP 诊断注入 (若 LSP 可用)
  → 返回 { success, path, bytes, _lspDiagnostics? }
```

### 9.2 KHY vs CC 对照

| 能力 | Claude Code (Write) | KHY (FileWriteTool) | 对齐 |
|------|---------------------|---------------------|------|
| Schema | file_path + content | file_path + content | ✅ 完全一致 |
| 绝对路径要求 | prompt 指导 | prompt 指导 | ✅ |
| Read-before-write | 已读检查 | _readTracker 检查 | ✅ |
| 路径遍历防护 | 有 | validateNoPathTraversal | ✅ |
| UNC 路径防护 | 有 | validateNotUNCPath | ✅ |
| 自动建目录 | mkdirSync recursive | mkdirSync recursive | ✅ |
| UTF-8 编码 | 固定 utf-8 | 固定 utf-8 | ✅ |
| 字节数返回 | 有 | Buffer.byteLength | ✅ |
| 破坏性检测 | isDestructive | isDestructive (existsSync) | ✅ |
| LSP 诊断 | Ink 内置 | _lspDiagnostics 注入 | ✅ |
| 文件快照/回滚 | 无 | fileHistoryService | ✅ KHY 独有 |
| ~ 展开 | 有 | 有 | ✅ |
| Prompt 指导 | complete + no placeholder | complete + no scaffold | ✅ |

### 9.3 安全性审计结果

| 检查项 | 状态 | 备注 |
|--------|------|------|
| 路径遍历 `../../../etc/passwd` | ✅ 拦截 | validateNoPathTraversal |
| UNC `\\server\share` | ✅ 拦截 (Win) | validateNotUNCPath |
| 环境变量注入 `$HOME` | ✅ 安全 | 简单替换, 无 shell exec |
| ~ 展开顺序 | ⚠️ 注意 | ~ 展开在 path.resolve 之前, 但在 validateInput 之后 |
| 已有文件覆写 | ✅ 保护 | read-before-write + fileHistoryService 快照 |

### 9.4 测试覆盖 (12 tests)

| ID | 检查项 | 状态 |
|----|--------|------|
| DQ-9.1 | schema: file_path + content required | ✅ |
| DQ-9.2 | risk = high | ✅ |
| DQ-9.3 | isDestructive 不存在文件 = false | ✅ |
| DQ-10.1 | 路径遍历拦截 | ✅ |
| DQ-10.2 | UNC 拦截 (Windows) | ✅ |
| DQ-10.3 | ~ 展开为绝对路径 | ✅ |
| DQ-11.1 | HTML 文件实际写盘 | ✅ |
| DQ-11.2 | 自动创建嵌套父目录 | ✅ |
| DQ-11.3 | UTF-8 字节数准确 | ✅ |
| DQ-11.4 | 未读文件覆写被拒绝 | ✅ |
| DQ-12.1 | prompt 要求完整内容 | ✅ |
| DQ-12.2 | prompt 对齐 CC Write 指导 | ✅ |

---

---

# 修复记录与总结

## 10. 修复记录

### 10.1 第一阶段修复 (4 项, repl.js)

| # | 问题 | 修复 | 行号 |
|---|------|------|------|
| 1 | printTurnCost 在 QueryEngine 路径未调用 | `streamState._qeCost` 累积 + done 后调用 `printTurnCost` | `repl.js:7228,7249` |
| 2 | 工具输出截断无告警 | `_formatToolResult` 追加 `[已截断 N 字符]` | `repl.js:2893` |
| 3 | Ctrl+C/Esc 中断信息冗长 | 改为 `⏸ Interrupted` | `repl.js:2404,9264` |
| 4 | 回复结束无分隔线 | finally 块添加 dim `─` | `repl.js:9175` |

### 10.2 第二阶段修复 (1 项, formatters.js)

#### GAP-A: `truncateToWidth` CJK 范围不一致 (已修复)

**文件:** `backend/src/cli/formatters.js:279-301`

**问题:** `truncateToWidth` 的 CJK 宽字符检测范围与 `displayWidth` 不一致:

| 差异点 | `displayWidth` | `truncateToWidth` (修复前) |
|--------|---------------|--------------------------|
| 0x2E80-0x303E | 精确: 0x2E80-0x303E | 粗范围: 0x2E80-0x9FFF (包含所有子区间) |
| 0xA000-0xA4CF (Yi 文字) | ✅ 有 | ❌ 缺失 |
| 0x0300-0x036F (combining) | width = 0 | ❌ 未处理 (算 width 1) |
| ANSI escape | N/A (先 stripAnsi) | ❌ 未跳过 (算 width 1) |

**修复内容:**
1. 统一 CJK 区间为 13 个精确子区间 (与 `displayWidth` 一致)
2. 增加 `0xA000-0xA4CF` Yi 文字区间
3. 增加 combining characters (`0x0300-0x036F`) 零宽处理
4. 增加 ANSI escape (`0x1B`) 跳过

**影响范围:** 表格渲染中文截断、工具输出截断、任何通过 `truncateToWidth` 的 CJK 文本

### 10.3 确认无需修复的关注点

| 关注点 | 分析结论 |
|--------|---------|
| WebSearch CW 排除 | `Set.has` 大小写敏感, `WebSearch` ≠ `websearch`, 无风险 |
| FileWrite ~ 展开顺序 | ~ 展开在 `validateInput` 之后, 但 `path.resolve` 会标准化, 安全性不受影响 |
| FileWrite 环境变量展开 | 简单字符串替换, 无 `exec`/`spawn`, 不存在命令注入 |

---

## 11. 尚存真实差距 (CC 能做但 KHY 缺失或不足)

以下差距不是面板函数缺不缺的问题，而是 **端到端交付体验** 的结构性差距。

### 11.1 Diff 内联渲染: 有实现但有冗余

| 对比项 | Claude Code | KHY |
|--------|------------|-----|
| Edit 后自动显示 diff | ✅ 内建于 tool result | ✅ `maybeRenderWriteDiff` → `renderStructuredDiff` 自动触发 |
| 渲染格式 | `11 │-old` / `11 │+new` 紧贴工具结果行 | 类似但缩进层级不同 (独立段落) |
| Word-level diff 高亮 | ✅ | ✅ `wordDiff` 字级别着色 |

**问题:** `toolDisplay.js` 中的 `printInlineDiff` (第 569-603 行) 是 **死代码** — 它被定义、导出、测试覆盖，但 **从未在任何生产路径中调用**。实际走的是 `diffRenderer.js` → `renderStructuredDiff` 路径。两套 diff 渲染实现并存，增加维护负担。

### 11.2 交付一体化: toolUseLoop vs QueryEngine 路径割裂

这是 **最大的结构性差距**。KHY 有两条响应路径，但只有 toolUseLoop 路径具备完整的交付体验:

| 能力 | CC | KHY toolUseLoop | KHY QueryEngine |
|------|-----|-----------------|-----------------|
| 完成面板 (printCompletionPanel) | ✅ 内建 | ✅ 已接入 (`repl.js:8782`) | ❌ **缺失** |
| 执行简报 (printExecutionBrief) | ✅ 内建 | ⚠️ 已接入但无 AI steps | ❌ **缺失** |
| Post-edit 语法检查 | ✅ 内建 | ✅ `verificationAgent.quickSyntaxCheck` | ❌ **缺失** |
| LSP 诊断注入 | ✅ 内建 | ✅ `_pendingLspDiagnostics` | ❌ **缺失** |
| Coding mode 自动验证 nudge | ✅ 内建 | ✅ 一次性 `npm test` 提醒 | ❌ **缺失** |
| 3+ 文件写入验证 nudge | ✅ 内建 | ✅ 自动提醒验证 | ❌ **缺失** |
| 交付完整性检查 (跑偏检测) | ✅ 内建 | ✅ 关键词覆盖率 <30% 则 nudge | ⚠️ 仅短回复/无工具 nudge |
| 结构化执行摘要 | ✅ 内建 | ✅ `_buildDeliverySummary` | ❌ **缺失** |
| 回归闸门 | ❌ CC 无 | ✅ **KHY 独有** | ❌ **缺失** |

**结论:** 当 `KHY_QUERY_ENGINE=true` 时，用户得到的是一个 **功能孤岛** — 工具能调用、结果能显示，但没有完成面板、没有自动验证、没有交付摘要。这与 CC 的 "问题→分析→执行→验证→总结" 全链路体验有本质差距。

### 11.3 任务规划: 被动提取 vs 主动编排

| 对比项 | Claude Code | KHY |
|--------|------------|-----|
| 规划方式 | 内部主动规划，执行前就有 plan | **被动提取**: AI 回复后正则匹配 "执行计划" 关键词，`extractFromResponse` 事后提取 |
| 进度追踪 | 执行每步时自动更新 plan 状态 | TaskPlanTracker 的 `start()/complete()` 需显式调用 |
| 规划显示 | 可选显示，内部始终有 | 依赖 AI 是否在回复中输出编号列表 |

CC 的规划是 **编排层行为** — 模型决定做什么，系统追踪执行进度。KHY 的规划是 **文本解析行为** — 系统从 AI 的自由文本中碰运气提取步骤列表。如果 AI 没有主动列出步骤，TaskPlanTracker 就不会触发。

### 11.4 执行简报: 有面板无内容

`printExecutionBrief` 面板在 toolUseLoop 路径中已接入 (`ai.js:4087`)，但:

- `opts.steps` 参数面板支持但 **发射端没有传** — 用户看不到 "我打算做 X, Y, Z" 的步骤列表
- 只传了静态分析结果 (规模/文件数/知识库上下文数)
- CC 的简报包含模型规划的具体步骤，KHY 只有统计数字

---

## 12. KHY 独有优势 (CC 不具备)

| 能力 | 说明 |
|------|------|
| 表格并排渲染 | 终端 >120 cols 时自动将相邻表格并排显示 |
| 表格统一列宽 | 相邻表格列数相同时统一列宽 |
| 单元格内 Markdown | `**bold**` / `` `code` `` / `*italic*` 在表格内生效 |
| 4 后端搜索级联 | Baidu → Bing CN → Kiro MCP → DuckDuckGo, 中国直连 |
| 零 API key 搜索 | 三个免费后端无需配置 |
| 文件写入快照 | fileHistoryService 自动在覆写前创建快照, 支持 /rollback |
| LSP 诊断注入 | 写入后自动收集编译错误返回给模型 |
| 回归闸门 | toolUseLoop 路径独有，CC 无此能力 |
| 交付完整性检测 | 关键词覆盖率跑偏检测 + 结论 nudge |

---

## 13. 全量测试矩阵

### 三套 AB 测试总览

| 测试套件 | 文件 | 测试数 | 关注层面 |
|----------|------|--------|----------|
| v1 Interactivity | `ab_test_interactivity.test.js` | 51 | UI 显示元素 (3 轮 × F1-F20) |
| v2 Timeline | `ab_interactivity_v2.test.js` | 62 | 精确时间线 (CC-1~34 + F1-20 + GAP-1~8) |
| v3 Delivery | `ab_delivery_quality.test.js` | 34 | 任务交付质量 (DQ-1~12 + GAP-A~C) |
| **合计** | | **147** | **0 failures** |

### 覆盖维度

```
UI 层 (v1+v2: 113 tests)
├── Spinner / Thinking indicator
├── Tool call start/result + Step N/M
├── Bash preview / File stats / Inline diff
├── Task tracker + Completion panel
├── Cost / Cascade / Permission
├── Markdown rendering / Agent tree
├── Interrupt / Compaction / Session recap
└── Tool dedup (15s window)

交付层 (v3: 34 tests)
├── Table rendering (box-drawing, CJK, shrink, side-by-side)
├── WebSearch (schema, cascade, CW compat, sanitize)
├── FileWrite (schema, security, write, auto-mkdir, UTF-8, read-guard)
└── Gap detection (CJK range, CW exclusion, env expansion)
```

---

## 14. 结论

### 已对齐

**UI 互动感 (F1-F20):** 20/20 全部覆盖。发现 4 项实现差距, 全部修复。113 tests 通过。

**单工具交付 (表格/搜索/网页):** 三条管线功能完整, 对齐 CC。7 项 KHY 独有优势 (并排表格/级联搜索/文件快照等)。34 tests 通过。

### 尚存差距

| 差距 | 严重程度 | 性质 |
|------|---------|------|
| QE 路径缺少完成面板/执行简报/自动验证/交付摘要 | **P0** | 功能孤岛 — 两条路径能力严重不对等 |
| 任务规划是被动文本提取而非主动编排 | **P1** | 架构差距 — CC 的 plan 是编排层行为 |
| 执行简报面板有框架无内容 (不传 steps) | **P2** | 接入不完整 |
| `printInlineDiff` 是死代码, 与 `renderStructuredDiff` 功能重叠 | **P3** | 冗余 — 需清理 |

### 下一步

1. **P0**: QE 路径补齐完成面板 + 自动验证 + 交付摘要 (对齐 toolUseLoop 能力)
2. **P1**: TaskPlanTracker 改为编排层驱动 (工具调用前生成 plan, 执行中自动 update)
3. **P2**: `printExecutionBrief` 发射端补传 `steps` 字段
4. **P3**: 删除 `toolDisplay.printInlineDiff` 死代码

**总计 5 项已修复, 4 项待修复, 147 tests, 0 failures。**
