Preserve concurrent edits during remote Hermes reinstall (#20631)

Hermes remote install only rewrites config.yaml when its content changed, so a stale snapshot can no longer overwrite a concurrent edit (matches local install).
This commit is contained in:
Sunhy
2026-10-24 17:00:33 -07:00
committed by GitHub
parent c580d7f2d3
commit 759e536e5f
2 changed files with 26 additions and 1 deletions
@@ -46,6 +46,29 @@ describe('Hermes remote installer through a local filesystem adapter (no SSH)',
expect(readFileSync(`${configPath}.bak`, 'utf8')).toBe('recovery point')
})
it('keeps edits made during an already-configured remote install', async () => {
writeFileSync(configPath, 'model: initial\n')
// Why: derive "already configured" from a real install so the fixture tracks managed-config changes.
await service.installRemote(createManagedHookLocalFilesystem(), directory)
rmSync(join(directory, '.hermes', 'plugins'), { recursive: true })
const updated = readFileSync(configPath, 'utf8').replace(
'model: initial',
'model: operator-edited'
)
expect(updated).toContain('model: operator-edited')
const filesystem = createManagedHookLocalFilesystem()
const rename = filesystem.ext_openssh_rename.bind(filesystem)
filesystem.ext_openssh_rename = (source, destination, callback) => {
if (destination === join(directory, '.hermes', 'plugins', 'orca-status', 'plugin.yaml')) {
writeFileSync(configPath, updated)
}
rename(source, destination, callback)
}
expect((await service.installRemote(filesystem, directory)).state).toBe('installed')
expect(readFileSync(configPath, 'utf8')).toBe(updated)
})
it.each(['\n', '\r\n'])(
'preserves comments and parsed values during real install (%j)',
async (eol) => {
+3 -1
View File
@@ -131,7 +131,9 @@ export class HermesHookService {
}
await writeTextFileRemoteAtomic(sftp, `${remotePluginDir}/plugin.yaml`, getPluginManifest())
await writeTextFileRemoteAtomic(sftp, `${remotePluginDir}/__init__.py`, getPluginInitSource())
await writeTextFileRemoteAtomic(sftp, remoteConfigPath, next.content)
if (next.content !== existing) {
await writeTextFileRemoteAtomic(sftp, remoteConfigPath, next.content)
}
return {
agent: 'hermes',
state: 'installed',