9.3 KiB
Phase 008 — 测试与 CI 收口 + harness 重写
| 项 | 值 |
|---|---|
| 目标 | harness:check 覆盖新结构;CI 全绿;删 reference_code/ 后仍自洽 |
| 前置 | Phase 007 通过 |
| 产出 | scripts/harness-check.mjs 重写完成,CI 五个检查项全过 |
| 参考 | docs/03-施工蓝图.md §10 |
0. 为什么要重写而不是删几行
现有 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.mdARCHITECTURE.mddocs/harness/README.mddocs/harness/validation.mddocs/harness/worktree-runbook.mddocs/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/<date>-<slug>.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 步骤
- 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. 验收
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)
# 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-uiimport,测试会红
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 通过后,项目达成:
- 无
ekko/hermes-web-ui字样(配置层白名单除外) - 无 Electron、无桌面端、无官网
- 无编程代理、无自有 Agent、无桌宠
- 聊天链路只走 Hermes 桥,协议未改
- Arco Design Vue 单 UI 库
- ArkScope 只做装饰位面
- i18n 只 zh + en
- CI 全绿
- 删掉
reference_code/后完全自洽
此时可以安全删除 reference_code/。
可选后续(不在本蓝图范围)
- 发布 npm 包,接通
update.ts在线更新 - ESP32 语音硬件(需从 reference 恢复
packages/esp32-c3) - 更多 locale 语言