7.8 KiB
2026-09-03 全方位代码防腐 / 质量优化审查报告
三路探索子代理对 src / tests / scripts / CI / 文档做全方位摸底后,经用户批准按「P0 速修 + P1 行为不变去重 + P2 深度项全做」执行,共 10 个变更流、11 个 PR,全部走分支 + PR + 三 job CI 门禁合入。本文记录审查结论、落地清单、过程中的重要发现与遗留 backlog。
1. 审查结论总览
底子健康,无大面积腐化:
- 类型纪律严格:全仓 0
as any、0@ts-ignore、0 TODO/FIXME。 - 模块边界零违规:懒加载 chunk 隔离、client externals 白名单、tsdown purity gate 全部干净。
- 错误 envelope 一致:宿主侧
wire.ts/ 客户端侧api.ts双层归一。 - 测试规模:118 个 vitest spec(约 3300 断言)+ 6 条 Playwright e2e lane。
压力点集中在:少数巨型组件、若干字面重复、脚本间复制粘贴、以及缺 lint / task-runner 基础设施。
2. 已落地的变更流
| PR | 主题 | 要点 |
|---|---|---|
| #524 | feat/test-utils | 共享 tests/test-utils.ts(setupReactAct + renderRoot),迁移 28 个 spec 的重复样板;chunk-artifact / manifest-consistency 加 lib 缺失 skipIf 守卫 |
| #525 | feat/dedup-core | api envelope 解析、extOf 双实现、lineage-walk 四份、GitLens 错误归一化六处收敛;删零引用死代码 sidechatSeed;console 分级统一。测试零改动 |
| #526 | feat/dev-commands | Makefile(11 目标薄封装,check 聚合对齐 CI);package.json 补 test:mount:aggregate / clean / packageManager: pnpm@11.8.0;release.yml 补 consumer-types 并统一步骤序;.editorconfig;双语 README 补文档 |
| #527 | fix/scripts-hardening | aggregate 脚本 tarball 改 mtime 选取(修真 bug);DSH_CMD 默认值统一;package-registry.mjs 补 mermaid chunk;抽 scripts/e2e-common.sh 消除两 e2e 脚本约 40% 重复(函数级等价性探针 + 双 lane 真机验证) |
| #534 | feat/palette-single-source | One Dark/Light 语法色板单源化(one-dark-palette.ts),迁移前后映射机器证明逐字节相等 |
| #535 | feat/i18n-catalog-names | 目录项 name / shell 预设 desc 词典化(20 key × 21 词典文件,`string |
| #536 | feat/eslint | ESLint 10 flat config(typescript-eslint recommended + 经典 react-hooks 规则),存量 141 错误/21 警告清零(含 24 处真实死代码删除、_ 前缀 mock 约定入 config);pnpm lint / make lint / CI 三 job 全部接入;make check 同步含 lint |
| #540 | feat/drop-rc7-fallback | 删 rc.7 宿主 window.__DSH_MODULES__ 回退(peer 基线 rc.1 下不可达);测试 fixture 切换到与生产同路径;附带修复 main 上 #535/#536 语义合并冲突导致的 add-plugin-modal spec 断裂 |
| #541 | feat/unify-polling | use-polling.ts 原语(83 行)统一四处轮询习语(SubagentView 自排程 3s / SideChatView fixed 2s / GitLens fixed 2s / ChangesTab fixed 2.5s),守护 spec 断言零改动 |
| #542 | feat/split-sidebar | Sidebar.tsx 1831 → 1176 行,抽 src/client/sidebar/ 五模块(TabContent 74 / use-center-column 171 / use-host-feeds 269 / use-pinned-tabs 153 / free-windows 167);面板拖拽机约 330 行因 sidebar-layout-push.spec 的源码文本计数断言钉住而有意保留主文件 |
过程中同步发生的外部事件:DSH 0.1.2-rc.1 适配(PR #537)合入后,Wave 2 三个 PR 全部 rebase 到新 main 并重跑门禁再合并。
3. 过程中的重要发现(记录在案)
3.1 Windows agent-pty PTY 超时 flaky(既有,非本轮引入)
tests/agent-pty.spec.ts 的真实 PTY spawn 用例在 ci-windows 上间歇性 5s 超时。证据链:main@ceed6b2(Wave 1 首个合并的 push run)挂 agent-pty ×4 + git.spec ×1;#535、#536、#541 的 ci-windows 各挂过 1-2 个同类用例,重跑均绿;失败组合在多次运行间漂移。建议后续对该 describe 块在 win32 上提升 testTimeout 或加有界重试。
3.2 desktop-layout.e2e.ts 间歇 flaky(上游时序敏感)
该用例测「右面板保持桌面 session 头部位置」,区域与上游适配提交 ab6f960(toggle cluster 重定位动画)重叠。本机(钉版 rc.1 CLI)稳定因宿主 onboarding 浮层 / workspace 选择对话框不可达而失败,且 main 原样产物 A/B 对照同样失败;CI 上 aa01140 的 push run 也挂过一次(同内容分支 run 与后续 main 验证 run 均绿)。属宿主时序敏感的既有 flaky,建议上游动画稳定后加等待收敛。
3.3 跨分支语义合并冲突的流程教训
#535 新增了 builtinTabPlugins 的使用(依赖既有 import),#536 的 eslint 清理在其各自基线上把当时未使用的同名 import 删除——两个各自全绿的 PR 文本合并成功但语义断裂(typecheck TS2304 + spec 加载即挂),且被并发 run 取消掩盖后带病合入 main,由 Wave 3 两个子代理独立发现并热修(#540 8820efd)。教训:并行分支触碰同一文件时,每合入一个后其余分支需重验(rebase + typecheck/test),不能只信各自 PR 的绿勾;unused-import 类清理与功能分支并行时尤其如此。
3.4 GitHub push run 丢触发一例
#541 合并产生的 main push run(68839aa)从未被创建(workflows 均 active,按 SHA 查询 0 runs),经 workflow_dispatch 手动补跑三 job 全绿。原因不明,遇到「merge 后 main 无 push run」时可按此法补验。
4. 基础设施变化速查
- Makefile:
help(默认目标)/install/build/typecheck/lint/test/check(typecheck+build+test+consumer-types+lint 聚合)/clean/pack/mount/mount-aggregate/registry。package.json scripts 仍是唯一事实源,Makefile 只做薄封装与依赖链。 - Lint:
pnpm lint=eslint .(flat config,reportUnusedDisableDirectives: error);CI 三处(ci / ci-windows / release)在 Typecheck 后执行。 - 本地工具钉版:
packageManager: pnpm@11.8.0(CI workflow 的显式version:输入已移除,统一由该字段供版)。 - e2e 本地跑法:
make mount/make mount-aggregate;本机无 rc.1 CLI 时npm install --prefix /tmp/dsh-rc1-bin @deepseek-ai/dsh@0.1.2-rc.1后置 PATH。
5. Backlog(本次仅记录)
- mount.e2e 的固定
waitForTimeout与英文文案选择器([title="Files"]等)——宿主文案/语言变更即碎。 - CI 无 Playwright 浏览器缓存(每 run 重装 Chromium)。
state.spec(1498 行)/smoke.spec(1208)/service.spec(1124)三个千行 spec 拆分。- FreeWindow / TreePanel / split-pane / DiffPane / DiffRows 等组件缺直接渲染 spec(现靠 state 纯函数 spec + e2e 间接守护)。
- coverage 工具引入评估(当前零覆盖率度量)。
- CHANGELOG / CONTRIBUTING 文件(README「🆕 最近更新」小节手工充当 changelog)。
- Sidebar.tsx 剩余拖拽机(~330 行)拆分——前置条件是先重构
sidebar-layout-push.spec.tsx的源码文本计数断言为行为断言。 JobOutputPane的 2s 轮询未迁移use-polling(独立形状,见 #541 PR body)。- install.sh / install.ps1 / check-consumer-types.sh 内部的 say/warn/die 重复——install.sh 必须自包含随 npm 包分发,属有意设计,除非改分发方式否则不动。
- §3.1 / §3.2 两个 flaky 的根治。
6. 验证基线(全部 PR 合并后于 main 复核)
pnpm lint/pnpm typecheck/pnpm build/pnpm test:119 files / 1243 passed / 9 skipped。pnpm check:consumer-types通过。- 真机挂载 lane:mount 5/5、drag-layout 7/7、float-window 2/2、toggle-layout 1/1、perf 2/2(desktop-layout 见 §3.2)。
- aggregate 双挂载回归 lane 通过。