# Agent Note: 本地 JSON 树渲染器

Status: implemented

[English](2026-07-28-local-json-tree-renderer.md) | 中文

## 问题

[轨迹检查记录表](../feature/2026-07-27-trajectory-inspection-ledger.md)使用的只读 JSON 检查器需要提供紧凑的对象和数组预览、供复制操作使用的明确数组路径、固定展开与可折叠两种根节点模式，以及键盘导航。`react-json-view-lite` 既不提供自定义节点渲染，也不提供行标识；要通过该依赖满足这些要求，就必须使用包管理器为编译后的发布文件打补丁，并遍历 DOM，从可见标签中还原数据路径。该补丁实际上相当于一个不受类型约束的 fork，但其源码映射与上游源码均未同步修改。

## 决策

`dsh-client-ui-primitives` 中的 `JsonTree` 自行负责递归呈现。

- 每个渲染行都直接接收自身的值和属性路径。递归时，对象键和数组索引会附加到路径末尾，因此复制操作无需再从 DOM 渲染文本中反向还原应用数据。
- 可展开行在本地渲染紧凑预览，仅在展开时挂载子行。`expandTopLevel` 可选择固定展开的括号框架或可折叠根节点，而不改变组件的公开约定。
- 树中所有可见节点仅保留一个可通过 Tab 键聚焦的展开控件。使用指针激活控件后，该控件会成为 Tab 键焦点位置；上、下方向键循环移动焦点，左、右方向键折叠或展开当前焦点所在节点。
- `react-json-view-lite` 不在 `dsh-client-ui-primitives` 的依赖项中，也没有 pnpm 补丁。针对性组件测试锁定预览、展开、键盘焦点和数组复制路径。

## 曾考虑的替代方案

**保留发布文件补丁。** 不予采纳：应用专用的渲染逻辑和数组标识约定仍会隐藏在生成的第三方文件中；每次更新依赖，都必须评审一个没有配套源码映射的 fork。

**直接使用不提供预览的上游渲染器。** 不予采纳：`{…}` 和 `[…]` 会丢失轨迹检查器扫读时所需的紧凑载荷上下文。

**渲染后注入预览和行元数据。** 不予采纳：Effect 或 MutationObserver 仍会依赖同一套私有 DOM 结构，同时使 React 和命令式变更机制分别负责同一行的不同部分。

**采用更大型的 JSON 查看器。** 不予采纳：编辑、搜索与主题系统不在当前只读约定范围内；扩大依赖范围也无法去除检查器专用的复制和布局代码。

## 后果

JSON 检查器在源码层由单一实现负责，具有显式数据流和准确的数组路径，且没有经过补丁修改的依赖。`dsh-client-ui-primitives` 负责递归渲染、展开状态、ARIA 树结构和焦点循环移动行为，因此修改这些语义时必须提供针对性组件测试。实现有意保持只读，仅包含当前消费方使用的预览、导航与复制行为。
