# 贡献指南 [文档索引](README.md) · [English](contributing.en.md) 感谢你考虑为 dsh-TUI 做贡献!本文档是 `dsh-cc-tui` 的共享开发契约,适用于 在本仓库工作的所有人与编码 Agent。 ## 如何贡献 - **报告 bug 或请求功能**:提交 issue,附上清晰的复现步骤与你使用的终端环境。 - **提交 PR**:base 指向 `main`。保持改动聚焦——一个 PR 只做一个逻辑改动, 标题用中文或中英对照,描述写清动机、改动点与验证方式。 - **请求 review 前先跑验证矩阵**:CI 运行的就是下面这些命令。 - 新功能应附带或扩展一个聚焦的回归脚本。 ## 范围(Scope) `dsh-cc-tui` 是单包、纯 ESM 的 TypeScript 项目:为 DeepSeek Harness 提供 React 终端 UI 前门(通过 Cordis 挂载)。包内拥有 TUI、本地命令面、打包技能 以及移植的 Ink/Yoga 渲染器;Agent、会话、模型、工具、持久化与策略域由 DeepSeek Harness 拥有,TUI 只消费它们。 做大改动前,先读 `package.json`、相关 README 章节和你将要编辑的每个源文件。 优先复用仓库现有的服务边界与辅助函数,而不是引入平行的抽象。 ## 仓库地图(Repository Map) - `src/index.ts`:公共 Cordis 插件入口、配置 Schema,与对运行时插件的惰性移交。 - `src/plugin.ts`:TTY 校验、服务注册、Agent 创建/恢复、React 树挂载,以及 终端/进程的收尾清理。 - `src/channel.ts`:事件到视图的投影 + 非 React 的动作面。把 DSH 会话事件 翻译成 transcript 行,实现 submit、steer、rewind、resume、模型/preset 切换、 本地报告及相关状态迁移。 - `src/screens/Chat.tsx`:顶层交互协调器。负责模态优先级、全局键盘、滚动/ 搜索/选区状态、slash 命令分发与聊天屏组装。 - `src/screens/StatusLine.tsx` 与 `src/screens/StatusMetrics.ts`:底部状态栏 呈现与指标推导。 - `src/components/`:功能组件。`components/design-system/` 是主题感知原语; `components/messages/` 是 transcript 行;`components/questions/` 是 `ask_user_question` 的 UI。 - `src/ui.ts`:本地渲染器、主题化 `Box`/`Text`、hooks 与公共 TUI 原语的 首选门面。 - `src/ink/`:移植的低层 Ink 渲染器与终端实现。**敏感基础设施**:改动要聚焦, 并附渲染器专用回归覆盖。 - `src/native-ts/yoga-layout/`:渲染器使用的移植布局引擎。 - `src/cc/`:为 Claude Code 风格 UI 适配的终端格式化与呈现辅助。 - `src/*Prefs.ts`、`src/customTheme.ts`、`src/sessionHistory.ts`:持久化的 用户偏好与 `~/.dsh-cc` 下的本地会话元数据。 - `skills/*/SKILL.md`:随 npm 包分发的技能,由 `src/packaged-skills.ts` 注册。 - `cordis.patch.yml`:profile 安装时使用的包级 bundle 覆盖层。行的顺序、行 ID、 被禁用的 host 行、insert/override 语义都很关键。 - `cordis.yml`:直接 Cordis/DSH 启动的完整裸组合示例。 - `scripts/`:无头回归、复现环境、探针与诊断。运行前先读脚本头部说明。 - `lib/types/`:`tsc` 的入库产物(JavaScript、声明与声明映射),由 `src/` 生成并随 npm 分发。 - `lib/invariant.js`:`./invariant` 的独立打包运行时导出;普通 `pnpm build` 不会重新生成它。 - `README.md` 与 `README_EN.md`:中英文用户文档。行为、配置、快捷键与限制 必须两版同步。 ## 运行时形态(Runtime Shape) 核心运行时链路: ```text Cordis config -> src/index.ts -> src/plugin.ts -> DSH agent/session services -> src/channel.ts (session events -> Channel snapshot) -> src/screens/Chat.tsx -> src/components/* -> src/ui.ts -> src/ink/* + Yoga layout -> terminal ANSI output ``` 职责归属在各层,不要越权: - Agent/会话/工具事实来自 DSH 服务与持久化会话事件。 - 投影与 TUI 动作属于 `channel.ts`,不属于呈现组件。 - 交互模式与按键优先级属于 `Chat.tsx` 或当前聚焦的模态/输入组件。 - 可复用的视觉行为属于 `components/` 与主题感知原语。 - 终端协议、布局、命中测试、选区与帧差分行为属于 `ink/`。 不要仅仅为了让某个界面更好写,就在 TUI 里重新实现 DSH 域服务。通过 channel 或既有注册表缝隙去适配服务。 ## 工具链(Toolchain) - 支持 Node `^22.19 || >=24`;CI 用 Node 24。 - CI 与发布用 pnpm 11;开发也请用 pnpm。 - 干净检出安装:`pnpm install --frozen-lockfile`。 - `pnpm-lock.yaml` 是 CI 锁文件。`package-lock.json` 为 npm 用户跟踪但当前 落后于包版本;不要把它当作依赖真源,也不要顺手改写。 - 有意改依赖时:更新 `pnpm-lock.yaml`,检查完整 lockfile diff,避免无关升级。 只有任务明确包含 npm-install 兼容性时才动 `package-lock.json`。 - `@deepseek-ai/cordis` 与 `@deepseek-ai/dsh-invariants` 同时是 peer 与 dev 依赖,便于本地类型检查;改版本时保持这两组声明兼容。 - 不要暴露、持久化或打印凭证。交互启动读取 `DEEPSEEK_API_KEY`;诊断可以 报告是否已设置,但绝不能泄露完整值。 ## 构建与生成产物(Build And Generated Files) 常规构建与类型检查关口:`pnpm build`(`tsc -p tsconfig.json`,把 `src/` 输出 到 `lib/types/`)。仓库提交这些产物,因为发布的包直接执行它们。 生成产物规则: - 改 `src/`,**绝不直接改 `lib/types/`**。 - 任何源码改动后运行 `pnpm build`,并提交对应的 `lib/types/` JavaScript、 `.d.ts` 与 `.d.ts.map` 变更。 - `tsc` 不清理 `outDir`。重命名或删除源模块后,检查 `lib/types/` 并只删除该 模块的过期输出。 - 审查生成的 diff。意外变化通常意味着编译器/配置或依赖的意外漂移。 - 纯文档、纯 workflow、纯 YAML 改动不需要重建(除非同时改了 TypeScript 输入)。 - `lib/invariant.js` 不由 `pnpm build` 生成。若 `src/invariant.ts` 或 `./invariant` 导出契约变化,显式保持打包文件与 `lib/types/invariant.d.ts` 对齐,并验证包导出。 `scripts/build.sh` 是面向本地 DeepSeek Harness 源码检出的备用构建器(定位 DSH 检出并重连依赖),不是本独立仓库的默认构建命令。 ## 验证(Verification) 仓库没有根级 `test` 或 `lint` 脚本;不要声称跑过它们。TypeScript 构建是通用 静态关口,随后是聚焦的可执行回归。 CI 在安装后运行: ```sh pnpm build node --import tsx/esm scripts/repro-askpanel.tsx node --import tsx/esm scripts/verify-askpanel-layout.tsx node --import tsx/esm scripts/repro-toolcards.tsx ``` 改动共享渲染、`Chat`、提示/问卷布局、工具卡、主题原语或 Ink core 时,三个 CI 回归都要跑。窄改动还要跑最近的聚焦脚本: | 改动区域 | 聚焦验证 | | --- | --- | | 通用无头屏幕组装 | `pnpm smoke` | | Channel submit/steer/pending 行为 | `node scripts/verify-submit.mjs` | | 提示队列行为 | `node scripts/verify-queue.mjs` | | Goal/todo 投影与渲染 | `node scripts/verify-channel-goal-todo.mjs` + `node scripts/verify-goal-todo.mjs` | | Compaction 与折叠 transcript 行 | `node scripts/verify-compact.mjs` | | 主题加载与持久化 | `node --import tsx/esm scripts/verify-themes.mjs` | | 滚动/粘底行为 | `node scripts/verify-scroll.mjs`、`node scripts/verify-resticky.mjs` 及对应 `repro-*` 环境 | | 全屏复制即选区 | `node scripts/verify-copy-on-select.mjs` | 多数用普通 `node` 调用的脚本 import `lib/types/`——先跑 `pnpm build`。import TypeScript 源的脚本在头部声明 `node --import tsx/esm