docs: 新增 AGENTS.md(AI 协作规范与经验教训)

只记录 README 没有的协作专属信息:Bun 运行时约定(禁混用其他包管理器)、验证命令清单、命名规范、SFC 注释位置、测试盲区经验(stub useElementSize/断言渲染内容/能杀死 bug)、架构红线(model 层选区/tabs 纯导航/节流 trailing/rAF 每帧重读输入)、已知边界。
This commit is contained in:
2026-09-08 15:37:39 +08:00
parent 93bbea2489
commit 00ccfc4849
+50
View File
@@ -0,0 +1,50 @@
# AGENTS.md
面向 AI 编码工具(Claude / Cursor / Codex 等)的项目协作说明。项目概述、运行方式、架构说明见 [README.md](./README.md),本文件只记录 README 没有的协作规范与经验教训。
## 运行时:Bun
- 运行时与包管理器是 **Bun**(依赖锁是 `bun.lock`)。安装依赖用 `bun install`,跑脚本用 `bun run <script>`(如 `bun run dev` / `bun run test`)。
- **不要引入 npm/pnpm/yarn 的产物**:不提交 `package-lock.json` / `pnpm-lock.yaml`,不建议任何需要 lockfile 迁移的依赖操作。
## 常用验证命令
```bash
bun run test # vitest 全量(单元 + 组件 + 集成冒烟)
bun run type-check # vue-tsc
bun run lint # oxlint + eslint
bun run build # type-check + vite build
```
改动完成后按此顺序验证,全绿才算完成。prettier 不在 lint 链里,涉及 `.vue`/`.ts` 文件改动后需另跑 `bunx prettier --write <文件>`。
## 命名规范
- 代码文件名一律 **kebab-case 且语义化完整,宁长勿缩写**:`json-text-view.vue` 而非 `jtv.vue`;变量同理(`endpointList` 优于 `epList`)。
- 模板中引用组件转大驼峰:`import SideNav from '@/components/side-nav.vue'` → `<SideNav />`。
- 项目文档用**中文命名**(`bench实施计划.md`);README.md / AGENTS.md 等约定俗成者除外。
## Vue SFC 书写规范
- **块注释必须写在 `<script setup>` 内部顶部**(import 之前),不能写在 SFC 顶层(块标签之外)——SFC 顶层不是 prettier 认识的注释位置,JSDoc 块会被拍平重排。
- composable(`useXxx`)必须在 `<script setup>` 顶层调用,不能在事件回调/异步函数内调用(provide/inject 失效)。
## 测试经验(防踩坑)
- **jsdom 下容器高度恒为 0**:涉及视口尺寸的组件测试必须 stub `useElementSize`(见 `json-text-view.spec.ts` 顶部的 `vi.mock`),否则虚拟滚动窗口恒空、断言失效。
- **断言"实际渲染内容",不要只断言"结构存在"**。曾发生 script 层重构后模板漏改、结构断言全绿而页面全空的事故。
- **测试有效性的判据是"能杀死 bug"**:修 bug 后可用 `git stash` 对照验证——旧代码下新测试应当失败。
- 测试需要 TanStack Query 时要提供 `QueryClient`(挂载 `EndpointPanel` 一类的组件必须包 `VueQueryPlugin`)。
## 架构红线
- **滚动/选区等交互状态放 model 层**(`json-text-view.vue` 的行号锚点),DOM 只是投影。不要把选区状态存在 DOM Selection 里——虚拟滚动跨窗口边界会卸载 DOM,原生选区必丢。
- **不要往 t-tabs 的 panel 里塞内容**。tabs 采用"纯导航模式"(list 不传 panel,面板外置渲染,`v-show` 切换),面板显隐/布局完全自有。仅存的一条样式钩子(隐藏空 panel 壳)写在 `request-tabs.vue` 样式区,注释里有依赖类名与版本记录。
- **节流连续高频事件(滚动条拖拽)必须开 trailing**:`useThrottleFn(fn, ms, true)`——默认 false 会丢弃节流窗口内的全部事件(白屏事故的根因)。
- **rAF/循环 + 外部输入**:输入必须在循环体内每帧重读,闭包捕获只是快照(自动滚动速度漂移事故的根因)。
## 已知边界(不要当 bug 修)
- build 产物 >500kB(TDesign 全量引入),按需引入留作后续优化,见 README「已知边界」。
- 生产部署无 Vite 代理,网关路径需反向代理;`GATEWAY` 只从环境变量读取,代码不写死默认值。
- 选区随滚动重建会丢失 DOM 层可见选区(model 高亮保留)——虚拟滚动固有行为,非 bug。