# Phase 008 — 测试与 CI 收口 + harness 重写 | 项 | 值 | |---|---| | 目标 | `harness:check` 覆盖新结构;CI 全绿;删 `reference_code/` 后仍自洽 | | 前置 | Phase 007 通过 | | 产出 | `scripts/harness-check.mjs` 重写完成,CI 五个检查项全过 | | 参考 | `docs/03-施工蓝图.md` §10 | --- ## 0. 为什么要重写而不是删几行 现有 [harness-check.mjs](file:///Users/jack/source/OtherProjectTemp/ekko-studio/scripts/harness-check.mjs) 有 **170+ 行在断言 desktop / website 的产物与文案**: - `desktop-release.yml` 的 dmg / exe / AppImage / nsis 产物名 - `installer.nsh` 的 `Stop-Process` 片段 - updater 的 `download.ekkolearnai.com` - `packages/desktop/build/icons/` 的 11 个图标文件名 - website 的 `docs/` 静态站路径 **Phase 001 已删掉这些包,这些断言全部失效。逐行删会漏,且失去对新结构的保护。整体重写。** --- ## 1. 功能任务 1 — 新 harness 的校验项 新建 `scripts/harness-check.mjs`,覆盖以下 9 项: ### 1.1 必需文件存在 ``` AGENTS.md ARCHITECTURE.md DEVELOPMENT.md README.md package.json vite.config.ts vitest.config.ts playwright.config.ts tsconfig.json docs/harness/README.md docs/harness/validation.md docs/harness/worktree-runbook.md docs/harness/pr-review.md ``` ### 1.2 必需目录存在 ``` packages/client/src packages/server/src packages/skills tests/client tests/server tests/shared tests/e2e .github/workflows ``` ### 1.3 **禁止目录不存在**(防回流,Phase 001 已有对应配置) ``` packages/desktop packages/website packages/ekko-agent packages/esp32-c3 reference_code ← 项目完成前允许存在,见 §5 ``` > `reference_code` 这一条**先不加**。等 Phase 009 确认项目完全自洽后再加,避免中途误红。 ### 1.4 `AGENTS.md` 约束 - 行数 ≤ 120 - 链接到 `DEVELOPMENT.md` `ARCHITECTURE.md` `docs/harness/README.md` `docs/harness/validation.md` `docs/harness/worktree-runbook.md` `docs/harness/pr-review.md` - 6 条 Hard Rules 齐全(路由薄 / Web UI 状态隔离 / Hermes 状态隔离 / 本地路由先于代理 / 结构化 API / 双 locale) - 提及 `packages/skills` ### 1.5 `package.json` 脚本齐全 必须含:`harness:check` `test` `test:coverage` `test:e2e` `build` 必须**不含**:`desktop:*` `build:desktop*` `dev:website` `build:website` ### 1.6 `ARCHITECTURE.md` 数据归属 必须含 `HERMES_WEB_UI_HOME`(这是有意保留的旧标识,需要在文档里写明原因)。 ### 1.7 **禁止字符串扫描**(Phase 002 已建测试,harness 里做静态版) 扫 `packages/` `tests/` `scripts/` `bin/`: ``` 'ekko'(大小写不敏感) 'hermes-web-ui' 'hermes-studio' ``` **白名单**(允许出现,需在代码里显式注释原因): ``` HERMES_WEB_UI_* 环境变量名 HERMES_WEBUI_STATE_DIR 环境变量名 hermes_brightness localStorage key hermes_style localStorage key hermes_locale localStorage key config.ts 里的 ~/.hermes-web-ui 默认数据目录名 ``` > `config.ts` 的默认数据目录名是**刻意保留**的旧标识(避免破坏已有数据目录)。白名单里写清楚。 ### 1.8 **禁止第二 UI 库**(Phase 007 已有 `no-naive-ui.test.ts`,harness 做静态版) `package.json` 的 `dependencies` / `devDependencies` 里: ``` 只能有 @arco-design/web-vue 不能有 naive-ui / element-plus / ant-design-vue / primevue / vuetify / quasar ``` ### 1.9 Chat 链路变更片段规则 保留旧版机制(`docs/chat-chain-changes/`),但清单去掉已砍的部分。 **变更以下文件时,必须附一个 `docs/chat-chain-changes/-.md`**: ``` packages/server/src/services/hermes/run-chat/** packages/server/src/services/hermes/agent-bridge/**(含 python/) packages/server/src/services/hermes/group-chat/** packages/server/src/services/hermes/context-engine/** packages/server/src/lib/context-compressor/** packages/client/src/stores/hermes/chat.ts packages/client/src/stores/hermes/group-chat.ts ``` > **已砍掉**:`services/agent-runner/**`(Phase 003)、`services/coding-agents.ts`、`services/ekko-agent/**` —— 不再需要片段。 CI 里 `actions/checkout` 必须带 `fetch-depth: 0`,否则 `git diff` 检测失效。 --- ## 2. 功能任务 2 — CI workflow ### 2.1 保留的 5 个 ``` build.yml playwright.yml npm-lockfile-check.yml docker-publish.yml webui-release.yml ``` ### 2.2 `build.yml` 步骤 ```yaml - uses: actions/checkout@v4 with: fetch-depth: 0 # 必须,harness:check 依赖 git diff - run: npm ci --ignore-scripts - run: npm run harness:check - run: npm run test:coverage - run: npm run test:e2e - run: npm run build ``` ### 2.3 `playwright.yml` 保留,但要确认 mock 后端服务启动脚本里没有引用已删的 API。 ### 2.4 `webui-release.yml` Phase 002 已去品牌。确认打包产物名是 `hermes-ui`。 若你**不打算发布**,这个 workflow 可以删。发布与否决定 `controllers/update.ts` 的在线更新是否可用(见 Phase 002 §2.3)。 --- ## 3. 功能任务 3 — 测试补强清单 已有机制(Phase 002 / 007 建立): | 测试 | 作用 | |---|---| | `tests/server/no-legacy-brand.test.ts` | 旧品牌扫描 | | `tests/client/no-naive-ui.test.ts` | UI 库防回流 | | `tests/client/i18n-coverage.test.ts` | zh/en key 一致性 | | `tests/client/arkscope-vendor.test.ts` | vendor 边界 | | `tests/client/message-item-arko.test.ts` | 气泡内禁 Arco | 本 Phase 建议再加 3 个: ### 3.1 `tests/client/i18n-parity.test.ts` `zh.ts` 与 `en.ts` 的 key 集合必须完全一致(`i18n-coverage.test.ts` 已覆盖大部分,此处补 `zh` 与 `en` 互相的完整对等检查)。 ### 3.2 `tests/server/hermes-db-readonly.test.ts` **红线机械化**:断言 server 源码中没有任何地方直接 `open()` / `new Database()` hermes 的 `state.db`。 扫描 `packages/server/src/` 下对 `state.db` 的引用,每一处都必须在白名单(如注释、文档字符串)里。 ### 3.3 `tests/server/no-desktop-reference.test.ts` 断言 `packages/` 里没有 `HERMES_DESKTOP`(**除 `agent-bridge/python/bridge_runtime.py`**)。 那个文件里的判断是 Windows 隐藏控制台窗口用的(见 Phase 004 §6),必须豁免。 --- ## 4. 功能任务 4 — 文档收口 | 文件 | 收口内容 | |---|---| | `AGENTS.md` | 补一条:**`agent-bridge/python/` 是只读 vendored 代码**;**hermes `state.db` 只读** | | `ARCHITECTURE.md` | 补数据归属图:我们的 SQLite 唯一可写 vs hermes state.db 只读;profile 隔离靠注入 `HERMES_HOME` | | `DEVELOPMENT.md` | 加「首次安装」章节:装 Python + `pip install hermes-agent`,或设 `HERMES_BIN`(因为已无桌面端捆绑) | | `README.md` / `README_zh.md` | 同上,安装步骤放最前面 | | `docs/harness/validation.md` | 更新为新结构(Phase 001 拷的是旧版,含 desktop 内容) | | `docs/harness/pr-review.md` | 检查是否引用已砍功能 | | `docs/harness/worktree-runbook.md` | 检查是否引用 `packages/desktop` 路径 | **这 4 个 harness 文档是 Phase 001 从 reference 拷的,里面大概率有 desktop 内容。逐个检查。** --- ## 5. 验收 ```bash cd /Users/jack/source/MyProject/js/hermes-ui npm run harness:check npm run test:coverage npm run test:e2e npm run build ``` ### 5.1 自洽性验证(**模拟最终删 reference_code**) ```bash # 1. 确认无引用 grep -rn "reference_code" . \ --include="*.ts" --include="*.vue" --include="*.json" \ --include="*.mjs" --include="*.yml" --include="Dockerfile*" \ | grep -v "^./docs/phases/" # 期望:零命中 # 2. 临时移走,验证完全自洽 mv reference_code /tmp/hermes-ui-reference-backup npm ci --ignore-scripts npm run build npm run test npm run harness:check # 全部通过 mv /tmp/hermes-ui-reference-backup reference_code ``` **这一步通过,才允许删除 `reference_code/`。** ### 5.2 手工 - [ ] `npm run harness:check` 在故意破坏时能报错(删一个必需文件试试) - [ ] 往代码里加一处 `ekko` 字样,扫描会红 - [ ] 往代码里加一处 `naive-ui` import,测试会红 --- ## 6. 风险 | # | 风险 | 缓解 | |---|---|---| | P8-1 | harness 重写漏项,CI 变弱 | §5.2 手工验证三个场景都能报红 | | P8-2 | harness 白名单被后续误加,扫描形同虚设 | 白名单每项必须带注释写明原因,review 时盯 | | P8-3 | `docs/harness/*.md` 里的 desktop 内容没改,误导后续 | §4 逐个检查 | | P8-4 | `fetch-depth: 0` 丢失,链路变更检测静默失效 | build.yml 显式写,harness 也检查这条 | | P8-5 | `no-desktop-reference.test.ts` 误伤 python 文件 | 显式豁免路径 + 注释说明原因 | --- ## 7. 项目完成 Phase 008 通过后,项目达成: - [x] 无 `ekko` / `hermes-web-ui` 字样(配置层白名单除外) - [x] 无 Electron、无桌面端、无官网 - [x] 无编程代理、无自有 Agent、无桌宠 - [x] 聊天链路只走 Hermes 桥,协议未改 - [x] Arco Design Vue 单 UI 库 - [x] ArkScope 只做装饰位面 - [x] i18n 只 zh + en - [x] CI 全绿 - [x] **删掉 `reference_code/` 后完全自洽** **此时可以安全删除 `reference_code/`。** ### 可选后续(不在本蓝图范围) - 发布 npm 包,接通 `update.ts` 在线更新 - ESP32 语音硬件(需从 reference 恢复 `packages/esp32-c3`) - 更多 locale 语言