Phase 002: rebrand to hermes-ui and consolidate i18n to zh/en
Build / build (push) Canceled after 0s
NPM Lockfile Check / npm ci --ignore-scripts (push) Canceled after 0s
Playwright / e2e (push) Canceled after 0s

Removes the ekko / hermes-web-ui branding from the whole tree and drops
eight locale files, so the project presents one name and one language pair.

Data compatibility is deliberate, not accidental: DB filenames, the JWT
audience, and skill manifest ownership all still recognise their pre-rename
values so existing deployments under ~/.hermes-web-ui keep working without a
re-login or a re-injection.

scripts/harness-check.mjs now scans for the legacy strings and fails the
build on any new occurrence, with an explicit allow-list (and reasons) for
the compatibility paths that must keep them.
This commit is contained in:
2026-10-16 11:11:29 +08:00
parent 1e9ea89d86
commit c93e1fe1bd
70 changed files with 1305 additions and 17856 deletions
+10 -10
View File
@@ -129,7 +129,7 @@ describe('skills controller', () => {
})
it('lists configured external skill directories with external source while keeping local skills first', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-external-skills-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-external-skills-'))
const profileDir = join(root, 'profile')
const localSkillDir = join(profileDir, 'skills', 'tools', 'dupe-skill')
const externalDir = join(root, 'external-skills')
@@ -165,7 +165,7 @@ describe('skills controller', () => {
})
it('lists flat symlinked skills in the misc category', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-symlink-flat-skill-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-symlink-flat-skill-'))
const profileDir = join(root, 'profile')
const profileSkillsDir = join(profileDir, 'skills')
const sharedSkillDir = join(root, 'shared-skills', 'linked-flat-skill')
@@ -199,7 +199,7 @@ describe('skills controller', () => {
})
it('lists Codex user and system skills for the codex target', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-codex-skills-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-codex-skills-'))
const previousHome = process.env.HOME
const userSkillDir = join(root, '.agents', 'skills', 'user-skill')
const systemSkillDir = join(root, '.codex', 'skills', '.system', 'system-skill')
@@ -234,7 +234,7 @@ describe('skills controller', () => {
})
it('reads Codex system skill details for the codex target', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-codex-system-skill-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-codex-system-skill-'))
const previousHome = process.env.HOME
const systemSkillDir = join(root, '.codex', 'skills', '.system', 'imagegen')
@@ -278,7 +278,7 @@ describe('skills controller', () => {
})
it('traverses symlinked category entries without following hidden or cyclic links', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-symlink-category-skill-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-symlink-category-skill-'))
const profileDir = join(root, 'profile')
const toolsDir = join(profileDir, 'skills', 'tools')
const linkedSkillDir = join(root, 'shared-skills', 'linked-skill')
@@ -337,7 +337,7 @@ describe('skills controller', () => {
})
it('imports skills into the request-scoped profile directory', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-import-profile-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-import-profile-'))
const defaultProfileDir = join(root, 'default')
const researchProfileDir = join(root, 'research')
mockGetProfileDir.mockImplementation((profile: string) => profile === 'research' ? researchProfileDir : defaultProfileDir)
@@ -385,7 +385,7 @@ describe('skills controller', () => {
})
it('imports skills with valid encoded multipart filenames', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-import-encoded-filename-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-import-encoded-filename-'))
const profileDir = join(root, 'research')
mockGetProfileDir.mockReturnValue(profileDir)
@@ -412,7 +412,7 @@ describe('skills controller', () => {
})
it('deletes local skills only from the request-scoped profile directory', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-delete-profile-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-delete-profile-'))
const defaultProfileDir = join(root, 'default')
const researchProfileDir = join(root, 'research')
const defaultSkillDir = join(defaultProfileDir, 'skills', 'tools', 'dupe-skill')
@@ -443,7 +443,7 @@ describe('skills controller', () => {
})
it('updates local skill content in the request-scoped profile directory', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-update-skill-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-update-skill-'))
const defaultProfileDir = join(root, 'default')
const researchProfileDir = join(root, 'research')
const defaultSkillDir = join(defaultProfileDir, 'skills', 'tools', 'dupe-skill')
@@ -476,7 +476,7 @@ describe('skills controller', () => {
})
it('updates Codex user skills but not Codex system skills', async () => {
const root = await mkdtemp(join(tmpdir(), 'hermes-web-ui-update-codex-skill-'))
const root = await mkdtemp(join(tmpdir(), 'hermes-ui-update-codex-skill-'))
const previousHome = process.env.HOME
const userSkillDir = join(root, '.agents', 'skills', 'user-skill')
const systemSkillDir = join(root, '.codex', 'skills', '.system', 'system-skill')